From f087b150c992ec0c54615143de3018ec7f75329f Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Thu, 25 Jan 2018 15:50:57 -0500 Subject: [PATCH 1/2] Add quick menu option to watch shader files for changes and recompile automatically (Linux only for now) --- CHANGES.md | 1 + config.def.h | 3 + configuration.c | 1 + configuration.h | 1 + frontend/drivers/platform_ctr.c | 2 + frontend/drivers/platform_dos.c | 2 + frontend/drivers/platform_emscripten.c | 2 + frontend/drivers/platform_gx.c | 2 + frontend/drivers/platform_null.c | 2 + frontend/drivers/platform_ps3.c | 2 + frontend/drivers/platform_psp.c | 2 + frontend/drivers/platform_qnx.c | 2 + frontend/drivers/platform_unix.c | 210 ++++++++++++++++++++++++- frontend/drivers/platform_wiiu.c | 2 + frontend/drivers/platform_win32.c | 2 + frontend/drivers/platform_xdk.c | 2 + frontend/drivers/platform_xenon.c | 2 + frontend/frontend_driver.c | 25 +++ frontend/frontend_driver.h | 20 +++ gfx/video_driver.c | 1 - gfx/video_shader_parse.c | 38 +++++ gfx/video_shader_parse.h | 2 + intl/msg_hash_chs.h | 4 - intl/msg_hash_cht.h | 4 - intl/msg_hash_de.h | 4 - intl/msg_hash_eo.h | 4 - intl/msg_hash_es.h | 6 +- intl/msg_hash_fr.h | 4 - intl/msg_hash_it.h | 4 - intl/msg_hash_ja.h | 10 +- intl/msg_hash_ko.h | 4 - intl/msg_hash_lbl.h | 4 +- intl/msg_hash_nl.h | 4 - intl/msg_hash_pl.h | 4 - intl/msg_hash_pt_br.h | 4 - intl/msg_hash_pt_pt.h | 4 - intl/msg_hash_ru.h | 4 - intl/msg_hash_us.c | 9 ++ intl/msg_hash_us.h | 8 +- intl/msg_hash_vn.h | 4 - menu/cbs/menu_cbs_get_value.c | 28 ++++ menu/cbs/menu_cbs_left.c | 11 ++ menu/cbs/menu_cbs_right.c | 11 ++ menu/cbs/menu_cbs_start.c | 12 ++ menu/cbs/menu_cbs_sublabel.c | 4 + menu/menu_displaylist.c | 13 +- msg_hash.h | 2 +- retroarch.c | 6 + retroarch.cfg | 3 + 49 files changed, 428 insertions(+), 77 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ded565ab73..79946c5fe6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ - COMMON: Bugfix for issue related to 'Windows mouse pointer visible when running MESS or MAME cores'. - COMMON: Fix bug 'Last item in a Playlist is ignored'. - COMMON: New LED API. Driver implemented for Raspberry Pi, proof of concept implemented for core MAME 2003. +- COMMON: Add quick menu option to watch shader files for changes and recompile them automatically (Linux only for now). - D3D8: Direct3D 8 can now work on systems that have Direct3D 8 installed. - D3D9: Add menu support for MaterialUI/XMB. - D3D10: Initial video driver implementation. diff --git a/config.def.h b/config.def.h index 1d2cc4f085..529b282ffa 100644 --- a/config.def.h +++ b/config.def.h @@ -404,6 +404,9 @@ static const bool post_filter_record = false; /* Screenshots post-shaded GPU output if available. */ static const bool gpu_screenshot = true; +/* Watch shader files for changes and auto-apply as necessary. */ +static const bool video_shader_watch_files = false; + /* Screenshots named automatically. */ static const bool auto_screenshot_filename = true; diff --git a/configuration.c b/configuration.c index 5a7c973a6c..3a5ec036ad 100644 --- a/configuration.c +++ b/configuration.c @@ -1211,6 +1211,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("rewind_enable", &settings->bools.rewind_enable, true, rewind_enable, false); SETTING_BOOL("audio_sync", &settings->bools.audio_sync, true, audio_sync, false); SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, shader_enable, false); + SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, video_shader_watch_files, false); /* Let implementation decide if automatic, or 1:1 PAR. */ SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, aspect_ratio_auto, false); diff --git a/configuration.h b/configuration.h index 656ceb4758..21c7b75e99 100644 --- a/configuration.h +++ b/configuration.h @@ -81,6 +81,7 @@ typedef struct settings bool video_aspect_ratio_auto; bool video_scale_integer; bool video_shader_enable; + bool video_shader_watch_files; bool video_threaded; bool video_font_enable; bool video_disable_composition; diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c index 529580d5ab..8f376c97fe 100644 --- a/frontend/drivers/platform_ctr.c +++ b/frontend/drivers/platform_ctr.c @@ -558,5 +558,7 @@ frontend_ctx_driver_t frontend_ctx_ctr = { NULL, /* destroy_signal_handler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "ctr", }; diff --git a/frontend/drivers/platform_dos.c b/frontend/drivers/platform_dos.c index e7c0af7e14..b8974439ce 100644 --- a/frontend/drivers/platform_dos.c +++ b/frontend/drivers/platform_dos.c @@ -68,5 +68,7 @@ frontend_ctx_driver_t frontend_ctx_dos = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "dos", }; diff --git a/frontend/drivers/platform_emscripten.c b/frontend/drivers/platform_emscripten.c index 72b28f027e..121e3c09ba 100644 --- a/frontend/drivers/platform_emscripten.c +++ b/frontend/drivers/platform_emscripten.c @@ -260,5 +260,7 @@ frontend_ctx_driver_t frontend_ctx_emscripten = { NULL, /* destroy_signal_handler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "emscripten" }; diff --git a/frontend/drivers/platform_gx.c b/frontend/drivers/platform_gx.c index 9de04586cb..ba480c3af3 100644 --- a/frontend/drivers/platform_gx.c +++ b/frontend/drivers/platform_gx.c @@ -559,5 +559,7 @@ frontend_ctx_driver_t frontend_ctx_gx = { NULL, /* destroy_signal_handler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "gx", }; diff --git a/frontend/drivers/platform_null.c b/frontend/drivers/platform_null.c index 0f5e76d6ea..5b98c84bb3 100644 --- a/frontend/drivers/platform_null.c +++ b/frontend/drivers/platform_null.c @@ -44,5 +44,7 @@ frontend_ctx_driver_t frontend_ctx_null = { #ifdef HAVE_LAKKA NULL, /* get_lakka_version */ #endif + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "null", }; diff --git a/frontend/drivers/platform_ps3.c b/frontend/drivers/platform_ps3.c index ffb573c4ab..1ec907c417 100644 --- a/frontend/drivers/platform_ps3.c +++ b/frontend/drivers/platform_ps3.c @@ -632,5 +632,7 @@ frontend_ctx_driver_t frontend_ctx_ps3 = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "ps3", }; diff --git a/frontend/drivers/platform_psp.c b/frontend/drivers/platform_psp.c index 9b61c2ca62..6a08c0bc0e 100644 --- a/frontend/drivers/platform_psp.c +++ b/frontend/drivers/platform_psp.c @@ -518,6 +518,8 @@ frontend_ctx_driver_t frontend_ctx_psp = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ #ifdef VITA "vita", #else diff --git a/frontend/drivers/platform_qnx.c b/frontend/drivers/platform_qnx.c index e1497b3b57..0b3af7895b 100644 --- a/frontend/drivers/platform_qnx.c +++ b/frontend/drivers/platform_qnx.c @@ -198,5 +198,7 @@ frontend_ctx_driver_t frontend_ctx_qnx = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "qnx", }; diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c index 7a323d1c5a..daee38d2a3 100644 --- a/frontend/drivers/platform_unix.c +++ b/frontend/drivers/platform_unix.c @@ -27,6 +27,24 @@ #include #include +#ifdef __linux__ +#include +/* inotify API was added in 2.6.13 */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) +#define HAS_INOTIFY +#define INOTIFY_BUF_LEN (1024 * (sizeof(struct inotify_event) + 16)) + +#include +#include + +#define VECTOR_LIST_TYPE int +#define VECTOR_LIST_NAME int +#include "../../libretro-common/lists/vector_list.c" +#undef VECTOR_LIST_TYPE +#undef VECTOR_LIST_NAME +#endif +#endif + #include #include @@ -45,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +100,6 @@ enum struct android_app *g_android; - static pthread_key_t thread_key; static char screenshot_dir[PATH_MAX_LENGTH]; @@ -104,6 +122,17 @@ static volatile sig_atomic_t unix_sighandler_quit; static enum frontend_fork unix_fork_mode = FRONTEND_FORK_NONE; #endif +#ifdef HAS_INOTIFY +typedef struct inotify_data +{ + int fd; + int flags; + struct int_vector_list *wd_list; + struct string_list *path_list; +} inotify_data_t; + +#endif + int system_property_get(const char *command, const char *args, char *value) { @@ -2223,6 +2252,183 @@ static void frontend_unix_destroy_signal_handler_state(void) unix_sighandler_quit = 0; } +/* To free change_data, call the function again with a NULL string_list while providing change_data again */ +static void frontend_unix_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data) +{ +#ifdef HAS_INOTIFY + int major = 0; + int minor = 0; + int inotify_mask = 0, fd = 0; + unsigned i, krel = 0; + struct utsname buffer; + inotify_data_t *inotify_data; + + if (!list) + { + if (change_data && *change_data) + { + /* free the original data */ + inotify_data = (inotify_data_t*)((*change_data)->data); + + if (inotify_data->wd_list->count > 0) + { + for (i = 0; i < inotify_data->wd_list->count; i++) + { + inotify_rm_watch(inotify_data->fd, inotify_data->wd_list->data[i]); + } + } + + int_vector_list_free(inotify_data->wd_list); + string_list_free(inotify_data->path_list); + close(inotify_data->fd); + free(inotify_data); + free(*change_data); + return; + } + } + else if (list->size == 0) + return; + else + if (!change_data) + return; + + if (uname(&buffer) != 0) + { + RARCH_WARN("watch_path_for_changes: Failed to get current kernel version.\n"); + return; + } + + /* get_os doesn't provide all three */ + sscanf(buffer.release, "%d.%d.%u", &major, &minor, &krel); + + /* check if we are actually running on a high enough kernel version as well */ + if (major < 2) + { + RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel); + return; + } + else if (major == 2) + { + if (minor < 6) + { + RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel); + return; + } + else if (minor == 6) + { + if (krel < 13) + { + RARCH_WARN("watch_path_for_changes: inotify unsupported on this kernel version (%d.%d.%u).\n", major, minor, krel); + return; + } + else + { + /* anything >= 2.6.13 is supported */ + } + } + else + { + /* anything >= 2.7 is supported */ + } + } + else + { + /* anything >= 3 is supported */ + } + + fd = inotify_init(); + + if (fd < 0) + { + RARCH_WARN("watch_path_for_changes: Could not initialize inotify.\n"); + return; + } + + socket_nonblock(fd); + + inotify_data = (inotify_data_t*)calloc(1, sizeof(*inotify_data)); + inotify_data->fd = fd; + + inotify_data->wd_list = int_vector_list_new(); + inotify_data->path_list = string_list_new(); + + /* handle other flags here as new ones are added */ + if (flags & PATH_CHANGE_TYPE_MODIFIED) + inotify_mask |= IN_MODIFY; + if (flags & PATH_CHANGE_TYPE_WRITE_FILE_CLOSED) + inotify_mask |= IN_CLOSE_WRITE; + + inotify_data->flags = inotify_mask; + + for (i = 0; i < list->size; i++) + { + int wd = inotify_add_watch(fd, list->elems[i].data, inotify_mask); + union string_list_elem_attr attr = {0}; + + RARCH_LOG("Watching file for changes: %s\n", list->elems[i].data); + + int_vector_list_append(inotify_data->wd_list, wd); + string_list_append(inotify_data->path_list, list->elems[i].data, attr); + } + + *change_data = (path_change_data_t*)calloc(1, sizeof(path_change_data_t)); + (*change_data)->data = inotify_data; +#endif +} + +static bool frontend_unix_check_for_path_changes(path_change_data_t *change_data) +{ +#ifdef HAS_INOTIFY + inotify_data_t *inotify_data = (inotify_data_t*)(change_data->data); + char buffer[INOTIFY_BUF_LEN] = {0}; + int length, i = 0; + + while ((length = read(inotify_data->fd, buffer, INOTIFY_BUF_LEN)) > 0) + { + i = 0; + + while (i < length) + { + struct inotify_event *event = (struct inotify_event *)&buffer[i]; + + if (event->mask & inotify_data->flags) + { + unsigned j; + + /* A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a file system to flush the buffers when the stream is closed. + * So we manually fsync() here to flush the data to disk, to make sure that the new data is immediately available when the file is re-read. + */ + for (j = 0; j < inotify_data->wd_list->count; j++) + { + if (inotify_data->wd_list->data[j] == event->wd) + { + /* found the right file, now sync it */ + const char *path = inotify_data->path_list->elems[j].data; + FILE *fp = fopen_utf8(path, "rb"); + + RARCH_LOG("file change detected: %s\n", path); + + if (fp) + { + fsync(fileno(fp)); + fclose(fp); + } + } + } + + return true; + } + + i += sizeof(struct inotify_event) + event->len; + } + } + + return false; +#else + return false; +#endif +} + frontend_ctx_driver_t frontend_ctx_unix = { frontend_unix_get_env, /* environment_get */ frontend_unix_init, /* init */ @@ -2264,6 +2470,8 @@ frontend_ctx_driver_t frontend_ctx_unix = { #ifdef HAVE_LAKKA frontend_unix_get_lakka_version, /* get_lakka_version */ #endif + frontend_unix_watch_path_for_changes, + frontend_unix_check_for_path_changes, #ifdef ANDROID "android" #else diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index 8107f8c0d9..a7382bbfed 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -305,6 +305,8 @@ frontend_ctx_driver_t frontend_ctx_wiiu = NULL, /* destroy_signal_handler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "wiiu", NULL, /* get_video_driver */ }; diff --git a/frontend/drivers/platform_win32.c b/frontend/drivers/platform_win32.c index b754a7bc8c..b0dec9dd78 100644 --- a/frontend/drivers/platform_win32.c +++ b/frontend/drivers/platform_win32.c @@ -584,5 +584,7 @@ frontend_ctx_driver_t frontend_ctx_win32 = { NULL, /* destroy_sighandler_state */ frontend_win32_attach_console, /* attach_console */ frontend_win32_detach_console, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "win32" }; diff --git a/frontend/drivers/platform_xdk.c b/frontend/drivers/platform_xdk.c index 2f623e10db..81991276e6 100644 --- a/frontend/drivers/platform_xdk.c +++ b/frontend/drivers/platform_xdk.c @@ -1444,5 +1444,7 @@ frontend_ctx_driver_t frontend_ctx_xdk = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "xdk", }; diff --git a/frontend/drivers/platform_xenon.c b/frontend/drivers/platform_xenon.c index b1e84bf443..26e14463a3 100644 --- a/frontend/drivers/platform_xenon.c +++ b/frontend/drivers/platform_xenon.c @@ -91,5 +91,7 @@ frontend_ctx_driver_t frontend_ctx_qnx = { NULL, /* destroy_sighandler_state */ NULL, /* attach_console */ NULL, /* detach_console */ + NULL, /* watch_path_for_changes */ + NULL, /* check_for_path_changes */ "xenon", }; diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c index 6ec6918999..83e4da8a64 100644 --- a/frontend/frontend_driver.c +++ b/frontend/frontend_driver.c @@ -384,4 +384,29 @@ void frontend_driver_destroy_signal_handler_state(void) return; frontend->destroy_signal_handler_state(); } + +bool frontend_driver_can_watch_for_changes(void) +{ + frontend_ctx_driver_t *frontend = frontend_get_ptr(); + if (!frontend || !frontend->watch_path_for_changes) + return false; + return true; +} + +void frontend_driver_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data) +{ + frontend_ctx_driver_t *frontend = frontend_get_ptr(); + if (!frontend || !frontend->watch_path_for_changes) + return; + frontend->watch_path_for_changes(list, flags, change_data); +} + +bool frontend_driver_check_for_path_changes(path_change_data_t *change_data) +{ + frontend_ctx_driver_t *frontend = frontend_get_ptr(); + if (!frontend || !frontend->check_for_path_changes) + return false; + return frontend->check_for_path_changes(change_data); +} + #endif diff --git a/frontend/frontend_driver.h b/frontend/frontend_driver.h index 0f90d5aafb..8e3fe089bf 100644 --- a/frontend/frontend_driver.h +++ b/frontend/frontend_driver.h @@ -22,6 +22,7 @@ #include #include +#include RETRO_BEGIN_DECLS @@ -55,6 +56,17 @@ enum frontend_architecture FRONTEND_ARCH_TILE }; +enum path_change_type +{ + PATH_CHANGE_TYPE_MODIFIED = (1 << 0), + PATH_CHANGE_TYPE_WRITE_FILE_CLOSED = (1 << 1) +}; + +typedef struct path_change_data +{ + void *data; +} path_change_data_t; + typedef void (*environment_get_t)(int *argc, char *argv[], void *args, void *params_data); typedef void (*process_args_t)(int *argc, char *argv[]); @@ -88,6 +100,8 @@ typedef struct frontend_ctx_driver #ifdef HAVE_LAKKA void (*get_lakka_version)(char *, size_t); #endif + void (*watch_path_for_changes)(struct string_list *list, int flags, path_change_data_t **change_data); + bool (*check_for_path_changes)(path_change_data_t *change_data); const char *ident; @@ -180,6 +194,12 @@ void frontend_driver_attach_console(void); void frontend_driver_detach_console(void); +bool frontend_driver_can_watch_for_changes(void); + +void frontend_driver_watch_path_for_changes(struct string_list *list, int flags, path_change_data_t **change_data); + +bool frontend_driver_check_for_path_changes(path_change_data_t *change_data); + RETRO_END_DECLS #endif diff --git a/gfx/video_driver.c b/gfx/video_driver.c index e9c4d1fc0f..1d1998dff0 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3332,7 +3332,6 @@ static struct video_shader *video_shader_driver_get_current_shader_null(void *da return NULL; } - static void video_shader_driver_set_params_null(void *data, void *shader_data, unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index d993b84a5f..6313cdacbc 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -27,9 +27,12 @@ #include #include #include +#include #include "../msg_hash.h" #include "../verbosity.h" +#include "../configuration.h" +#include "../frontend/frontend_driver.h" #include "video_shader_parse.h" #ifdef HAVE_SLANG @@ -53,6 +56,8 @@ #define SEMANTIC_TRANSITION_COUNT 0x3ef2af78U #define SEMANTIC_PYTHON 0x15efc547U +static path_change_data_t *file_change_data = NULL; + /** * wrap_mode_to_str: * @type : Wrap type. @@ -755,6 +760,11 @@ bool video_shader_read_conf_cgp(config_file_t *conf, { unsigned i; unsigned shaders = 0; + settings_t *settings = config_get_ptr(); + struct string_list *file_list = NULL; + union string_list_elem_attr attr = {0}; + + (void)file_list; memset(shader, 0, sizeof(*shader)); shader->type = RARCH_SHADER_CG; @@ -776,10 +786,31 @@ bool video_shader_read_conf_cgp(config_file_t *conf, shader->passes = MIN(shaders, GFX_MAX_SHADERS); + if (settings->bools.video_shader_watch_files) + { + if (file_change_data) + frontend_driver_watch_path_for_changes(NULL, 0, &file_change_data); + + file_change_data = NULL; + file_list = string_list_new(); + string_list_append(file_list, conf->path, attr); + } + for (i = 0; i < shader->passes; i++) { if (!video_shader_parse_pass(conf, &shader->pass[i], i)) return false; + + if (settings->bools.video_shader_watch_files) + { + string_list_append(file_list, shader->pass[i].source.path, attr); + } + } + + if (settings->bools.video_shader_watch_files) + { + frontend_driver_watch_path_for_changes(file_list, PATH_CHANGE_TYPE_WRITE_FILE_CLOSED, &file_change_data); + string_list_free(file_list); } if (!video_shader_parse_textures(conf, shader)) @@ -1198,3 +1229,10 @@ void video_shader_resolve_relative(struct video_shader *shader, free(tmp_path); } +bool video_shader_check_for_changes(void) +{ + if (!file_change_data) + return false; + + return frontend_driver_check_for_path_changes(file_change_data); +} diff --git a/gfx/video_shader_parse.h b/gfx/video_shader_parse.h index ba1cd2f0a4..fcffeb428b 100644 --- a/gfx/video_shader_parse.h +++ b/gfx/video_shader_parse.h @@ -231,6 +231,8 @@ bool video_shader_resolve_parameters(config_file_t *conf, enum rarch_shader_type video_shader_parse_type(const char *path, enum rarch_shader_type fallback); +bool video_shader_check_for_changes(void); + RETRO_END_DECLS #endif diff --git a/intl/msg_hash_chs.h b/intl/msg_hash_chs.h index 77fe82c0fb..e6a0cdf061 100644 --- a/intl/msg_hash_chs.h +++ b/intl/msg_hash_chs.h @@ -3205,7 +3205,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_cht.h b/intl/msg_hash_cht.h index 8862de00a9..2644f450a8 100644 --- a/intl/msg_hash_cht.h +++ b/intl/msg_hash_cht.h @@ -3199,7 +3199,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_de.h b/intl/msg_hash_de.h index 08d8d369a5..3140125ee4 100644 --- a/intl/msg_hash_de.h +++ b/intl/msg_hash_de.h @@ -3315,7 +3315,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_eo.h b/intl/msg_hash_eo.h index a7719a8558..4052dcfe41 100644 --- a/intl/msg_hash_eo.h +++ b/intl/msg_hash_eo.h @@ -3072,7 +3072,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_es.h b/intl/msg_hash_es.h index ad7789021b..49bd2f839e 100644 --- a/intl/msg_hash_es.h +++ b/intl/msg_hash_es.h @@ -5701,8 +5701,4 @@ MSG_HASH( MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Valores mas bajos favorecen el rendimiento y bajan la latencia a costa de la calidad, incrementar el valor aumentará la calidad a costa del rendimiento y latencia" - ) -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") + ) \ No newline at end of file diff --git a/intl/msg_hash_fr.h b/intl/msg_hash_fr.h index 2f05bad0c8..96ac3c3425 100644 --- a/intl/msg_hash_fr.h +++ b/intl/msg_hash_fr.h @@ -3237,7 +3237,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_it.h b/intl/msg_hash_it.h index 77586ec343..f3ee9a8317 100644 --- a/intl/msg_hash_it.h +++ b/intl/msg_hash_it.h @@ -3295,7 +3295,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Qualità del Resampler Audio") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Abbassare questo valore per favorire prestazioni/bassa latenza rispetto alla qualità audio, aumentare se si desidera una migliore qualità audio a scapito delle prestazioni/minore latenza.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Segnaposto") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Segnaposto sotto etichetta") diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index f15e34a828..0fce42a8db 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -2990,7 +2990,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_INFO_PATH, MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR, "If a joypad is plugged in, that joypad will be autoconfigured if a config file corresponding to it is present inside this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY, - "すべてのコレクションをこのフォルダに保存する。") + "すべてのプレイリストをこのフォルダに保存する。") MSG_HASH( MENU_ENUM_SUBLABEL_CACHE_DIRECTORY, "If set to a directory, content which is temporarily extracted (e.g. from archives) will be extracted to this directory." @@ -3256,7 +3256,7 @@ MSG_HASH(MSG_GAME_REMAP_FILE_LOADED, MSG_HASH(MSG_CORE_REMAP_FILE_LOADED, "コアの優先ファイルをロードしました。") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, - "Automatically add content to playlist") + "自動的にコンテンツをプレイリストに追加") MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, "Automatically scans loaded content so they appear inside playlists.") MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, @@ -3267,7 +3267,5 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, + "シェーダーファイルの変更を監視") diff --git a/intl/msg_hash_ko.h b/intl/msg_hash_ko.h index dce3671f67..26db263322 100644 --- a/intl/msg_hash_ko.h +++ b/intl/msg_hash_ko.h @@ -3200,7 +3200,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 746f1fc21d..dcd7b57f17 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -931,6 +931,8 @@ MSG_HASH(MENU_ENUM_LABEL_SETTINGS_TAB, "settings_tab") MSG_HASH(MENU_ENUM_LABEL_SHADER_APPLY_CHANGES, "shader_apply_changes") +MSG_HASH(MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES, + "video_shader_watch_files") MSG_HASH(MENU_ENUM_LABEL_SHADER_OPTIONS, "shader_options") MSG_HASH(MENU_ENUM_LABEL_SHADER_PARAMETERS_ENTRY, @@ -1391,5 +1393,3 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_WINDOW_OPACITY, "video_window_opacity") MSG_HASH(MENU_ENUM_LABEL_AUDIO_RESAMPLER_QUALITY, "audio_resampler_quality") -MSG_HASH(MENU_ENUM_LABEL_SHADER_PLACEHOLDER, - "shader_placeholder") diff --git a/intl/msg_hash_nl.h b/intl/msg_hash_nl.h index 2b70e557d3..d5729cb759 100644 --- a/intl/msg_hash_nl.h +++ b/intl/msg_hash_nl.h @@ -3074,7 +3074,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h index 2cd106153c..8a64d8cc08 100644 --- a/intl/msg_hash_pl.h +++ b/intl/msg_hash_pl.h @@ -3335,7 +3335,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index 638d4a814c..a37db1a1e6 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -4179,7 +4179,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_pt_pt.h b/intl/msg_hash_pt_pt.h index eb8a06aef9..c71f653067 100644 --- a/intl/msg_hash_pt_pt.h +++ b/intl/msg_hash_pt_pt.h @@ -3175,7 +3175,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_ru.h b/intl/msg_hash_ru.h index 67e5a5bfe5..cc391e57ef 100644 --- a/intl/msg_hash_ru.h +++ b/intl/msg_hash_ru.h @@ -3258,7 +3258,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/intl/msg_hash_us.c b/intl/msg_hash_us.c index b26150d298..f28500cecd 100644 --- a/intl/msg_hash_us.c +++ b/intl/msg_hash_us.c @@ -1071,6 +1071,15 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len) "saved to Shader Directory." ); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + snprintf(s, len, + "Watch shader files for new changes. \n" + " \n" + "After saving changes to a shader on disk, \n" + "it will automatically be recompiled \n" + "and applied to the running content." + ); + break; case MENU_ENUM_LABEL_MENU_TOGGLE: snprintf(s, len, "Toggles menu."); diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index acffb4f0e0..fddbe1b808 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3405,7 +3405,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, + "Watch shader files for changes") +MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, + "Auto-apply changes made to shader files on disk.") diff --git a/intl/msg_hash_vn.h b/intl/msg_hash_vn.h index 4550175612..77a36a6753 100644 --- a/intl/msg_hash_vn.h +++ b/intl/msg_hash_vn.h @@ -3223,7 +3223,3 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Audio Resampler Quality") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Lower this value to favor performance/lower latency over audio quality, increase if you want better audio quality at the expense of performance/lower latency.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER, - "Shader Placeholder") -MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_PLACEHOLDER, - "Shader Placeholder sublabel") diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 60c1c0de3a..d9d05ce54d 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -309,6 +309,30 @@ static void menu_action_setting_disp_set_label_pipeline( } +static void menu_action_setting_disp_set_label_shader_watch_for_changes( + file_list_t* list, + unsigned *w, unsigned type, unsigned i, + const char *label, + char *s, size_t len, + const char *entry_label, + const char *path, + char *s2, size_t len2) +{ + settings_t *settings = config_get_ptr(); + + *s = '\0'; + *w = 19; + strlcpy(s2, path, len2); + + if (settings) + { + if (settings->bools.video_shader_watch_files) + snprintf(s, len, "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE)); + else + snprintf(s, len, "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FALSE)); + } +} + static void menu_action_setting_disp_set_label_shader_num_passes( file_list_t* list, unsigned *w, unsigned type, unsigned i, @@ -1873,6 +1897,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label( BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_shader_num_passes); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + BIND_ACTION_GET_VALUE(cbs, + menu_action_setting_disp_set_label_shader_watch_for_changes); + break; case MENU_ENUM_LABEL_XMB_RIBBON_ENABLE: BIND_ACTION_GET_VALUE(cbs, menu_action_setting_disp_set_label_pipeline); diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index e2ce711afa..8faa386e2b 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -324,6 +324,14 @@ static int action_left_shader_num_passes(unsigned type, const char *label, return 0; } +static int action_left_shader_watch_for_changes(unsigned type, const char *label, + bool wraparound) +{ + settings_t *settings = config_get_ptr(); + settings->bools.video_shader_watch_files = !settings->bools.video_shader_watch_files; + return 0; +} + static int action_left_video_resolution(unsigned type, const char *label, bool wraparound) { @@ -482,6 +490,9 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_SHADER_DEFAULT_FILTER: BIND_ACTION_LEFT(cbs, action_left_shader_filter_default); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + BIND_ACTION_LEFT(cbs, action_left_shader_watch_for_changes); + break; case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES: BIND_ACTION_LEFT(cbs, action_left_shader_num_passes); break; diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 0513da6490..2f4fe0efcc 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -327,6 +327,14 @@ static int action_right_shader_num_passes(unsigned type, const char *label, return 0; } +static int action_right_shader_watch_for_changes(unsigned type, const char *label, + bool wraparound) +{ + settings_t *settings = config_get_ptr(); + settings->bools.video_shader_watch_files = !settings->bools.video_shader_watch_files; + return 0; +} + static int action_right_video_resolution(unsigned type, const char *label, bool wraparound) { @@ -592,6 +600,9 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_SHADER_DEFAULT_FILTER: BIND_ACTION_RIGHT(cbs, action_right_shader_filter_default); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + BIND_ACTION_RIGHT(cbs, action_right_shader_watch_for_changes); + break; case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES: BIND_ACTION_RIGHT(cbs, action_right_shader_num_passes); break; diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 84ac5e0e16..377c84294e 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -40,6 +40,8 @@ #include "../../input/input_driver.h" #include "../../input/input_remapping.h" +#include "../../config.def.h" + #ifndef BIND_ACTION_START #define BIND_ACTION_START(cbs, name) \ cbs->action_start = name; \ @@ -166,6 +168,13 @@ static int action_start_shader_filter_pass(unsigned type, const char *label) return menu_shader_manager_clear_pass_filter(pass); } +static int action_start_shader_watch_for_changes(unsigned type, const char *label) +{ + settings_t *settings = config_get_ptr(); + settings->bools.video_shader_watch_files = video_shader_watch_files; + return 0; +} + static int action_start_shader_num_passes(unsigned type, const char *label) { return menu_shader_manager_clear_num_passes(); @@ -279,6 +288,9 @@ static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs) case MENU_ENUM_LABEL_VIDEO_SHADER_FILTER_PASS: BIND_ACTION_START(cbs, action_start_shader_filter_pass); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + BIND_ACTION_START(cbs, action_start_shader_watch_for_changes); + break; case MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES: BIND_ACTION_START(cbs, action_start_shader_num_passes); break; diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 2bd0baac54..003aacea12 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -353,6 +353,7 @@ default_sublabel_macro(action_bind_sublabel_recording_output_directory, default_sublabel_macro(action_bind_sublabel_recording_config_directory, MENU_ENUM_SUBLABEL_RECORDING_CONFIG_DIRECTORY) default_sublabel_macro(action_bind_sublabel_video_font_path, MENU_ENUM_SUBLABEL_VIDEO_FONT_PATH) default_sublabel_macro(action_bind_sublabel_shader_apply_changes, MENU_ENUM_SUBLABEL_SHADER_APPLY_CHANGES) +default_sublabel_macro(action_bind_sublabel_shader_watch_for_changes, MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES) default_sublabel_macro(action_bind_sublabel_shader_num_passes, MENU_ENUM_SUBLABEL_VIDEO_SHADER_NUM_PASSES) default_sublabel_macro(action_bind_sublabel_shader_preset, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET) default_sublabel_macro(action_bind_sublabel_shader_preset_save_as, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_AS) @@ -518,6 +519,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_SHADER_APPLY_CHANGES: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_shader_apply_changes); break; + case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_shader_watch_for_changes); + break; case MENU_ENUM_LABEL_VIDEO_FONT_PATH: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_font_path); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index d9208ad8d2..3d311fc984 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1366,16 +1366,19 @@ static int menu_displaylist_parse_shader_options(menu_displaylist_info_t *info) unsigned i; unsigned pass_count = menu_shader_manager_get_amount_passes(); - menu_entries_append_enum(info->list, - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_PLACEHOLDER), - msg_hash_to_str(MENU_ENUM_LABEL_SHADER_PLACEHOLDER), - MENU_ENUM_LABEL_SHADER_PLACEHOLDER, - MENU_SETTING_ACTION, 0, 0); menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_APPLY_CHANGES), msg_hash_to_str(MENU_ENUM_LABEL_SHADER_APPLY_CHANGES), MENU_ENUM_LABEL_SHADER_APPLY_CHANGES, MENU_SETTING_ACTION, 0, 0); + if (frontend_driver_can_watch_for_changes()) + { + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES), + msg_hash_to_str(MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES), + MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES, + 0, 0, 0); + } menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET), diff --git a/msg_hash.h b/msg_hash.h index c229cca7f2..21bdc4ceac 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1467,12 +1467,12 @@ enum msg_hash_enums MENU_ENUM_LABEL_ONSCREEN_KEYBOARD_OVERLAY_SETTINGS, - MENU_LABEL(SHADER_PLACEHOLDER), MENU_LABEL(MULTIMEDIA_SETTINGS), MENU_LABEL(PLAYLIST_SETTINGS), MENU_LABEL(CORE_UPDATER_SETTINGS), MENU_LABEL(LAKKA_SERVICES), MENU_LABEL(SHADER_APPLY_CHANGES), + MENU_LABEL(SHADER_WATCH_FOR_CHANGES), MENU_LABEL(SAVE_NEW_CONFIG), MENU_LABEL(ONSCREEN_DISPLAY_SETTINGS), MENU_LABEL(ONSCREEN_OVERLAY_SETTINGS), diff --git a/retroarch.c b/retroarch.c index 7dff2df3cd..f07dc16e3a 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2994,6 +2994,12 @@ static enum runloop_state runloop_check_state( old_cheat_index_toggle = cheat_index_toggle; } + if (settings->bools.video_shader_watch_files) + { + if (video_shader_check_for_changes()) + command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL); + } + return RUNLOOP_STATE_ITERATE; } diff --git a/retroarch.cfg b/retroarch.cfg index 238520536b..9319490de6 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -811,6 +811,9 @@ video_message_bgcolor_opacity = 1.0 # Screenshots output of GPU shaded material if available. # video_gpu_screenshot = true +# Watch content shader files for changes and auto-apply as necessary. +# video_shader_watch_files = false + # Block SRAM from being overwritten when loading save states. # Might potentially lead to buggy games. # block_sram_overwrite = false From 9e347ec71fc408fe77b95d39ec91c83b1c57f1ff Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Thu, 25 Jan 2018 19:09:55 -0500 Subject: [PATCH 2/2] detect shader file changes on move and delete as well, and wait a few frames before re-applying changes --- frontend/drivers/platform_unix.c | 4 ++++ frontend/frontend_driver.h | 5 ++++- gfx/video_shader_parse.c | 7 ++++++- retroarch.c | 27 ++++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c index daee38d2a3..6f6015ed1a 100644 --- a/frontend/drivers/platform_unix.c +++ b/frontend/drivers/platform_unix.c @@ -2357,6 +2357,10 @@ static void frontend_unix_watch_path_for_changes(struct string_list *list, int f inotify_mask |= IN_MODIFY; if (flags & PATH_CHANGE_TYPE_WRITE_FILE_CLOSED) inotify_mask |= IN_CLOSE_WRITE; + if (flags & PATH_CHANGE_TYPE_FILE_MOVED) + inotify_mask |= IN_MOVE_SELF; + if (flags & PATH_CHANGE_TYPE_FILE_DELETED) + inotify_mask |= IN_DELETE_SELF; inotify_data->flags = inotify_mask; diff --git a/frontend/frontend_driver.h b/frontend/frontend_driver.h index 8e3fe089bf..a2f5ddf966 100644 --- a/frontend/frontend_driver.h +++ b/frontend/frontend_driver.h @@ -56,10 +56,13 @@ enum frontend_architecture FRONTEND_ARCH_TILE }; +/* different platforms may only support some of these types */ enum path_change_type { PATH_CHANGE_TYPE_MODIFIED = (1 << 0), - PATH_CHANGE_TYPE_WRITE_FILE_CLOSED = (1 << 1) + PATH_CHANGE_TYPE_WRITE_FILE_CLOSED = (1 << 1), + PATH_CHANGE_TYPE_FILE_MOVED = (1 << 2), + PATH_CHANGE_TYPE_FILE_DELETED = (1 << 3) }; typedef struct path_change_data diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 6313cdacbc..d4160fd4a9 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -809,7 +809,12 @@ bool video_shader_read_conf_cgp(config_file_t *conf, if (settings->bools.video_shader_watch_files) { - frontend_driver_watch_path_for_changes(file_list, PATH_CHANGE_TYPE_WRITE_FILE_CLOSED, &file_change_data); + int flags = PATH_CHANGE_TYPE_MODIFIED | + PATH_CHANGE_TYPE_WRITE_FILE_CLOSED | + PATH_CHANGE_TYPE_FILE_MOVED | + PATH_CHANGE_TYPE_FILE_DELETED; + + frontend_driver_watch_path_for_changes(file_list, flags, &file_change_data); string_list_free(file_list); } diff --git a/retroarch.c b/retroarch.c index f07dc16e3a..1c6165f6c3 100644 --- a/retroarch.c +++ b/retroarch.c @@ -130,6 +130,8 @@ #define DEFAULT_EXT "" #endif +#define SHADER_FILE_WATCH_DELAY_FRAMES 5 + /* Descriptive names for options without short variant. * * Please keep the name in sync with the option name. @@ -2996,8 +2998,31 @@ static enum runloop_state runloop_check_state( if (settings->bools.video_shader_watch_files) { + static bool need_to_apply = false; + static int elapsed_frames = 0; + if (video_shader_check_for_changes()) - command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL); + { + need_to_apply = true; + elapsed_frames = 0; + } + + /* If a file is modified atomically (moved/renamed from a different file), we have no idea how long that might take. + * If we're trying to re-apply shaders immediately after changes are made to the original file(s), the filesystem might be in an in-between + * state where the new file hasn't been moved over yet and the original file was already deleted. This leaves us no choice + * but to wait an arbitrary amount of time and hope for the best. + */ + if (need_to_apply) + { + if (elapsed_frames > SHADER_FILE_WATCH_DELAY_FRAMES) + { + need_to_apply = false; + elapsed_frames = 0; + command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL); + } + else + elapsed_frames++; + } } return RUNLOOP_STATE_ITERATE;