diff --git a/frontend/menu/backend/menu_common_backend.c b/frontend/menu/backend/menu_common_backend.c index f8a4cd299e..28b2f2c1e3 100644 --- a/frontend/menu/backend/menu_common_backend.c +++ b/frontend/menu/backend/menu_common_backend.c @@ -1328,6 +1328,11 @@ static int menu_common_setting_set(unsigned id, unsigned action) return 0; } +#ifdef HAVE_SHADER_MANAGER +#include "menu_common_shader_backend.c" +#endif + + static int menu_common_setting_toggle(unsigned id, unsigned action, unsigned menu_type) { @@ -2410,434 +2415,6 @@ static int menu_common_iterate(unsigned action) return ret; } -#ifdef HAVE_SHADER_MANAGER -static void menu_common_shader_manager_init(menu_handle_t *menu) -{ - char cgp_path[PATH_MAX]; - config_file_t *conf = NULL; - const char *config_path = NULL; - struct gfx_shader *shader = (struct gfx_shader*)menu->shader; - - if (*g_extern.core_specific_config_path && g_settings.core_specific_config) - config_path = g_extern.core_specific_config_path; - else if (*g_extern.config_path) - config_path = g_extern.config_path; - - // In a multi-config setting, we can't have conflicts on menu.cgp/menu.glslp. - if (config_path) - { - fill_pathname_base(menu->default_glslp, config_path, sizeof(menu->default_glslp)); - path_remove_extension(menu->default_glslp); - strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp)); - fill_pathname_base(menu->default_cgp, config_path, sizeof(menu->default_cgp)); - path_remove_extension(menu->default_cgp); - strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp)); - } - else - { - strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp)); - strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp)); - } - - - const char *ext = path_get_extension(g_settings.video.shader_path); - if (strcmp(ext, "glslp") == 0 || strcmp(ext, "cgp") == 0) - { - conf = config_file_new(g_settings.video.shader_path); - if (conf) - { - if (gfx_shader_read_conf_cgp(conf, shader)) - { - gfx_shader_resolve_relative(shader, g_settings.video.shader_path); - gfx_shader_resolve_parameters(conf, shader); - } - config_file_free(conf); - } - } - else if (strcmp(ext, "glsl") == 0 || strcmp(ext, "cg") == 0) - { - strlcpy(shader->pass[0].source.path, g_settings.video.shader_path, - sizeof(shader->pass[0].source.path)); - shader->passes = 1; - } - else - { - const char *shader_dir = *g_settings.video.shader_dir ? - g_settings.video.shader_dir : g_settings.system_directory; - - fill_pathname_join(cgp_path, shader_dir, "menu.glslp", sizeof(cgp_path)); - conf = config_file_new(cgp_path); - - if (!conf) - { - fill_pathname_join(cgp_path, shader_dir, "menu.cgp", sizeof(cgp_path)); - conf = config_file_new(cgp_path); - } - - if (conf) - { - if (gfx_shader_read_conf_cgp(conf, shader)) - { - gfx_shader_resolve_relative(shader, cgp_path); - gfx_shader_resolve_parameters(conf, shader); - } - config_file_free(conf); - } - } -} - -static void menu_common_shader_manager_set_preset(struct gfx_shader *shader, unsigned type, const char *cgp_path) -{ - RARCH_LOG("Setting Menu shader: %s.\n", cgp_path ? cgp_path : "N/A (stock)"); - - if (driver.video->set_shader && driver.video->set_shader(driver.video_data, (enum rarch_shader_type)type, cgp_path)) - { - // Makes sure that we use Menu CGP shader on driver reinit. - // Only do this when the cgp actually works to avoid potential errors. - strlcpy(g_settings.video.shader_path, cgp_path ? cgp_path : "", - sizeof(g_settings.video.shader_path)); - g_settings.video.shader_enable = true; - - if (cgp_path && shader) - { - // Load stored CGP into menu on success. - // Used when a preset is directly loaded. - // No point in updating when the CGP was created from the menu itself. - config_file_t *conf = config_file_new(cgp_path); - - if (conf) - { - if (gfx_shader_read_conf_cgp(conf, shader)) - { - gfx_shader_resolve_relative(shader, cgp_path); - gfx_shader_resolve_parameters(conf, shader); - } - config_file_free(conf); - } - - driver.menu->need_refresh = true; - } - } - else - { - RARCH_ERR("Setting Menu CGP failed.\n"); - g_settings.video.shader_enable = false; - } -} - -static void menu_common_shader_manager_get_str(struct gfx_shader *shader, char *type_str, size_t type_str_size, unsigned type) -{ - *type_str = '\0'; - - if (type >= MENU_SETTINGS_SHADER_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST) - { - // menu->parameter_shader here. - if (shader) - { - const struct gfx_shader_parameter *param = (const struct gfx_shader_parameter*)&shader->parameters[type - MENU_SETTINGS_SHADER_PARAMETER_0]; - snprintf(type_str, type_str_size, "%.2f [%.2f %.2f]", param->current, param->minimum, param->maximum); - } - } - else if (type == MENU_SETTINGS_SHADER_PASSES) - snprintf(type_str, type_str_size, "%u", shader->passes); - else if (type >= MENU_SETTINGS_SHADER_0 && type <= MENU_SETTINGS_SHADER_LAST) - { - unsigned pass = (type - MENU_SETTINGS_SHADER_0) / 3; - switch ((type - MENU_SETTINGS_SHADER_0) % 3) - { - case 0: - if (*shader->pass[pass].source.path) - fill_pathname_base(type_str, - shader->pass[pass].source.path, type_str_size); - else - strlcpy(type_str, "N/A", type_str_size); - break; - - case 1: - { - static const char *modes[] = { - "Don't care", - "Linear", - "Nearest" - }; - - strlcpy(type_str, modes[shader->pass[pass].filter], type_str_size); - } - break; - - case 2: - { - unsigned scale = shader->pass[pass].fbo.scale_x; - if (!scale) - strlcpy(type_str, "Don't care", type_str_size); - else - snprintf(type_str, type_str_size, "%ux", scale); - break; - } - } - } -} - -static void menu_common_shader_manager_save_preset(const char *basename, bool apply) -{ - char buffer[PATH_MAX], config_directory[PATH_MAX], cgp_path[PATH_MAX]; - unsigned d, type = RARCH_SHADER_NONE; - config_file_t *conf = NULL; - const char *conf_path = NULL; - bool ret = false; - - if (!driver.menu) - { - RARCH_ERR("Cannot save shader preset, menu handle is not initialized.\n"); - return; - } - - if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_get_type) - type = driver.menu_ctx->backend->shader_manager_get_type(driver.menu->shader); - - if (type == RARCH_SHADER_NONE) - return; - - conf_path = (type == RARCH_SHADER_GLSL) ? driver.menu->default_glslp : driver.menu->default_cgp; - *config_directory = '\0'; - - if (basename) - { - strlcpy(buffer, basename, sizeof(buffer)); - // Append extension automatically as appropriate. - if (!strstr(basename, ".cgp") && !strstr(basename, ".glslp")) - { - if (type == RARCH_SHADER_GLSL) - strlcat(buffer, ".glslp", sizeof(buffer)); - else if (type == RARCH_SHADER_CG) - strlcat(buffer, ".cgp", sizeof(buffer)); - } - } - - if (*g_extern.config_path) - fill_pathname_basedir(config_directory, g_extern.config_path, sizeof(config_directory)); - - const char *dirs[] = { - g_settings.video.shader_dir, - g_settings.menu_config_directory, - config_directory, - }; - - if (!(conf = (config_file_t*)config_file_new(NULL))) - return; - gfx_shader_write_conf_cgp(conf, driver.menu->shader); - - for (d = 0; d < ARRAY_SIZE(dirs); d++) - { - if (!*dirs[d]) - continue; - - fill_pathname_join(cgp_path, dirs[d], conf_path, sizeof(cgp_path)); - if (config_file_write(conf, cgp_path)) - { - RARCH_LOG("Saved shader preset to %s.\n", cgp_path); - if (apply) - { - if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_set_preset) - driver.menu_ctx->backend->shader_manager_set_preset(NULL, type, cgp_path); - } - ret = true; - break; - } - else - RARCH_LOG("Failed writing shader preset to %s.\n", cgp_path); - } - - config_file_free(conf); - if (!ret) - RARCH_ERR("Failed to save shader preset. Make sure config directory and/or shader dir are writable.\n"); -} - -static unsigned menu_common_shader_manager_get_type(const struct gfx_shader *shader) -{ - // All shader types must be the same, or we cannot use it. - unsigned i; - unsigned type = RARCH_SHADER_NONE; - - if (!shader) - { - RARCH_ERR("Cannot get shader type, shader handle is not initialized.\n"); - return RARCH_SHADER_NONE; - } - - for (i = 0; i < shader->passes; i++) - { - enum rarch_shader_type pass_type = gfx_shader_parse_type(shader->pass[i].source.path, - RARCH_SHADER_NONE); - - switch (pass_type) - { - case RARCH_SHADER_CG: - case RARCH_SHADER_GLSL: - if (type == RARCH_SHADER_NONE) - type = pass_type; - else if (type != pass_type) - return RARCH_SHADER_NONE; - break; - default: - return RARCH_SHADER_NONE; - } - } - - return type; -} - -static int menu_common_shader_manager_setting_toggle(unsigned id, unsigned action) -{ - if (!driver.menu) - { - RARCH_ERR("Cannot toggle shader setting, menu handle is not initialized.\n"); - return 0; - } - - rarch_setting_t *current_setting = NULL; - rarch_setting_t *setting_data = (rarch_setting_t *)setting_data_get_list(); - - unsigned dist_shader = id - MENU_SETTINGS_SHADER_0; - unsigned dist_filter = id - MENU_SETTINGS_SHADER_0_FILTER; - unsigned dist_scale = id - MENU_SETTINGS_SHADER_0_SCALE; - - if (id == MENU_SETTINGS_SHADER_FILTER) - { - if ((current_setting = setting_data_find_setting(setting_data, "video_smooth"))) - menu_common_setting_set_current_boolean(current_setting, action); - } - else if ((id == MENU_SETTINGS_SHADER_PARAMETERS - || id == MENU_SETTINGS_SHADER_PRESET_PARAMETERS)) - menu_common_setting_push_current_menu(driver.menu->menu_stack, "", - "shader_parameters", id, driver.menu->selection_ptr, action); - else if (id >= MENU_SETTINGS_SHADER_PARAMETER_0 && id <= MENU_SETTINGS_SHADER_PARAMETER_LAST) - { - struct gfx_shader *shader = NULL; - struct gfx_shader_parameter *param = NULL; - - if (!(shader = (struct gfx_shader*)driver.menu->parameter_shader)) - return 0; - - if (!(param = &shader->parameters[id - MENU_SETTINGS_SHADER_PARAMETER_0])) - return 0; - - switch (action) - { - case MENU_ACTION_START: - param->current = param->initial; - break; - - case MENU_ACTION_LEFT: - param->current -= param->step; - break; - - case MENU_ACTION_RIGHT: - param->current += param->step; - break; - - default: - break; - } - - param->current = min(max(param->minimum, param->current), param->maximum); - } - else if ((id == MENU_SETTINGS_SHADER_APPLY || id == MENU_SETTINGS_SHADER_PASSES)) - menu_common_setting_set(id, action); - else if (((dist_shader % 3) == 0 || id == MENU_SETTINGS_SHADER_PRESET)) - { - struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; - struct gfx_shader_pass *pass = NULL; - - dist_shader /= 3; - if (shader && id == MENU_SETTINGS_SHADER_PRESET) - pass = &shader->pass[dist_shader]; - - switch (action) - { - case MENU_ACTION_OK: - menu_common_setting_push_current_menu(driver.menu->menu_stack, - g_settings.video.shader_dir, "video_shader_preset", - id, driver.menu->selection_ptr, action); - break; - - case MENU_ACTION_START: - if (pass) - *pass->source.path = '\0'; - break; - - default: - break; - } - } - else if ((dist_filter % 3) == 0) - { - dist_filter /= 3; - struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; - struct gfx_shader_pass *pass = (struct gfx_shader_pass*)&shader->pass[dist_filter]; - - switch (action) - { - case MENU_ACTION_START: - if (shader && shader->pass) - shader->pass[dist_filter].filter = RARCH_FILTER_UNSPEC; - break; - - case MENU_ACTION_LEFT: - case MENU_ACTION_RIGHT: - case MENU_ACTION_OK: - { - unsigned delta = (action == MENU_ACTION_LEFT) ? 2 : 1; - if (pass) - pass->filter = ((pass->filter + delta) % 3); - break; - } - - default: - break; - } - } - else if ((dist_scale % 3) == 0) - { - dist_scale /= 3; - struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; - struct gfx_shader_pass *pass = (struct gfx_shader_pass*)&shader->pass[dist_scale]; - - switch (action) - { - case MENU_ACTION_START: - if (shader && shader->pass) - { - pass->fbo.scale_x = pass->fbo.scale_y = 0; - pass->fbo.valid = false; - } - break; - - case MENU_ACTION_LEFT: - case MENU_ACTION_RIGHT: - case MENU_ACTION_OK: - { - unsigned current_scale = pass->fbo.scale_x; - unsigned delta = action == MENU_ACTION_LEFT ? 5 : 1; - current_scale = (current_scale + delta) % 6; - - if (pass) - { - pass->fbo.valid = current_scale; - pass->fbo.scale_x = pass->fbo.scale_y = current_scale; - } - break; - } - - default: - break; - } - } - - return 0; -} -#endif - #ifdef GEKKO static unsigned menu_gx_resolutions[GX_RESOLUTIONS_LAST][2] = { { 512, 192 }, diff --git a/frontend/menu/backend/menu_common_shader_backend.c b/frontend/menu/backend/menu_common_shader_backend.c new file mode 100644 index 0000000000..8f5e8fad93 --- /dev/null +++ b/frontend/menu/backend/menu_common_shader_backend.c @@ -0,0 +1,441 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2014 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +static void menu_common_shader_manager_init(menu_handle_t *menu) +{ + char cgp_path[PATH_MAX]; + config_file_t *conf = NULL; + const char *config_path = NULL; + struct gfx_shader *shader = (struct gfx_shader*)menu->shader; + + if (*g_extern.core_specific_config_path && g_settings.core_specific_config) + config_path = g_extern.core_specific_config_path; + else if (*g_extern.config_path) + config_path = g_extern.config_path; + + // In a multi-config setting, we can't have conflicts on menu.cgp/menu.glslp. + if (config_path) + { + fill_pathname_base(menu->default_glslp, config_path, sizeof(menu->default_glslp)); + path_remove_extension(menu->default_glslp); + strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp)); + fill_pathname_base(menu->default_cgp, config_path, sizeof(menu->default_cgp)); + path_remove_extension(menu->default_cgp); + strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp)); + } + else + { + strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp)); + strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp)); + } + + + const char *ext = path_get_extension(g_settings.video.shader_path); + if (strcmp(ext, "glslp") == 0 || strcmp(ext, "cgp") == 0) + { + conf = config_file_new(g_settings.video.shader_path); + if (conf) + { + if (gfx_shader_read_conf_cgp(conf, shader)) + { + gfx_shader_resolve_relative(shader, g_settings.video.shader_path); + gfx_shader_resolve_parameters(conf, shader); + } + config_file_free(conf); + } + } + else if (strcmp(ext, "glsl") == 0 || strcmp(ext, "cg") == 0) + { + strlcpy(shader->pass[0].source.path, g_settings.video.shader_path, + sizeof(shader->pass[0].source.path)); + shader->passes = 1; + } + else + { + const char *shader_dir = *g_settings.video.shader_dir ? + g_settings.video.shader_dir : g_settings.system_directory; + + fill_pathname_join(cgp_path, shader_dir, "menu.glslp", sizeof(cgp_path)); + conf = config_file_new(cgp_path); + + if (!conf) + { + fill_pathname_join(cgp_path, shader_dir, "menu.cgp", sizeof(cgp_path)); + conf = config_file_new(cgp_path); + } + + if (conf) + { + if (gfx_shader_read_conf_cgp(conf, shader)) + { + gfx_shader_resolve_relative(shader, cgp_path); + gfx_shader_resolve_parameters(conf, shader); + } + config_file_free(conf); + } + } +} + +static void menu_common_shader_manager_set_preset(struct gfx_shader *shader, unsigned type, const char *cgp_path) +{ + RARCH_LOG("Setting Menu shader: %s.\n", cgp_path ? cgp_path : "N/A (stock)"); + + if (driver.video->set_shader && driver.video->set_shader(driver.video_data, (enum rarch_shader_type)type, cgp_path)) + { + // Makes sure that we use Menu CGP shader on driver reinit. + // Only do this when the cgp actually works to avoid potential errors. + strlcpy(g_settings.video.shader_path, cgp_path ? cgp_path : "", + sizeof(g_settings.video.shader_path)); + g_settings.video.shader_enable = true; + + if (cgp_path && shader) + { + // Load stored CGP into menu on success. + // Used when a preset is directly loaded. + // No point in updating when the CGP was created from the menu itself. + config_file_t *conf = config_file_new(cgp_path); + + if (conf) + { + if (gfx_shader_read_conf_cgp(conf, shader)) + { + gfx_shader_resolve_relative(shader, cgp_path); + gfx_shader_resolve_parameters(conf, shader); + } + config_file_free(conf); + } + + driver.menu->need_refresh = true; + } + } + else + { + RARCH_ERR("Setting Menu CGP failed.\n"); + g_settings.video.shader_enable = false; + } +} + +static void menu_common_shader_manager_get_str(struct gfx_shader *shader, char *type_str, size_t type_str_size, unsigned type) +{ + *type_str = '\0'; + + if (type >= MENU_SETTINGS_SHADER_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST) + { + // menu->parameter_shader here. + if (shader) + { + const struct gfx_shader_parameter *param = (const struct gfx_shader_parameter*)&shader->parameters[type - MENU_SETTINGS_SHADER_PARAMETER_0]; + snprintf(type_str, type_str_size, "%.2f [%.2f %.2f]", param->current, param->minimum, param->maximum); + } + } + else if (type == MENU_SETTINGS_SHADER_PASSES) + snprintf(type_str, type_str_size, "%u", shader->passes); + else if (type >= MENU_SETTINGS_SHADER_0 && type <= MENU_SETTINGS_SHADER_LAST) + { + unsigned pass = (type - MENU_SETTINGS_SHADER_0) / 3; + switch ((type - MENU_SETTINGS_SHADER_0) % 3) + { + case 0: + if (*shader->pass[pass].source.path) + fill_pathname_base(type_str, + shader->pass[pass].source.path, type_str_size); + else + strlcpy(type_str, "N/A", type_str_size); + break; + + case 1: + { + static const char *modes[] = { + "Don't care", + "Linear", + "Nearest" + }; + + strlcpy(type_str, modes[shader->pass[pass].filter], type_str_size); + } + break; + + case 2: + { + unsigned scale = shader->pass[pass].fbo.scale_x; + if (!scale) + strlcpy(type_str, "Don't care", type_str_size); + else + snprintf(type_str, type_str_size, "%ux", scale); + break; + } + } + } +} + +static void menu_common_shader_manager_save_preset(const char *basename, bool apply) +{ + char buffer[PATH_MAX], config_directory[PATH_MAX], cgp_path[PATH_MAX]; + unsigned d, type = RARCH_SHADER_NONE; + config_file_t *conf = NULL; + const char *conf_path = NULL; + bool ret = false; + + if (!driver.menu) + { + RARCH_ERR("Cannot save shader preset, menu handle is not initialized.\n"); + return; + } + + if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_get_type) + type = driver.menu_ctx->backend->shader_manager_get_type(driver.menu->shader); + + if (type == RARCH_SHADER_NONE) + return; + + conf_path = (type == RARCH_SHADER_GLSL) ? driver.menu->default_glslp : driver.menu->default_cgp; + *config_directory = '\0'; + + if (basename) + { + strlcpy(buffer, basename, sizeof(buffer)); + // Append extension automatically as appropriate. + if (!strstr(basename, ".cgp") && !strstr(basename, ".glslp")) + { + if (type == RARCH_SHADER_GLSL) + strlcat(buffer, ".glslp", sizeof(buffer)); + else if (type == RARCH_SHADER_CG) + strlcat(buffer, ".cgp", sizeof(buffer)); + } + } + + if (*g_extern.config_path) + fill_pathname_basedir(config_directory, g_extern.config_path, sizeof(config_directory)); + + const char *dirs[] = { + g_settings.video.shader_dir, + g_settings.menu_config_directory, + config_directory, + }; + + if (!(conf = (config_file_t*)config_file_new(NULL))) + return; + gfx_shader_write_conf_cgp(conf, driver.menu->shader); + + for (d = 0; d < ARRAY_SIZE(dirs); d++) + { + if (!*dirs[d]) + continue; + + fill_pathname_join(cgp_path, dirs[d], conf_path, sizeof(cgp_path)); + if (config_file_write(conf, cgp_path)) + { + RARCH_LOG("Saved shader preset to %s.\n", cgp_path); + if (apply) + { + if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_set_preset) + driver.menu_ctx->backend->shader_manager_set_preset(NULL, type, cgp_path); + } + ret = true; + break; + } + else + RARCH_LOG("Failed writing shader preset to %s.\n", cgp_path); + } + + config_file_free(conf); + if (!ret) + RARCH_ERR("Failed to save shader preset. Make sure config directory and/or shader dir are writable.\n"); +} + +static unsigned menu_common_shader_manager_get_type(const struct gfx_shader *shader) +{ + // All shader types must be the same, or we cannot use it. + unsigned i; + unsigned type = RARCH_SHADER_NONE; + + if (!shader) + { + RARCH_ERR("Cannot get shader type, shader handle is not initialized.\n"); + return RARCH_SHADER_NONE; + } + + for (i = 0; i < shader->passes; i++) + { + enum rarch_shader_type pass_type = gfx_shader_parse_type(shader->pass[i].source.path, + RARCH_SHADER_NONE); + + switch (pass_type) + { + case RARCH_SHADER_CG: + case RARCH_SHADER_GLSL: + if (type == RARCH_SHADER_NONE) + type = pass_type; + else if (type != pass_type) + return RARCH_SHADER_NONE; + break; + default: + return RARCH_SHADER_NONE; + } + } + + return type; +} + +static int menu_common_shader_manager_setting_toggle(unsigned id, unsigned action) +{ + if (!driver.menu) + { + RARCH_ERR("Cannot toggle shader setting, menu handle is not initialized.\n"); + return 0; + } + + rarch_setting_t *current_setting = NULL; + rarch_setting_t *setting_data = (rarch_setting_t *)setting_data_get_list(); + + unsigned dist_shader = id - MENU_SETTINGS_SHADER_0; + unsigned dist_filter = id - MENU_SETTINGS_SHADER_0_FILTER; + unsigned dist_scale = id - MENU_SETTINGS_SHADER_0_SCALE; + + if (id == MENU_SETTINGS_SHADER_FILTER) + { + if ((current_setting = setting_data_find_setting(setting_data, "video_smooth"))) + menu_common_setting_set_current_boolean(current_setting, action); + } + else if ((id == MENU_SETTINGS_SHADER_PARAMETERS + || id == MENU_SETTINGS_SHADER_PRESET_PARAMETERS)) + menu_common_setting_push_current_menu(driver.menu->menu_stack, "", + "shader_parameters", id, driver.menu->selection_ptr, action); + else if (id >= MENU_SETTINGS_SHADER_PARAMETER_0 && id <= MENU_SETTINGS_SHADER_PARAMETER_LAST) + { + struct gfx_shader *shader = NULL; + struct gfx_shader_parameter *param = NULL; + + if (!(shader = (struct gfx_shader*)driver.menu->parameter_shader)) + return 0; + + if (!(param = &shader->parameters[id - MENU_SETTINGS_SHADER_PARAMETER_0])) + return 0; + + switch (action) + { + case MENU_ACTION_START: + param->current = param->initial; + break; + + case MENU_ACTION_LEFT: + param->current -= param->step; + break; + + case MENU_ACTION_RIGHT: + param->current += param->step; + break; + + default: + break; + } + + param->current = min(max(param->minimum, param->current), param->maximum); + } + else if ((id == MENU_SETTINGS_SHADER_APPLY || id == MENU_SETTINGS_SHADER_PASSES)) + menu_common_setting_set(id, action); + else if (((dist_shader % 3) == 0 || id == MENU_SETTINGS_SHADER_PRESET)) + { + struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; + struct gfx_shader_pass *pass = NULL; + + dist_shader /= 3; + if (shader && id == MENU_SETTINGS_SHADER_PRESET) + pass = &shader->pass[dist_shader]; + + switch (action) + { + case MENU_ACTION_OK: + menu_common_setting_push_current_menu(driver.menu->menu_stack, + g_settings.video.shader_dir, "video_shader_preset", + id, driver.menu->selection_ptr, action); + break; + + case MENU_ACTION_START: + if (pass) + *pass->source.path = '\0'; + break; + + default: + break; + } + } + else if ((dist_filter % 3) == 0) + { + dist_filter /= 3; + struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; + struct gfx_shader_pass *pass = (struct gfx_shader_pass*)&shader->pass[dist_filter]; + + switch (action) + { + case MENU_ACTION_START: + if (shader && shader->pass) + shader->pass[dist_filter].filter = RARCH_FILTER_UNSPEC; + break; + + case MENU_ACTION_LEFT: + case MENU_ACTION_RIGHT: + case MENU_ACTION_OK: + { + unsigned delta = (action == MENU_ACTION_LEFT) ? 2 : 1; + if (pass) + pass->filter = ((pass->filter + delta) % 3); + break; + } + + default: + break; + } + } + else if ((dist_scale % 3) == 0) + { + dist_scale /= 3; + struct gfx_shader *shader = (struct gfx_shader*)driver.menu->shader; + struct gfx_shader_pass *pass = (struct gfx_shader_pass*)&shader->pass[dist_scale]; + + switch (action) + { + case MENU_ACTION_START: + if (shader && shader->pass) + { + pass->fbo.scale_x = pass->fbo.scale_y = 0; + pass->fbo.valid = false; + } + break; + + case MENU_ACTION_LEFT: + case MENU_ACTION_RIGHT: + case MENU_ACTION_OK: + { + unsigned current_scale = pass->fbo.scale_x; + unsigned delta = action == MENU_ACTION_LEFT ? 5 : 1; + current_scale = (current_scale + delta) % 6; + + if (pass) + { + pass->fbo.valid = current_scale; + pass->fbo.scale_x = pass->fbo.scale_y = current_scale; + } + break; + } + + default: + break; + } + } + + return 0; +}