diff --git a/menu/menu_driver.c b/menu/menu_driver.c index f3c03e7978..53e0a176f8 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -21,10 +21,15 @@ #endif #include +#include +#include + #include "menu_driver.h" #include "menu_cbs.h" #include "../list_special.h" +#include "../paths.h" #include "../tasks/tasks_internal.h" +#include "../verbosity.h" #ifdef HAVE_LANGEXTRA /* This file has a UTF8 BOM, we assume HAVE_LANGEXTRA @@ -2459,3 +2464,298 @@ void menu_entries_search_append_terms_string(char *s, size_t len) } } } + +#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) +bool menu_shader_manager_save_preset_internal( + bool save_reference, + const struct video_shader *shader, + const char *basename, + const char *dir_video_shader, + bool apply, + const char **target_dirs, + size_t num_target_dirs) +{ + char fullname[PATH_MAX_LENGTH]; + char buffer[PATH_MAX_LENGTH]; + bool ret = false; + enum rarch_shader_type type = RARCH_SHADER_NONE; + char *preset_path = NULL; + size_t i = 0; + + fullname[0] = buffer[0] = '\0'; + + if (!shader || !shader->passes) + return false; + + type = menu_shader_manager_get_type(shader); + + if (type == RARCH_SHADER_NONE) + return false; + + if (!string_is_empty(basename)) + { + /* We are comparing against a fixed list of file + * extensions, the longest (slangp) being 6 characters + * in length. We therefore only need to extract the first + * 7 characters from the extension of the input path + * to correctly validate a match */ + char ext_lower[8]; + const char *ext = NULL; + + ext_lower[0] = '\0'; + + strlcpy(fullname, basename, sizeof(fullname)); + + /* Get file extension */ + ext = strrchr(basename, '.'); + + /* Copy and convert to lower case */ + if (ext && (*(++ext) != '\0')) + { + strlcpy(ext_lower, ext, sizeof(ext_lower)); + string_to_lower(ext_lower); + } + + /* Append extension automatically as appropriate. */ + if ( !string_is_equal(ext_lower, "cgp") + && !string_is_equal(ext_lower, "glslp") + && !string_is_equal(ext_lower, "slangp")) + { + const char *preset_ext = video_shader_get_preset_extension(type); + strlcat(fullname, preset_ext, sizeof(fullname)); + } + } + else + snprintf(fullname, sizeof(fullname), "retroarch%s", + video_shader_get_preset_extension(type)); + + if (path_is_absolute(fullname)) + { + preset_path = fullname; + ret = video_shader_write_preset(preset_path, + dir_video_shader, + shader, save_reference); + + if (ret) + RARCH_LOG("[Shaders - Save Preset]: Saved shader preset to %s.\n", preset_path); + else + RARCH_ERR("[Shaders - Save Preset]: Failed writing shader preset to %s.\n", preset_path); + } + else + { + char basedir[PATH_MAX_LENGTH]; + + for (i = 0; i < num_target_dirs; i++) + { + if (string_is_empty(target_dirs[i])) + continue; + + fill_pathname_join(buffer, target_dirs[i], + fullname, sizeof(buffer)); + + strlcpy(basedir, buffer, sizeof(basedir)); + path_basedir(basedir); + + if (!path_is_directory(basedir)) + { + ret = path_mkdir(basedir); + + if (!ret) + { + RARCH_WARN("[Shaders - Save Preset]: Failed to create preset directory %s.\n", basedir); + continue; + } + } + + preset_path = buffer; + + ret = video_shader_write_preset(preset_path, + dir_video_shader, + shader, save_reference); + + if (ret) + { + RARCH_LOG("[Shaders - Save Preset]: Saved shader preset to %s.\n", preset_path); + break; + } + else + RARCH_WARN("[Shaders - Save Preset]: Failed writing shader preset to %s.\n", preset_path); + } + + if (!ret) + RARCH_ERR("[Shaders - Save Preset]: Failed to write shader preset. Make sure shader directory" + " and/or config directory are writable.\n"); + } + + if (ret && apply) + menu_shader_manager_set_preset(NULL, type, preset_path, true); + + return ret; +} + +bool menu_shader_manager_operate_auto_preset( + struct retro_system_info *system, + settings_t *settings, + enum auto_shader_operation op, + const struct video_shader *shader, + const char *dir_video_shader, + const char *dir_menu_config, + enum auto_shader_type type, bool apply) +{ + char old_presets_directory[PATH_MAX_LENGTH]; + char config_directory[PATH_MAX_LENGTH]; + char tmp[PATH_MAX_LENGTH]; + char file[PATH_MAX_LENGTH]; + static enum rarch_shader_type shader_types[] = + { + RARCH_SHADER_GLSL, RARCH_SHADER_SLANG, RARCH_SHADER_CG + }; + const char *core_name = system ? system->library_name : NULL; + const char *auto_preset_dirs[3] = {0}; + + old_presets_directory[0] = config_directory[0] = tmp[0] = file[0] = '\0'; + + if (type != SHADER_PRESET_GLOBAL && string_is_empty(core_name)) + return false; + + if (!path_is_empty(RARCH_PATH_CONFIG)) + fill_pathname_basedir( + config_directory, + path_get(RARCH_PATH_CONFIG), + sizeof(config_directory)); + + /* We are only including this directory for compatibility purposes with + * versions 1.8.7 and older. */ + if (op != AUTO_SHADER_OP_SAVE && !string_is_empty(dir_video_shader)) + fill_pathname_join( + old_presets_directory, + dir_video_shader, + "presets", + sizeof(old_presets_directory)); + + auto_preset_dirs[0] = dir_menu_config; + auto_preset_dirs[1] = config_directory; + auto_preset_dirs[2] = old_presets_directory; + + switch (type) + { + case SHADER_PRESET_GLOBAL: + strcpy_literal(file, "global"); + break; + case SHADER_PRESET_CORE: + fill_pathname_join(file, core_name, core_name, sizeof(file)); + break; + case SHADER_PRESET_PARENT: + fill_pathname_parent_dir_name(tmp, + path_get(RARCH_PATH_BASENAME), sizeof(tmp)); + fill_pathname_join(file, core_name, tmp, sizeof(file)); + break; + case SHADER_PRESET_GAME: + { + const char *game_name = + path_basename(path_get(RARCH_PATH_BASENAME)); + if (string_is_empty(game_name)) + return false; + fill_pathname_join(file, core_name, game_name, sizeof(file)); + break; + } + default: + return false; + } + + switch (op) + { + case AUTO_SHADER_OP_SAVE: + return menu_shader_manager_save_preset_internal( + settings->bools.video_shader_preset_save_reference_enable, + shader, file, + dir_video_shader, + apply, + auto_preset_dirs, + ARRAY_SIZE(auto_preset_dirs)); + case AUTO_SHADER_OP_REMOVE: + { + /* remove all supported auto-shaders of given type */ + char *end; + size_t i, j, m; + + char preset_path[PATH_MAX_LENGTH]; + + /* n = amount of relevant shader presets found + * m = amount of successfully deleted shader presets */ + size_t n = m = 0; + + for (i = 0; i < ARRAY_SIZE(auto_preset_dirs); i++) + { + if (string_is_empty(auto_preset_dirs[i])) + continue; + + fill_pathname_join(preset_path, + auto_preset_dirs[i], file, sizeof(preset_path)); + end = preset_path + strlen(preset_path); + + for (j = 0; j < ARRAY_SIZE(shader_types); j++) + { + const char *preset_ext; + + if (!video_shader_is_supported(shader_types[j])) + continue; + + preset_ext = video_shader_get_preset_extension(shader_types[j]); + strlcpy(end, preset_ext, sizeof(preset_path) - (end - preset_path)); + + if (path_is_valid(preset_path)) + { + n++; + + if (!filestream_delete(preset_path)) + { + m++; + RARCH_LOG("[Shaders]: Deleted shader preset from \"%s\".\n", preset_path); + } + else + RARCH_WARN("[Shaders]: Failed to remove shader preset at \"%s\".\n", preset_path); + } + } + } + + return n == m; + } + case AUTO_SHADER_OP_EXISTS: + { + /* test if any supported auto-shaders of given type exists */ + char *end; + size_t i, j; + + char preset_path[PATH_MAX_LENGTH]; + + for (i = 0; i < ARRAY_SIZE(auto_preset_dirs); i++) + { + if (string_is_empty(auto_preset_dirs[i])) + continue; + + fill_pathname_join(preset_path, + auto_preset_dirs[i], file, sizeof(preset_path)); + end = preset_path + strlen(preset_path); + + for (j = 0; j < ARRAY_SIZE(shader_types); j++) + { + const char *preset_ext; + + if (!video_shader_is_supported(shader_types[j])) + continue; + + preset_ext = video_shader_get_preset_extension(shader_types[j]); + strlcpy(end, preset_ext, sizeof(preset_path) - (end - preset_path)); + + if (path_is_valid(preset_path)) + return true; + } + } + } + break; + } + + return false; +} +#endif diff --git a/menu/menu_shader.h b/menu/menu_shader.h index 8ee8940da8..0eb83f9a55 100644 --- a/menu/menu_shader.h +++ b/menu/menu_shader.h @@ -18,6 +18,7 @@ #define _MENU_SHADER_MANAGER_H #include +#include #include "../gfx/video_shader_parse.h" @@ -31,6 +32,22 @@ enum auto_shader_type SHADER_PRESET_GAME }; +enum auto_shader_operation +{ + AUTO_SHADER_OP_SAVE = 0, + AUTO_SHADER_OP_REMOVE, + AUTO_SHADER_OP_EXISTS +}; + +struct rarch_dir_shader_list +{ + struct string_list *shader_list; + char *directory; + size_t selection; + bool shader_loaded; + bool remember_last_preset_dir; +}; + struct video_shader *menu_shader_get(void); void menu_shader_manager_free(void *data); @@ -141,6 +158,24 @@ bool menu_shader_manager_auto_preset_exists( const char *dir_video_shader, const char *dir_menu_config); +bool menu_shader_manager_save_preset_internal( + bool save_reference, + const struct video_shader *shader, + const char *basename, + const char *dir_video_shader, + bool apply, + const char **target_dirs, + size_t num_target_dirs); + +bool menu_shader_manager_operate_auto_preset( + struct retro_system_info *system, + settings_t *settings, + enum auto_shader_operation op, + const struct video_shader *shader, + const char *dir_video_shader, + const char *dir_menu_config, + enum auto_shader_type type, bool apply); + RETRO_END_DECLS #endif diff --git a/retroarch.c b/retroarch.c index b65a0345fe..9be5016e71 100644 --- a/retroarch.c +++ b/retroarch.c @@ -4103,299 +4103,6 @@ clear: return ret; } -static bool menu_shader_manager_save_preset_internal( - bool save_reference, - const struct video_shader *shader, - const char *basename, - const char *dir_video_shader, - bool apply, - const char **target_dirs, - size_t num_target_dirs) -{ - char fullname[PATH_MAX_LENGTH]; - char buffer[PATH_MAX_LENGTH]; - bool ret = false; - enum rarch_shader_type type = RARCH_SHADER_NONE; - char *preset_path = NULL; - size_t i = 0; - - fullname[0] = buffer[0] = '\0'; - - if (!shader || !shader->passes) - return false; - - type = menu_shader_manager_get_type(shader); - - if (type == RARCH_SHADER_NONE) - return false; - - if (!string_is_empty(basename)) - { - /* We are comparing against a fixed list of file - * extensions, the longest (slangp) being 6 characters - * in length. We therefore only need to extract the first - * 7 characters from the extension of the input path - * to correctly validate a match */ - char ext_lower[8]; - const char *ext = NULL; - - ext_lower[0] = '\0'; - - strlcpy(fullname, basename, sizeof(fullname)); - - /* Get file extension */ - ext = strrchr(basename, '.'); - - /* Copy and convert to lower case */ - if (ext && (*(++ext) != '\0')) - { - strlcpy(ext_lower, ext, sizeof(ext_lower)); - string_to_lower(ext_lower); - } - - /* Append extension automatically as appropriate. */ - if ( !string_is_equal(ext_lower, "cgp") - && !string_is_equal(ext_lower, "glslp") - && !string_is_equal(ext_lower, "slangp")) - { - const char *preset_ext = video_shader_get_preset_extension(type); - strlcat(fullname, preset_ext, sizeof(fullname)); - } - } - else - snprintf(fullname, sizeof(fullname), "retroarch%s", - video_shader_get_preset_extension(type)); - - if (path_is_absolute(fullname)) - { - preset_path = fullname; - ret = video_shader_write_preset(preset_path, - dir_video_shader, - shader, save_reference); - - if (ret) - RARCH_LOG("[Shaders - Save Preset]: Saved shader preset to %s.\n", preset_path); - else - RARCH_ERR("[Shaders - Save Preset]: Failed writing shader preset to %s.\n", preset_path); - } - else - { - char basedir[PATH_MAX_LENGTH]; - - for (i = 0; i < num_target_dirs; i++) - { - if (string_is_empty(target_dirs[i])) - continue; - - fill_pathname_join(buffer, target_dirs[i], - fullname, sizeof(buffer)); - - strlcpy(basedir, buffer, sizeof(basedir)); - path_basedir(basedir); - - if (!path_is_directory(basedir)) - { - ret = path_mkdir(basedir); - - if (!ret) - { - RARCH_WARN("[Shaders - Save Preset]: Failed to create preset directory %s.\n", basedir); - continue; - } - } - - preset_path = buffer; - - ret = video_shader_write_preset(preset_path, - dir_video_shader, - shader, save_reference); - - if (ret) - { - RARCH_LOG("[Shaders - Save Preset]: Saved shader preset to %s.\n", preset_path); - break; - } - else - RARCH_WARN("[Shaders - Save Preset]: Failed writing shader preset to %s.\n", preset_path); - } - - if (!ret) - RARCH_ERR("[Shaders - Save Preset]: Failed to write shader preset. Make sure shader directory" - " and/or config directory are writable.\n"); - } - - if (ret && apply) - menu_shader_manager_set_preset(NULL, type, preset_path, true); - - return ret; -} - -static bool menu_shader_manager_operate_auto_preset( - struct retro_system_info *system, - settings_t *settings, - enum auto_shader_operation op, - const struct video_shader *shader, - const char *dir_video_shader, - const char *dir_menu_config, - enum auto_shader_type type, bool apply) -{ - char old_presets_directory[PATH_MAX_LENGTH]; - char config_directory[PATH_MAX_LENGTH]; - char tmp[PATH_MAX_LENGTH]; - char file[PATH_MAX_LENGTH]; - static enum rarch_shader_type shader_types[] = - { - RARCH_SHADER_GLSL, RARCH_SHADER_SLANG, RARCH_SHADER_CG - }; - const char *core_name = system ? system->library_name : NULL; - const char *auto_preset_dirs[3] = {0}; - - old_presets_directory[0] = config_directory[0] = tmp[0] = file[0] = '\0'; - - if (type != SHADER_PRESET_GLOBAL && string_is_empty(core_name)) - return false; - - if (!path_is_empty(RARCH_PATH_CONFIG)) - fill_pathname_basedir( - config_directory, - path_get(RARCH_PATH_CONFIG), - sizeof(config_directory)); - - /* We are only including this directory for compatibility purposes with - * versions 1.8.7 and older. */ - if (op != AUTO_SHADER_OP_SAVE && !string_is_empty(dir_video_shader)) - fill_pathname_join( - old_presets_directory, - dir_video_shader, - "presets", - sizeof(old_presets_directory)); - - auto_preset_dirs[0] = dir_menu_config; - auto_preset_dirs[1] = config_directory; - auto_preset_dirs[2] = old_presets_directory; - - switch (type) - { - case SHADER_PRESET_GLOBAL: - strcpy_literal(file, "global"); - break; - case SHADER_PRESET_CORE: - fill_pathname_join(file, core_name, core_name, sizeof(file)); - break; - case SHADER_PRESET_PARENT: - fill_pathname_parent_dir_name(tmp, - path_get(RARCH_PATH_BASENAME), sizeof(tmp)); - fill_pathname_join(file, core_name, tmp, sizeof(file)); - break; - case SHADER_PRESET_GAME: - { - const char *game_name = - path_basename(path_get(RARCH_PATH_BASENAME)); - if (string_is_empty(game_name)) - return false; - fill_pathname_join(file, core_name, game_name, sizeof(file)); - break; - } - default: - return false; - } - - switch (op) - { - case AUTO_SHADER_OP_SAVE: - return menu_shader_manager_save_preset_internal( - settings->bools.video_shader_preset_save_reference_enable, - shader, file, - dir_video_shader, - apply, - auto_preset_dirs, - ARRAY_SIZE(auto_preset_dirs)); - case AUTO_SHADER_OP_REMOVE: - { - /* remove all supported auto-shaders of given type */ - char *end; - size_t i, j, m; - - char preset_path[PATH_MAX_LENGTH]; - - /* n = amount of relevant shader presets found - * m = amount of successfully deleted shader presets */ - size_t n = m = 0; - - for (i = 0; i < ARRAY_SIZE(auto_preset_dirs); i++) - { - if (string_is_empty(auto_preset_dirs[i])) - continue; - - fill_pathname_join(preset_path, - auto_preset_dirs[i], file, sizeof(preset_path)); - end = preset_path + strlen(preset_path); - - for (j = 0; j < ARRAY_SIZE(shader_types); j++) - { - const char *preset_ext; - - if (!video_shader_is_supported(shader_types[j])) - continue; - - preset_ext = video_shader_get_preset_extension(shader_types[j]); - strlcpy(end, preset_ext, sizeof(preset_path) - (end - preset_path)); - - if (path_is_valid(preset_path)) - { - n++; - - if (!filestream_delete(preset_path)) - { - m++; - RARCH_LOG("[Shaders]: Deleted shader preset from \"%s\".\n", preset_path); - } - else - RARCH_WARN("[Shaders]: Failed to remove shader preset at \"%s\".\n", preset_path); - } - } - } - - return n == m; - } - case AUTO_SHADER_OP_EXISTS: - { - /* test if any supported auto-shaders of given type exists */ - char *end; - size_t i, j; - - char preset_path[PATH_MAX_LENGTH]; - - for (i = 0; i < ARRAY_SIZE(auto_preset_dirs); i++) - { - if (string_is_empty(auto_preset_dirs[i])) - continue; - - fill_pathname_join(preset_path, - auto_preset_dirs[i], file, sizeof(preset_path)); - end = preset_path + strlen(preset_path); - - for (j = 0; j < ARRAY_SIZE(shader_types); j++) - { - const char *preset_ext; - - if (!video_shader_is_supported(shader_types[j])) - continue; - - preset_ext = video_shader_get_preset_extension(shader_types[j]); - strlcpy(end, preset_ext, sizeof(preset_path) - (end - preset_path)); - - if (path_is_valid(preset_path)) - return true; - } - } - } - break; - } - - return false; -} - /** * menu_shader_manager_save_auto_preset: * @shader : shader to save diff --git a/retroarch_data.h b/retroarch_data.h index 8517c0d68e..549d84d055 100644 --- a/retroarch_data.h +++ b/retroarch_data.h @@ -1005,13 +1005,6 @@ enum poll_type_override_t POLL_TYPE_OVERRIDE_LATE }; -enum auto_shader_operation -{ - AUTO_SHADER_OP_SAVE = 0, - AUTO_SHADER_OP_REMOVE, - AUTO_SHADER_OP_EXISTS -}; - enum input_game_focus_cmd_type { GAME_FOCUS_CMD_OFF = 0, @@ -1036,15 +1029,6 @@ typedef struct bool set; } runloop_core_status_msg_t; -struct rarch_dir_shader_list -{ - struct string_list *shader_list; - char *directory; - size_t selection; - bool shader_loaded; - bool remember_last_preset_dir; -}; - #ifdef HAVE_BSV_MOVIE struct bsv_state {