diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index f2d4ac35df..e8637fbf32 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -1219,7 +1219,6 @@ typedef struct MTLALIGN(16) [self _freeVideoShader:_shader]; _shader = nil; - config_file_t *conf = video_shader_read_preset(path.UTF8String); struct video_shader *shader = (struct video_shader *)calloc(1, sizeof(*shader)); settings_t *settings = config_get_ptr(); const char *dir_video_shader = settings->paths.directory_video_shader; @@ -1229,7 +1228,7 @@ typedef struct MTLALIGN(16) { unsigned i; texture_t *source = NULL; - if (!video_shader_read_conf_preset(conf, shader)) + if (!video_shader_load_preset_into_shader(path.UTF8String, shader)) return NO; source = &_engine.frame.texture[0]; @@ -1429,8 +1428,6 @@ typedef struct MTLALIGN(16) /* TODO(sgc): generate mip maps */ image_texture_free(&image); } - - video_shader_resolve_current_parameters(conf, shader); _shader = shader; shader = nil; } @@ -1440,12 +1437,6 @@ typedef struct MTLALIGN(16) { [self _freeVideoShader:shader]; } - - if (conf) - { - config_file_free(conf); - conf = nil; - } } resize_render_targets = YES; diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index d7f97b75ec..4d95dcce05 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -336,7 +336,6 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const { #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) unsigned i; - config_file_t* conf = NULL; d3d10_texture_t* source = NULL; d3d10_video_t* d3d10 = (d3d10_video_t*)data; @@ -355,12 +354,9 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } - if (!(conf = video_shader_read_preset(path))) - return false; - d3d10->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d10->shader_preset)); - if (!video_shader_read_conf_preset(conf, d3d10->shader_preset)) + if (!video_shader_load_preset_into_shader(path, d3d10->shader_preset)) goto error; source = &d3d10->frame.texture[0]; @@ -508,9 +504,6 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const image_texture_free(&image); } - video_shader_resolve_current_parameters(conf, d3d10->shader_preset); - config_file_free(conf); - d3d10->resize_render_targets = true; d3d10->init_history = true; diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 8b6ee3ad1d..19620b0f66 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -359,7 +359,6 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const { #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) unsigned i; - config_file_t* conf = NULL; d3d11_texture_t* source = NULL; d3d11_video_t* d3d11 = (d3d11_video_t*)data; @@ -378,12 +377,9 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } - if (!(conf = video_shader_read_preset(path))) - return false; - d3d11->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d11->shader_preset)); - if (!video_shader_read_conf_preset(conf, d3d11->shader_preset)) + if (!video_shader_load_preset_into_shader(path, d3d11->shader_preset)) goto error; source = &d3d11->frame.texture[0]; @@ -529,9 +525,6 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const image_texture_free(&image); } - video_shader_resolve_current_parameters(conf, d3d11->shader_preset); - config_file_free(conf); - d3d11->resize_render_targets = true; d3d11->init_history = true; diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 806241b58f..b1b0210a63 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -343,7 +343,6 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const { #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) unsigned i; - config_file_t* conf = NULL; d3d12_texture_t* source = NULL; d3d12_video_t* d3d12 = (d3d12_video_t*)data; @@ -362,12 +361,9 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } - if (!(conf = video_shader_read_preset(path))) - return false; - d3d12->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d12->shader_preset)); - if (!video_shader_read_conf_preset(conf, d3d12->shader_preset)) + if (!video_shader_load_preset_into_shader(path, d3d12->shader_preset)) goto error; source = &d3d12->frame.texture[0]; @@ -535,9 +531,6 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const image_texture_free(&image); } - video_shader_resolve_current_parameters(conf, d3d12->shader_preset); - config_file_free(conf); - d3d12->resize_render_targets = true; d3d12->init_history = true; diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index f05e74d56d..6f43460fce 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -324,25 +324,15 @@ static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path) unsigned i; bool use_extra_pass = false; struct video_shader_pass *pass = NULL; - config_file_t *conf = video_shader_read_preset(shader_path); - - if (!conf) - { - RARCH_ERR("[D3D9]: Failed to load preset.\n"); - return false; - } memset(&d3d->shader, 0, sizeof(d3d->shader)); - if (!video_shader_read_conf_preset(conf, &d3d->shader)) + if (!video_shader_load_preset_into_shader(shader_path, &d3d->shader)) { - config_file_free(conf); RARCH_ERR("[D3D9]: Failed to parse shader preset.\n"); return false; } - config_file_free(conf); - RARCH_LOG("[D3D9]: Found %u shaders.\n", d3d->shader.passes); for (i = 0; i < d3d->shader.passes; i++) @@ -1732,7 +1722,7 @@ static bool d3d9_set_shader(void *data, if (type != supported_shader_type) { RARCH_WARN("[D3D9]: Shader preset %s is using unsupported shader type %s, falling back to stock %s.\n", - path, video_shader_to_str(type), video_shader_to_str(supported_shader_type)); + path, video_shader_type_to_str(type), video_shader_type_to_str(supported_shader_type)); break; } diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index 346dce5555..4bee995ac1 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -2041,7 +2041,7 @@ static bool gl2_shader_init(gl_t *gl, const gfx_ctx_driver_t *ctx_driver, { if (!string_is_empty(shader_path)) RARCH_WARN("[GL] Shader preset %s is using unsupported shader type %s, falling back to stock %s.\n", - shader_path, video_shader_to_str(parse_type), video_shader_to_str(type)); + shader_path, video_shader_type_to_str(parse_type), video_shader_type_to_str(type)); shader_path = NULL; } @@ -4089,7 +4089,7 @@ static bool gl2_set_shader(void *data, if (type != fallback) { RARCH_ERR("[GL]: %s shader not supported, falling back to stock %s\n", - video_shader_to_str(type), video_shader_to_str(fallback)); + video_shader_type_to_str(type), video_shader_type_to_str(fallback)); path = NULL; } diff --git a/gfx/drivers/gx2_gfx.c b/gfx/drivers/gx2_gfx.c index 834caec0fe..88c3125c47 100644 --- a/gfx/drivers/gx2_gfx.c +++ b/gfx/drivers/gx2_gfx.c @@ -1428,7 +1428,6 @@ static bool wiiu_gfx_set_shader(void *data, enum rarch_shader_type type, const char *path) { unsigned i; - config_file_t *conf = NULL; wiiu_video_t *wiiu = (wiiu_video_t *)data; if (!wiiu) @@ -1446,24 +1445,15 @@ static bool wiiu_gfx_set_shader(void *data, return false; } - if (!(conf = video_shader_read_preset(path))) - return false; - wiiu->shader_preset = calloc(1, sizeof(*wiiu->shader_preset)); - if (!video_shader_read_conf_preset(conf, wiiu->shader_preset)) + if (!video_shader_load_preset_into_shader(path, wiiu->shader_preset)) { free(wiiu->shader_preset); wiiu->shader_preset = NULL; return false; } - for (i = 0; i < wiiu->shader_preset->passes; i++) - slang_preprocess_parse_parameters(wiiu->shader_preset->pass[i].source.path, wiiu->shader_preset); - - video_shader_resolve_current_parameters(conf, wiiu->shader_preset); - config_file_free(conf); - for (i = 0; i < wiiu->shader_preset->passes; i++) { unsigned j; diff --git a/gfx/drivers_shader/shader_gl_cg.c b/gfx/drivers_shader/shader_gl_cg.c index e8f06f74e0..429fbcff2a 100644 --- a/gfx/drivers_shader/shader_gl_cg.c +++ b/gfx/drivers_shader/shader_gl_cg.c @@ -664,7 +664,8 @@ static bool gl_cg_load_plain(void *data, const char *path) return false; } - video_shader_resolve_parameters(NULL, cg->shader); + video_shader_resolve_parameters(cg->shader); + video_shader_load_current_parameter_values(NULL, cg->shader); return true; } @@ -688,37 +689,25 @@ static bool gl_cg_load_shader(void *data, unsigned i) static bool gl_cg_load_preset(void *data, const char *path) { unsigned i; - config_file_t *conf = NULL; cg_shader_data_t *cg = (cg_shader_data_t*)data; if (!gl_cg_load_stock(cg)) return false; RARCH_LOG("[CG]: Loading Cg meta-shader: %s\n", path); - conf = video_shader_read_preset(path); - if (!conf) - { - RARCH_ERR("Failed to load preset.\n"); - return false; - } cg->shader = (struct video_shader*)calloc(1, sizeof(*cg->shader)); if (!cg->shader) { - config_file_free(conf); return false; } - if (!video_shader_read_conf_preset(conf, cg->shader)) + if (!video_shader_load_preset_into_shader(path, cg->shader)) { RARCH_ERR("Failed to parse CGP file.\n"); - config_file_free(conf); return false; } - video_shader_resolve_parameters(conf, cg->shader); - config_file_free(conf); - if (cg->shader->passes > GFX_MAX_SHADERS - 3) { RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", diff --git a/gfx/drivers_shader/shader_gl_core.cpp b/gfx/drivers_shader/shader_gl_core.cpp index a8baa5ce89..ca6f8cd286 100644 --- a/gfx/drivers_shader/shader_gl_core.cpp +++ b/gfx/drivers_shader/shader_gl_core.cpp @@ -2158,20 +2158,13 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset( const char *path, glslang_filter_chain_filter filter) { unsigned i; - config_file_t *conf = NULL; unique_ptr shader{ new video_shader() }; if (!shader) return nullptr; - if (!(conf = video_shader_read_preset(path))) + if (!video_shader_load_preset_into_shader(path, shader.get())) return nullptr; - if (!video_shader_read_conf_preset(conf, shader.get())) - { - config_file_free(conf); - return nullptr; - } - bool last_pass_is_fbo = shader->pass[shader->passes - 1].fbo.valid; unique_ptr chain{ new gl_core_filter_chain(shader->passes + (last_pass_is_fbo ? 1 : 0)) }; @@ -2203,7 +2196,7 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset( if (!glslang_compile_shader(pass->source.path, &output)) { - RARCH_ERR("Failed to compile shader: \"%s\".\n", + RARCH_ERR("[GLCore]: Failed to compile shader: \"%s\".\n", pass->source.path); goto error; } @@ -2212,7 +2205,7 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset( { if (shader->num_parameters >= GFX_MAX_PARAMETERS) { - RARCH_ERR("[GLCore]: Exceeded maximum number of parameters.\n"); + RARCH_ERR("[GLCore]: Exceeded maximum number of parameters (%u).\n", GFX_MAX_PARAMETERS); goto error; } @@ -2243,11 +2236,6 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset( video_shader_parameter *param = &shader->parameters[shader->num_parameters]; strlcpy(param->id, meta_param.id.c_str(), sizeof(param->id)); strlcpy(param->desc, meta_param.desc.c_str(), sizeof(param->desc)); - param->current = meta_param.initial; - param->initial = meta_param.initial; - param->minimum = meta_param.minimum; - param->maximum = meta_param.maximum; - param->step = meta_param.step; chain->add_parameter(i, shader->num_parameters, meta_param.id); shader->num_parameters++; } @@ -2415,19 +2403,14 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset( sizeof(gl_core_shader::opaque_frag) / sizeof(uint32_t)); } - if (!video_shader_resolve_current_parameters(conf, shader.get())) - goto error; - chain->set_shader_preset(move(shader)); if (!chain->init()) goto error; - config_file_free(conf); return chain.release(); error: - config_file_free(conf); return nullptr; } diff --git a/gfx/drivers_shader/shader_glsl.c b/gfx/drivers_shader/shader_glsl.c index 9f4b7756cd..28b5135bbb 100644 --- a/gfx/drivers_shader/shader_glsl.c +++ b/gfx/drivers_shader/shader_glsl.c @@ -856,7 +856,6 @@ static void *gl_glsl_init(void *data, const char *path) #ifdef GLSL_DEBUG char *error_string = NULL; #endif - config_file_t *conf = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; glsl_shader_data_t *glsl = (glsl_shader_data_t*) @@ -910,12 +909,8 @@ static void *gl_glsl_init(void *data, const char *path) if (is_preset) { - conf = video_shader_read_preset(path); - if (conf) - { - ret = video_shader_read_conf_preset(conf, glsl->shader); - glsl->shader->modern = true; - } + ret = video_shader_load_preset_into_shader(path, glsl->shader); + glsl->shader->modern = true; } else { @@ -944,14 +939,6 @@ static void *gl_glsl_init(void *data, const char *path) } } - video_shader_resolve_parameters(conf, glsl->shader); - - if (conf) - { - config_file_free(conf); - conf = NULL; - } - stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? @@ -1067,8 +1054,6 @@ static void *gl_glsl_init(void *data, const char *path) error: gl_glsl_destroy_resources(glsl); - if (conf) - config_file_free(conf); if (glsl) free(glsl); diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 72c4dae5a8..d349c5a821 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -2565,19 +2565,13 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( const char *path, glslang_filter_chain_filter filter) { unsigned i; - config_file_t *conf = NULL; unique_ptr shader{ new video_shader() }; + if (!shader) return nullptr; - if (!(conf = video_shader_read_preset(path))) - return nullptr; - - if (!video_shader_read_conf_preset(conf, shader.get())) - { - config_file_free(conf); - return nullptr; - } + if (!video_shader_load_preset_into_shader(path, shader.get())) + return nullptr; bool last_pass_is_fbo = shader->pass[shader->passes - 1].fbo.valid; auto tmpinfo = *info; @@ -2612,7 +2606,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( if (!glslang_compile_shader(pass->source.path, &output)) { - RARCH_ERR("Failed to compile shader: \"%s\".\n", + RARCH_ERR("[Vulkan]: Failed to compile shader: \"%s\".\n", pass->source.path); goto error; } @@ -2621,7 +2615,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( { if (shader->num_parameters >= GFX_MAX_PARAMETERS) { - RARCH_ERR("[Vulkan]: Exceeded maximum number of parameters.\n"); + RARCH_ERR("[Vulkan]: Exceeded maximum number of parameters (%u).\n", GFX_MAX_PARAMETERS); goto error; } @@ -2652,11 +2646,6 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( video_shader_parameter *param = &shader->parameters[shader->num_parameters]; strlcpy(param->id, meta_param.id.c_str(), sizeof(param->id)); strlcpy(param->desc, meta_param.desc.c_str(), sizeof(param->desc)); - param->current = meta_param.initial; - param->initial = meta_param.initial; - param->minimum = meta_param.minimum; - param->maximum = meta_param.maximum; - param->step = meta_param.step; chain->add_parameter(i, shader->num_parameters, meta_param.id); shader->num_parameters++; } @@ -2820,19 +2809,14 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( sizeof(opaque_frag) / sizeof(uint32_t)); } - if (!video_shader_resolve_current_parameters(conf, shader.get())) - goto error; - chain->set_shader_preset(move(shader)); if (!chain->init()) goto error; - config_file_free(conf); return chain.release(); error: - config_file_free(conf); return nullptr; } diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 11159f61a4..37743a9704 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -43,9 +43,42 @@ #include "drivers_shader/slang_process.h" #endif +/* Maximum depth of chain of referenced shader presets. + * 16 seems to be a very large number of references at the moment. */ +#define SHADER_MAX_REFERENCE_DEPTH 16 + /* TODO/FIXME - global state - perhaps move outside this file */ static path_change_data_t *file_change_data = NULL; +/** + * fill_pathname_expanded_and_absolute: + * @out_path : string to write into + * @in_refpath : used to get the base path if in_path is relative + * @in_path : path to turn into an absolute path + * + * Takes a path and returns an absolute path, + * It will expand it if the path was using the root path format e.g. :\shaders + * If the path was relative it will take this path and get the absolute path using in_refpath + * as the path to extract a base path + * + * out_path is filled with the absolute path + **/ +void fill_pathname_expanded_and_absolute(char *out_path, const char *in_refpath, const char *in_path) +{ + char expanded_path[PATH_MAX_LENGTH]; + + expanded_path[0] = '\0'; + + /* Expand paths which start with :\ to an absolute path */ + fill_pathname_expand_special(expanded_path, in_path, sizeof(expanded_path)); + + /* Resolve the reference path relative to the config */ + if (path_is_absolute(expanded_path)) + strlcpy(out_path, expanded_path, PATH_MAX_LENGTH); + else + fill_pathname_resolve_relative(out_path, in_refpath, in_path, PATH_MAX_LENGTH); +} + /** * wrap_mode_to_str: * @type : Wrap type. @@ -108,8 +141,7 @@ static enum gfx_wrap_type wrap_str_to_mode(const char *wrap_mode) * * Returns: true (1) if successful, otherwise false (0). **/ -static bool video_shader_parse_pass(config_file_t *conf, - struct video_shader_pass *pass, unsigned i) +static bool video_shader_parse_pass(config_file_t *conf, struct video_shader_pass *pass, unsigned i) { char shader_name[64]; char filter_name_buf[64]; @@ -125,12 +157,11 @@ static bool video_shader_parse_pass(config_file_t *conf, char scale_type_x[64]; char scale_type_y[64]; char tmp_path[PATH_MAX_LENGTH]; - struct gfx_fbo_scale *scale = NULL; - bool tmp_bool = false; - float fattr = 0.0f; - int iattr = 0; - struct config_entry_list - *entry = NULL; + struct gfx_fbo_scale *scale = NULL; + bool tmp_bool = false; + float fattr = 0.0f; + int iattr = 0; + struct config_entry_list *entry = NULL; fp_fbo_buf[0] = mipmap_buf[0] = alias_buf[0] = scale_name_buf[0] = attr_name_buf[0] = scale_type[0] = @@ -146,8 +177,8 @@ static bool video_shader_parse_pass(config_file_t *conf, return false; } - fill_pathname_resolve_relative(pass->source.path, - conf->path, tmp_path, sizeof(pass->source.path)); + /* Get the absolute path */ + fill_pathname_expanded_and_absolute(pass->source.path, conf->path, tmp_path); /* Smooth */ snprintf(filter_name_buf, sizeof(filter_name_buf), "filter_linear%u", i); @@ -161,18 +192,14 @@ static bool video_shader_parse_pass(config_file_t *conf, pass->filter = RARCH_FILTER_UNSPEC; /* Wrapping mode */ - snprintf(wrap_name_buf, - sizeof(wrap_name_buf), "wrap_mode%u", i); - if ((entry = config_get_entry(conf, wrap_name_buf)) - && !string_is_empty(entry->value)) + snprintf(wrap_name_buf, sizeof(wrap_name_buf), "wrap_mode%u", i); + if ((entry = config_get_entry(conf, wrap_name_buf)) && !string_is_empty(entry->value)) pass->wrap = wrap_str_to_mode(entry->value); entry = NULL; /* Frame count mod */ - snprintf(frame_count_mod_buf, - sizeof(frame_count_mod_buf), "frame_count_mod%u", i); - if ((entry = config_get_entry(conf, frame_count_mod_buf)) - && !string_is_empty(entry->value)) + snprintf(frame_count_mod_buf, sizeof(frame_count_mod_buf), "frame_count_mod%u", i); + if ((entry = config_get_entry(conf, frame_count_mod_buf)) && !string_is_empty(entry->value)) pass->frame_count_mod = (unsigned)strtoul(entry->value, NULL, 0); entry = NULL; @@ -311,18 +338,19 @@ static bool video_shader_parse_pass(config_file_t *conf, * * Returns: true (1) if successful, otherwise false (0). **/ -static bool video_shader_parse_textures(config_file_t *conf, - struct video_shader *shader) +static bool video_shader_parse_textures(config_file_t *conf, struct video_shader *shader) { size_t path_size = PATH_MAX_LENGTH; const char *id = NULL; char *save = NULL; char *textures = (char*)malloc(1024 + path_size); + char texture_path[PATH_MAX_LENGTH]; if (!textures) return false; textures[0] = '\0'; + texture_path[0] = '\0'; if (!config_get_array(conf, "textures", textures, 1024)) { @@ -352,8 +380,11 @@ static bool video_shader_parse_textures(config_file_t *conf, return false; } - fill_pathname_resolve_relative(shader->lut[shader->luts].path, - conf->path, entry->value, sizeof(shader->lut[shader->luts].path)); + config_get_path(conf, id, texture_path, sizeof(texture_path)); + + /* Get the absolute path */ + fill_pathname_expanded_and_absolute(shader->lut[shader->luts].path, conf->path, texture_path); + entry = NULL; strlcpy(shader->lut[shader->luts].id, id, @@ -362,15 +393,13 @@ static bool video_shader_parse_textures(config_file_t *conf, strlcpy(id_filter, id, sizeof(id_filter)); strlcat(id_filter, "_linear", sizeof(id_filter)); if (config_get_bool(conf, id_filter, &smooth)) - shader->lut[shader->luts].filter = smooth ? - RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST; + shader->lut[shader->luts].filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST; else shader->lut[shader->luts].filter = RARCH_FILTER_UNSPEC; strlcpy(id_wrap, id, sizeof(id_wrap)); strlcat(id_wrap, "_wrap_mode", sizeof(id_wrap)); - if ((entry = config_get_entry(conf, id_wrap)) - && !string_is_empty(entry->value)) + if ((entry = config_get_entry(conf, id_wrap)) && !string_is_empty(entry->value)) shader->lut[shader->luts].wrap = wrap_str_to_mode(entry->value); entry = NULL; @@ -396,9 +425,8 @@ static bool video_shader_parse_textures(config_file_t *conf, * * Returns: handle to shader parameter if successful, otherwise NULL. **/ -static struct video_shader_parameter *video_shader_parse_find_parameter( - struct video_shader_parameter *params, - unsigned num_params, const char *id) +static struct video_shader_parameter *video_shader_parse_find_parameter(struct video_shader_parameter *params, + unsigned num_params, const char *id) { unsigned i; @@ -411,64 +439,17 @@ static struct video_shader_parameter *video_shader_parse_find_parameter( return NULL; } -/** - * video_shader_set_current_parameters: - * @conf : Preset file to read from. - * @shader : Shader passes handle. - * - * For each parameter in the shader, if a value is set in the config file - * load this value to the parameter's current value. - * - * Returns: true (1) if successful, otherwise false (0). - **/ -bool video_shader_resolve_current_parameters(config_file_t *conf, - struct video_shader *shader) -{ - unsigned i; - const struct config_entry_list *entry = NULL; - - if (!conf) - return false; - - /* For all parameters in the shader see if there is any config value set */ - for (i = 0; i < shader->num_parameters; i++) - { - entry = config_get_entry(conf, shader->parameters[i].id); - - /* Only try to load the parameter value if an entry exists in the config */ - if (entry) - { - struct video_shader_parameter *parameter = - (struct video_shader_parameter*) - video_shader_parse_find_parameter( - shader->parameters, shader->num_parameters, shader->parameters[i].id); - - if (config_get_float(conf, shader->parameters[i].id, ¶meter->current)) - RARCH_LOG("[ Shaders - Load Parameter Values]: %s = %f.\n", - shader->parameters[i].id, parameter->current); - else - RARCH_WARN("[ Shaders - Load Parameter Values]: Name %s is set in preset " - "but couldn't load its value.\n", shader->parameters[i].id); - } - } - - return true; -} - /** * video_shader_resolve_parameters: * @conf : Preset file to read from. * @shader : Shader passes handle. * - * Resolves all shader parameters belonging to shaders. - * Fills the parameter definition list of the shader - * then calls video_shader_resolve_current_parameters to - * read in the config parameter values + * Resolves all shader parameters belonging to shaders + * from the #pragma parameter lines in the shader for each pass. * * Returns: true (1) if successful, otherwise false (0). **/ -bool video_shader_resolve_parameters(config_file_t *conf, - struct video_shader *shader) +bool video_shader_resolve_parameters(struct video_shader *shader) { unsigned i; struct video_shader_parameter *param = &shader->parameters[0]; @@ -477,6 +458,8 @@ bool video_shader_resolve_parameters(config_file_t *conf, /* Find all parameters in our shaders. */ + RARCH_LOG("[ Shaders ]: Finding Parameters in Shader Passes (#pragma parameter)\n"); + for (i = 0; i < shader->passes; i++) { const char *path = shader->pass[i].source.path; @@ -492,18 +475,15 @@ bool video_shader_resolve_parameters(config_file_t *conf, if (!path_is_valid(path)) continue; +/* First try to use the more robust slang implementation to support #includes. */ #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) - /* First try to use the more robust slang - * implementation to support #includes. */ /* FIXME: The check for slang can be removed - * if it's sufficiently tested for - * GLSL/Cg as well, it should be the same implementation. */ - if (string_is_equal(path_get_extension(path), "slang") && - slang_preprocess_parse_parameters(path, shader)) - continue; + * if it's sufficiently tested for GLSL/Cg as well, it should be the same implementation. + * The problem with switching currently is that it looks for a #version string in the + * first line of the file which glsl doesn't have */ - /* If that doesn't work, fallback to the old path. - * Ideally, we'd get rid of this path sooner or later. */ + if (string_is_equal(path_get_extension(path), "slang") && slang_preprocess_parse_parameters(path, shader)) + continue; #endif /* Read file contents */ @@ -527,22 +507,20 @@ bool video_shader_resolve_parameters(config_file_t *conf, /* even though the pass is set in the loop too, not all passes have parameters */ param->pass = i; - while ((shader->num_parameters < ARRAY_SIZE(shader->parameters)) && - (line_index < lines.size)) + while ((shader->num_parameters < ARRAY_SIZE(shader->parameters)) && (line_index < lines.size)) { int ret; const char *line = lines.elems[line_index].data; line_index++; /* Check if this is a '#pragma parameter' line */ - if (strncmp("#pragma parameter", line, - STRLEN_CONST("#pragma parameter"))) + if (strncmp("#pragma parameter", line, STRLEN_CONST("#pragma parameter"))) continue; /* Parse line */ ret = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", - param->id, param->desc, ¶m->initial, - ¶m->minimum, ¶m->maximum, ¶m->step); + param->id, param->desc, ¶m->initial, + ¶m->minimum, ¶m->maximum, ¶m->step); if (ret < 5) continue; @@ -555,7 +533,7 @@ bool video_shader_resolve_parameters(config_file_t *conf, param->pass = i; - RARCH_LOG("[ Shaders ]: Found #pragma parameter %s (%s) %f %f %f %f in pass %d\n", + RARCH_LOG("[ Shaders ]: Found #pragma parameter %s (%s) %f %f %f %f in pass %d\n", param->desc, param->id, param->initial, param->minimum, param->maximum, param->step, param->pass); param->current = param->initial; @@ -567,19 +545,329 @@ bool video_shader_resolve_parameters(config_file_t *conf, string_list_deinitialize(&lines); } - return video_shader_resolve_current_parameters(conf, shader); + return true; } -#ifdef _WIN32 -static void make_relative_path_portable(char* path) + +/** + * video_shader_load_current_parameter_values: + * @conf : Preset file to read from. + * @shader : Shader passes handle. + * + * For each parameter in the shader, if a value is set in the config file + * load this value to the parameter's current value. + * + * Returns: true (1) if successful, otherwise false (0). + **/ +bool video_shader_load_current_parameter_values(config_file_t *conf, struct video_shader *shader) { - /* use '/' instead of '\' for maximum portability */ - char* p; - for (p = path; *p; p++) - if (*p == '\\') - *p = '/'; + unsigned i; + bool load_parameter_message_shown = false; + const struct config_entry_list *entry = NULL; + + if (!conf) + { + RARCH_ERR("[ Shaders ]: Load Parameter Values - Config is Null.\n"); + return false; + } + + /* For all parameters in the shader see if there is any config value set */ + for (i = 0; i < shader->num_parameters; i++) + { + entry = config_get_entry(conf, shader->parameters[i].id); + + /* Only try to load the parameter value if an entry exists in the config */ + if (entry) + { + struct video_shader_parameter *parameter = (struct video_shader_parameter*) + video_shader_parse_find_parameter(shader->parameters, + shader->num_parameters, + shader->parameters[i].id); + /* Log the message for loading parameter values only once*/ + if (!load_parameter_message_shown) + { + RARCH_LOG("[ Shaders ]: Loading base parameter values\n"); + load_parameter_message_shown = true; + } + + /* Log each parameter read */ + if (config_get_float(conf, shader->parameters[i].id, ¶meter->current)) + RARCH_LOG("[ Shaders ]: Load parameter value: %s = %f.\n", shader->parameters[i].id, parameter->current); + else + RARCH_WARN("[ Shaders ]: Load parameter value: name %s is set in preset but couldn't load its value.\n", + shader->parameters[i].id); + } + } + + return true; +} + +static const char *scale_type_to_str(enum gfx_scale_type type) +{ + switch (type) + { + case RARCH_SCALE_INPUT: + return "source"; + case RARCH_SCALE_VIEWPORT: + return "viewport"; + case RARCH_SCALE_ABSOLUTE: + return "absolute"; + default: + break; + } + + return "?"; +} + +static void shader_write_scale_dim(config_file_t *conf, + const char *dim, + enum gfx_scale_type type, + float scale, + unsigned absolute, + unsigned i) +{ + char key[64]; + + key[0] = '\0'; + + snprintf(key, sizeof(key), "scale_type_%s%u", dim, i); + config_set_string(conf, key, scale_type_to_str(type)); + + snprintf(key, sizeof(key), "scale_%s%u", dim, i); + if (type == RARCH_SCALE_ABSOLUTE) + config_set_int(conf, key, absolute); + else + config_set_float(conf, key, scale); +} + +static void shader_write_fbo(config_file_t *conf, const struct gfx_fbo_scale *fbo, unsigned i) +{ + char key[64]; + + key[0] = '\0'; + + snprintf(key, sizeof(key), "float_framebuffer%u", i); + config_set_bool(conf, key, fbo->fp_fbo); + snprintf(key, sizeof(key), "srgb_framebuffer%u", i); + config_set_bool(conf, key, fbo->srgb_fbo); + + if (!fbo->valid) + return; + + shader_write_scale_dim(conf, "x", fbo->type_x, fbo->scale_x, fbo->abs_x, i); + shader_write_scale_dim(conf, "y", fbo->type_y, fbo->scale_y, fbo->abs_y, i); +} + +/** + * video_shader_write_root_preset: + * @conf : Preset file to write to. + * @shader : Shader passes handle. + * @preset_path : Optional path to where the preset will be written. + * + * Writes preset and all associated state (passes, textures, imports, etc) into @conf. + * If @preset_path is not NULL, shader paths are saved relative to it. + **/ +bool video_shader_write_root_preset(const struct video_shader *shader, const char *path) +{ + bool ret = true; + unsigned i; + char key[64]; + size_t tmp_size = PATH_MAX_LENGTH; + char *tmp = (char*)malloc(3*tmp_size); + char *tmp_rel = tmp + tmp_size; + char *tmp_base = tmp + 2*tmp_size; + config_file_t *conf = NULL; + + if (!path) + { + ret = false; + goto end; + } + + if (!(conf = config_file_new_alloc())) + { + ret = false; + goto end; + } + + if (!tmp) + { + ret = false; + goto end; + } + + RARCH_LOG("[ Shaders ]: Saving FULL PRESET to: %s\n", path); + + config_set_int(conf, "shaders", shader->passes); + if (shader->feedback_pass >= 0) + config_set_int(conf, "feedback_pass", shader->feedback_pass); + + strlcpy(tmp_base, path, tmp_size); + + /* ensure we use a clean base like the shader passes and texture paths do */ + path_resolve_realpath(tmp_base, tmp_size, false); + path_basedir(tmp_base); + + for (i = 0; i < shader->passes; i++) + { + const struct video_shader_pass *pass = &shader->pass[i]; + + snprintf(key, sizeof(key), "shader%u", i); + + strlcpy(tmp, pass->source.path, tmp_size); + path_relative_to(tmp_rel, tmp, tmp_base, tmp_size); + + pathname_make_slashes_portable(tmp_rel); + + config_set_path(conf, key, tmp_rel); + + + if (pass->filter != RARCH_FILTER_UNSPEC) + { + snprintf(key, sizeof(key), "filter_linear%u", i); + config_set_bool(conf, key, pass->filter == RARCH_FILTER_LINEAR); + } + + snprintf(key, sizeof(key), "wrap_mode%u", i); + config_set_string(conf, key, wrap_mode_to_str(pass->wrap)); + + if (pass->frame_count_mod) + { + snprintf(key, sizeof(key), "frame_count_mod%u", i); + config_set_int(conf, key, pass->frame_count_mod); + } + + snprintf(key, sizeof(key), "mipmap_input%u", i); + config_set_bool(conf, key, pass->mipmap); + + snprintf(key, sizeof(key), "alias%u", i); + config_set_string(conf, key, pass->alias); + + shader_write_fbo(conf, &pass->fbo, i); + } + + /* Write shader parameters which are different than the default shader values */ + if (shader->num_parameters) + for (i = 0; i < shader->num_parameters; i++) + if (shader->parameters[i].current != shader->parameters[i].initial) + config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current); + + if (shader->luts) + { + char textures[4096]; + + textures[0] = '\0'; + + /* Names of the textures */ + strlcpy(textures, shader->lut[0].id, sizeof(textures)); + + for (i = 1; i < shader->luts; i++) + { + /* O(n^2), but number of textures is very limited. */ + strlcat(textures, ";", sizeof(textures)); + strlcat(textures, shader->lut[i].id, sizeof(textures)); + } + + config_set_string(conf, "textures", textures); + + /* Step through the textures in the shader */ + for (i = 0; i < shader->luts; i++) + { + fill_pathname_abbreviated_or_relative(tmp_rel, tmp_base, shader->lut[i].path, PATH_MAX_LENGTH); + pathname_make_slashes_portable(tmp_rel); + config_set_string(conf, shader->lut[i].id, tmp_rel); + + /* Linear filter ON or OFF */ + if (shader->lut[i].filter != RARCH_FILTER_UNSPEC) + { + char key[128]; + key[0] = '\0'; + strlcpy(key, shader->lut[i].id, sizeof(key)); + strlcat(key, "_linear", sizeof(key)); + config_set_bool(conf, key, shader->lut[i].filter == RARCH_FILTER_LINEAR); + } + + /* Wrap Mode */ + { + char key[128]; + key[0] = '\0'; + strlcpy(key, shader->lut[i].id, sizeof(key)); + strlcat(key, "_wrap_mode", sizeof(key)); + config_set_string(conf, key, wrap_mode_to_str(shader->lut[i].wrap)); + } + + /* Mipmap On or Off */ + { + char key[128]; + key[0] = '\0'; + strlcpy(key, shader->lut[i].id, sizeof(key)); + strlcat(key, "_mipmap", sizeof(key)); + config_set_bool(conf, key, shader->lut[i].mipmap); + } + } + } + + /* Write the File! */ + ret = config_file_write(conf, path, false); + + end: + + config_file_free(conf); + free(tmp); + + return ret; +} + + +config_file_t *video_shader_get_root_preset_config(const char *path) +{ + config_file_t *conf = config_file_new_from_path_to_string(path); + char* nested_reference_path = (char*)malloc(PATH_MAX_LENGTH); + + if (!conf) + goto end; + else + { + int reference_depth = 1; + + while (conf->reference) + { + /* If we have reached the max depth of nested references stop attempting to read + * the next reference because we are likely in a self referential loop. + * SHADER_MAX_REFERENCE_DEPTH references deep seems like more than enough depth for expected usage */ + if (reference_depth > SHADER_MAX_REFERENCE_DEPTH) + { + RARCH_ERR("[ Shaders - Get Root Preset ]: Exceeded maximum reference depth(%u) without finding a full preset. " + "This chain of referenced presets is likely cyclical.\n", SHADER_MAX_REFERENCE_DEPTH); + config_file_free(conf); + conf = NULL; + goto end; + } + + /* Get the absolute path for the reference */ + fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->reference); + + /* Create a new config from the referenced path */ + config_file_free(conf); + conf = config_file_new_from_path_to_string(nested_reference_path); + + /* If we can't read the reference preset */ + if (!conf) + { + RARCH_WARN("[ Shaders ]: Could not read shader preset in #reference line: %s\n", nested_reference_path); + goto end; + } + + reference_depth += 1; + } + } + + end: + + free(nested_reference_path); + + return conf; } -#endif /** * video_shader_check_reference_chain: @@ -615,6 +903,7 @@ bool video_shader_check_reference_chain_for_save(const char *path_to_save, const if (!conf) { + RARCH_ERR("[ Shaders ]: Could not read the #reference preset: %s\n", reference_path); return_val = false; } else @@ -624,32 +913,23 @@ bool video_shader_check_reference_chain_for_save(const char *path_to_save, const while (conf->reference) { /* If we have reached the max depth of nested references stop attempting to read - * the next reference because we are likely in a self referential loop. - * 16 references deep seems like more than enough depth for expected usage */ - if (reference_depth > 16) + * the next reference because we are likely in a self referential loop. */ + if (reference_depth > SHADER_MAX_REFERENCE_DEPTH) { - RARCH_ERR("[ Shaders - Save Simple Preset ]: Exceeded maximum reference " - "depth(16) without finding a full preset. " - "This chain of referenced presets is likely cyclical.\n"); + RARCH_ERR("[ Shaders - Check Reference Chain for Save]: Exceeded maximum reference depth(%u) without " + "finding a full preset. This chain of referenced presets is likely cyclical.\n", SHADER_MAX_REFERENCE_DEPTH); return_val = false; break; } - /* Resolve the reference path relative to the config */ - if (path_is_absolute(conf->reference)) - strlcpy(nested_reference_path, conf->reference, PATH_MAX_LENGTH); - else - fill_pathname_resolve_relative(nested_reference_path, - conf->path, - conf->reference, - PATH_MAX_LENGTH); + /* Get the absolute path for the reference */ + fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->reference); - /* If one of the reference paths is the same as the file we want to save then - * this reference chain would be self-referential / cyclical and we can't save - * this as a simple preset*/ + /* If one of the reference paths is the same as the file we want to save then this reference chain would be + * self-referential / cyclical and we can't save this as a simple preset*/ if (string_is_equal(nested_reference_path, path_to_save)) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving preset:\n" + RARCH_WARN("[ Shaders ]: Saving preset:\n" " %s\n" " With a #reference of:\n" " %s\n" @@ -669,8 +949,8 @@ bool video_shader_check_reference_chain_for_save(const char *path_to_save, const /* If we can't read the reference preset */ if (!conf) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Could not read shader preset " - "in #reference line: %s\n", nested_reference_path); + RARCH_WARN("[ Shaders ]: Could not read shader preset in #reference line: %s\n", + nested_reference_path); return_val = false; break; } @@ -696,7 +976,6 @@ bool video_shader_check_reference_chain_for_save(const char *path_to_save, const * as it's first line to specify a root preset and can also include parameter * and texture values to override the values of the root preset * Returns false if a referenced preset cannot be saved - * See: video_shader_read_preset **/ bool video_shader_write_referenced_preset(const char *path, const char *shader_dir, @@ -705,6 +984,7 @@ bool video_shader_write_referenced_preset(const char *path, unsigned i; config_file_t *conf = NULL; config_file_t *reference_conf = NULL; + struct video_shader *referenced_shader = (struct video_shader*) calloc(1, sizeof(*referenced_shader)); bool ret = false; bool continue_saving_reference = true; char *new_preset_basedir = strdup(path); @@ -722,28 +1002,22 @@ bool video_shader_write_referenced_preset(const char *path, /* Get the retroarch config dir where the automatically loaded presets are located * and where Save Game Preset, Save Core Preset, Save Global Preset save to */ - fill_pathname_application_special(config_dir, - PATH_MAX_LENGTH, - APPLICATION_SPECIAL_DIRECTORY_CONFIG); + fill_pathname_application_special(config_dir, PATH_MAX_LENGTH, APPLICATION_SPECIAL_DIRECTORY_CONFIG); /* If there is no initial preset path loaded */ if (!shader->loaded_preset_path) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because the " - "loaded Shader does not have a path to a previously loaded preset " - "file on disk.\n"); - continue_saving_reference = false; - goto end; + RARCH_WARN("[ Shaders ]: Saving Full Preset because the loaded Shader does not have " + "a path to a previously loaded preset file on disk.\n"); + goto end; } /* If the initial preset loaded is the ever-changing retroarch preset don't save a reference - * TODO remove once we don't write this preset anymore */ + * TODO remove once we don't write this preset anymore */ if (!strncmp(path_basename(shader->loaded_preset_path), "retroarch", STRLEN_CONST("retroarch"))) { - continue_saving_reference = false; - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because we can't " - "save a reference to the ever-changing retroarch preset.\n"); - continue_saving_reference = false; + RARCH_WARN("[ Shaders ]: Saving Full Preset because we can't save a reference to the " + "ever-changing retroarch preset.\n"); goto end; } @@ -755,10 +1029,8 @@ bool video_shader_write_referenced_preset(const char *path, /* If the original preset can't be loaded, probably because it isn't there anymore */ if (!reference_conf) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because the " - "initially loaded preset can't be loaded. It was likely " - "renamed or deleted.\n"); - continue_saving_reference = false; + RARCH_WARN("[ Shaders ]: Saving Full Preset because the initially loaded preset can't be loaded. " + "It was likely renamed or deleted.\n"); goto end; } @@ -770,14 +1042,8 @@ bool video_shader_write_referenced_preset(const char *path, * the preset path we are currently trying to save */ if (reference_conf->reference) { - /* Get the absolute reference path in the initially loaded preset file*/ - if (!path_is_absolute(reference_conf->reference)) - fill_pathname_resolve_relative(abs_temp_reference_path, - reference_conf->path, - reference_conf->reference, - PATH_MAX_LENGTH); - else - abs_temp_reference_path = strdup(reference_conf->reference); + /* Get the absolute path for the reference */ + fill_pathname_expanded_and_absolute(abs_temp_reference_path, reference_conf->path, reference_conf->reference); /* If the reference is the same as the path we are trying to save to then this should be used as the reference to save */ @@ -802,21 +1068,14 @@ bool video_shader_write_referenced_preset(const char *path, /* If the reference path is the same as the path we want to save or the reference * path is in the config (auto shader) folder */ - if (string_is_equal(path_to_reference, path) || - !strncmp(config_dir, path_to_reference, strlen(config_dir))) + if (string_is_equal(path_to_reference, path) || !strncmp(config_dir, path_to_reference, strlen(config_dir))) { /* If the config from the reference path has a reference in it we will use this same * nested reference for the new preset */ if (reference_conf->reference) { /* Get the absolute path for the reference */ - if (!path_is_absolute(reference_conf->reference)) - fill_pathname_resolve_relative(path_to_reference, - reference_conf->path, - reference_conf->reference, - PATH_MAX_LENGTH); - else - strlcpy(path_to_reference, reference_conf->reference, PATH_MAX_LENGTH); + fill_pathname_expanded_and_absolute(path_to_reference, reference_conf->path, reference_conf->reference); /* If the reference path is also the same as what we are trying to save This can easily happen @@ -834,20 +1093,13 @@ bool video_shader_write_referenced_preset(const char *path, if (reference_conf->reference) { /* Get the absolute path for the reference */ - if (!path_is_absolute(reference_conf->reference)) - fill_pathname_resolve_relative(path_to_reference, - reference_conf->path, - reference_conf->reference, - PATH_MAX_LENGTH); - else - strlcpy(path_to_reference, reference_conf->reference, PATH_MAX_LENGTH); + fill_pathname_expanded_and_absolute(path_to_reference, reference_conf->path, reference_conf->reference); } /* If the config referenced is a full preset */ else { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because we " - "can't save a preset which would reference itself.\n"); - continue_saving_reference = false; + RARCH_WARN("[ Shaders ]: Saving Full Preset because we can't save a preset which " + "would reference itself.\n"); goto end; } } @@ -856,9 +1108,8 @@ bool video_shader_write_referenced_preset(const char *path, else { /* We can't save a reference to ourselves */ - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because we " - "can't save a preset which would reference itself.\n"); - continue_saving_reference = false; + RARCH_WARN("[ Shaders ]: Saving Full Preset because we can't save a preset which " + "would reference itself.\n"); goto end; } } @@ -866,287 +1117,204 @@ bool video_shader_write_referenced_preset(const char *path, /* Check the reference chain that we would be saving to make sure it is valid */ if (!video_shader_check_reference_chain_for_save(path, path_to_reference)) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because " - "saving a Simple Preset would result in a cyclical reference, " - "or a preset in the reference chain could not be read.\n"); - continue_saving_reference = false; + RARCH_WARN("[ Shaders ]: Saving Full Preset because saving a Simple Preset would result " + "in a cyclical reference, or a preset in the reference chain could not be read.\n"); goto end; } + RARCH_LOG("[ Shaders ]: Reading Preset to Compare with Current Values: %s\n", path); + + /* Load the preset referenced in the preset into the shader */ + if (!video_shader_load_preset_into_shader(path_to_reference, referenced_shader)) + { + RARCH_WARN("[ Shaders ]: Saving Full Preset because we could not load the preset from the #reference line: %s.\n", + path_to_reference); + goto end; + } + + /* Create a new EMPTY config */ + conf = config_file_new_alloc(); + + if (!(conf)) + goto end; + + conf->path = strdup(path); + + pathname_make_slashes_portable(relative_temp_reference_path); + + /* Add the reference path to the config */ + config_file_set_reference_path(conf, path_to_reference); + + /* Set modified to true so when you run config_file_write it will save a file */ + conf->modified = true; + + /* + Compare the shader to a shader created from the referenced config to see if + we can save a referenced preset and what parameters and textures of the + root_config are overridden + */ + + /* Check number of passes match */ + if (shader->passes != referenced_shader->passes) + { + RARCH_WARN("[ Shaders ]: passes (Number of Passes) " + "Current Value doesn't match Referenced Value - Full Preset will be Saved instead of Simple Preset\n"); + continue_saving_reference = false; + } + + /* Compare all passes from the shader, if anything is different then we should not + * save a reference and instead save a full preset instead + */ if (continue_saving_reference) { - - path_relative_to(relative_temp_reference_path, - path_to_reference, - new_preset_basedir, - PATH_MAX_LENGTH); -#ifdef _WIN32 - if (!path_is_absolute(relative_temp_reference_path)) - make_relative_path_portable(relative_temp_reference_path); -#endif - - /* Create a new EMPTY config */ - conf = config_file_new_alloc(); - if (!(conf)) - goto end; - conf->path = strdup(path); - - /* Add the reference path to the config */ - config_file_set_reference_path(conf, relative_temp_reference_path); - - /* Set modified to true so when you run config_file_write it will save a file */ - conf->modified = true; - - /* Get a config from the #reference line in the preset - * We will compare the current shader against this config */ - config_file_free(reference_conf); - reference_conf = video_shader_read_preset(path_to_reference); - - /* reference_conf could be NULL if the file was not found or if the - * chain of references was too deep */ - if (reference_conf == NULL) + /* Step through each pass comparing all the properties to make sure they match */ + for (i = 0; (i < shader->passes && continue_saving_reference == true); i++) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Saving Full Preset because we " - "could not load the preset from the #reference line: %s.\n", - path_to_reference); - continue_saving_reference = false; - } - else - { - /* - Compare the shader to a shader created from the referenced config to see if - we can save a referenced preset and what parameters and textures of the - root_config are overridden - */ + const struct video_shader_pass *pass = &shader->pass[i]; + const struct video_shader_pass *root_pass = &referenced_shader->pass[i]; + const struct gfx_fbo_scale *fbo = &pass->fbo; + const struct gfx_fbo_scale *root_fbo = &root_pass->fbo; - struct video_shader *root_shader = NULL; - root_shader = (struct video_shader*) calloc(1, sizeof(*root_shader)); - video_shader_read_conf_preset(reference_conf, root_shader); - - /* Check number of passes match */ - if (shader->passes != root_shader->passes) + if (!string_is_equal(pass->source.path, root_pass->source.path)) { - RARCH_WARN("[ Shaders - Save Simple Preset ]: passes (Number of Passes) " - "Current Value doesn't match Referenced Value - Full Preset " - "will be Saved instead of Simple Preset\n"); + RARCH_WARN("[ Shaders ]: Pass %u path", i); continue_saving_reference = false; } - /* - Compare all passes from the shader - if anything is different then we should not save a reference - and save instead safe a full preset instead - */ - if (continue_saving_reference) + if (continue_saving_reference && pass->filter != root_pass->filter) { - /* Step through each pass comparing all the properties to make sure they match */ - for (i = 0; (i < shader->passes && continue_saving_reference == true); i++) - { - const struct video_shader_pass *pass = &shader->pass[i]; - const struct video_shader_pass *root_pass = &root_shader->pass[i]; - const struct gfx_fbo_scale *fbo = &pass->fbo; - const struct gfx_fbo_scale *root_fbo = &root_pass->fbo; - - if (!string_is_equal(pass->source.path, root_pass->source.path)) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u path", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && pass->filter != root_pass->filter) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u filter", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && pass->wrap != root_pass->wrap) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u wrap", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && pass->frame_count_mod != root_pass->frame_count_mod) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u frame_count", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && pass->mipmap != root_pass->mipmap) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u mipmap", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && !string_is_equal(pass->alias, root_pass->alias)) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u alias", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->type_x != root_fbo->type_x) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u type_x", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->type_y != root_fbo->type_y) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u type_y", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->scale_x != root_fbo->scale_x) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u scale_x", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->scale_y != root_fbo->scale_y) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u scale_y", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->fp_fbo != root_fbo->fp_fbo) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u fp_fbo", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->srgb_fbo != root_fbo->srgb_fbo) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u srgb_fbo", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->valid != root_fbo->valid) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u valid", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->abs_x != root_fbo->abs_x) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u abs_x", i); - continue_saving_reference = false; - } - - if (continue_saving_reference && fbo->abs_y != root_fbo->abs_y) - { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Pass %u abs_y", i); - continue_saving_reference = false; - } - - if (!continue_saving_reference) - RARCH_WARN(" Current Value doesn't match Referenced Value - " - "Full Preset Will be Saved instead of Simple Preset\n"); - } + RARCH_WARN("[ Shaders ]: Pass %u filter", i); + continue_saving_reference = false; } - if (continue_saving_reference) + if (continue_saving_reference && pass->wrap != root_pass->wrap) { - const struct config_entry_list *entry = NULL; - - /* If the shader has parameters */ - if (shader->num_parameters) - { - unsigned i; - float parameter_value_reference = 0.0f; - - - for (i = 0; i < shader->num_parameters; i++) - { - bool add_param_to_override = false; - - entry = config_get_entry(reference_conf, shader->parameters[i].id); - - /* If the parameter is in the reference config */ - if (entry) - { - /* If the current param value is different than the referenced preset's value */ - config_get_float(reference_conf, shader->parameters[i].id, ¶meter_value_reference); - if (shader->parameters[i].current != parameter_value_reference) - add_param_to_override = true; - } - /* If it's not in the reference config, but it's different than the - initial value of the shader */ - else if (shader->parameters[i].current != shader->parameters[i].initial) - add_param_to_override = true; - - /* Add the parameter value to the config */ - if (add_param_to_override) - config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current); - } - } - - /* If the shader has textures */ - if (shader->luts) - { - char *shader_tex_path = (char*)malloc(PATH_MAX_LENGTH); - char *shader_tex_relative_path = (char*)malloc(PATH_MAX_LENGTH); - char *shader_tex_base_path = (char*)malloc(PATH_MAX_LENGTH); - char *referenced_tex_absolute_path = (char*)malloc(PATH_MAX_LENGTH); - char *referenced_tex_path = (char*)malloc(PATH_MAX_LENGTH); - unsigned i; - - shader_tex_path[0] = '\0'; - shader_tex_relative_path[0] = '\0'; - shader_tex_base_path[0] = '\0'; - referenced_tex_absolute_path[0] = '\0'; - referenced_tex_path[0] = '\0'; - - for (i = 0; i < shader->luts; i++) - { - /* If the texture is defined in the reference config */ - entry = config_get_entry(reference_conf, shader->lut[i].id); - if (entry) - { - /* Texture path from shader is already absolute */ - strlcpy(shader_tex_path, shader->lut[i].path, PATH_MAX_LENGTH); - strlcpy(referenced_tex_path, entry->value, PATH_MAX_LENGTH); - - /* Resolve the texture's path relative to the override config */ - if (!path_is_absolute(referenced_tex_path)) - fill_pathname_resolve_relative(referenced_tex_absolute_path, - reference_conf->path, - entry->value, - PATH_MAX_LENGTH); - else - strlcpy(referenced_tex_absolute_path, referenced_tex_path, PATH_MAX_LENGTH); - - /* If the current shader texture path is different than the referenced paths then - * write the current path into the new preset */ - if (!string_is_equal(referenced_tex_absolute_path, shader->lut[i].path)) - { - /* Get the texture path relative to the new preset */ - path_relative_to(shader_tex_relative_path, shader_tex_path, path_basename(path), PATH_MAX_LENGTH); - - RARCH_LOG("[ Shaders - Save Simple Preset ]: Texture override %s = %s.\n", - shader->lut[i].id, - shader->lut[i].path); - config_set_path(conf, shader->lut[i].id, shader->lut[i].path); - } - } - } - - free(shader_tex_path); - free(shader_tex_relative_path); - free(shader_tex_base_path); - free(referenced_tex_absolute_path); - free(referenced_tex_path); - } - /* Write the file, return will be true if successful */ - RARCH_LOG("[ Shaders - Save Simple Preset ]: Saving simple preset to: %s\n", path); - ret = config_file_write(conf, path, false); + RARCH_WARN("[ Shaders ]: Pass %u wrap", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && pass->frame_count_mod != root_pass->frame_count_mod) + { + RARCH_WARN("[ Shaders ]: Pass %u frame_count", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && pass->mipmap != root_pass->mipmap) + { + RARCH_WARN("[ Shaders ]: Pass %u mipmap", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && !string_is_equal(pass->alias, root_pass->alias)) + { + RARCH_WARN("[ Shaders ]: Pass %u alias", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->type_x != root_fbo->type_x) + { + RARCH_WARN("[ Shaders ]: Pass %u type_x", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->type_y != root_fbo->type_y) + { + RARCH_WARN("[ Shaders ]: Pass %u type_y", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->scale_x != root_fbo->scale_x) + { + RARCH_WARN("[ Shaders ]: Pass %u scale_x", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->scale_y != root_fbo->scale_y) + { + RARCH_WARN("[ Shaders ]: Pass %u scale_y", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->fp_fbo != root_fbo->fp_fbo) + { + RARCH_WARN("[ Shaders ]: Pass %u fp_fbo", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->srgb_fbo != root_fbo->srgb_fbo) + { + RARCH_WARN("[ Shaders ]: Pass %u srgb_fbo", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->valid != root_fbo->valid) + { + RARCH_WARN("[ Shaders ]: Pass %u valid", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->abs_x != root_fbo->abs_x) + { + RARCH_WARN("[ Shaders ]: Pass %u abs_x", i); + continue_saving_reference = false; + } + + if (continue_saving_reference && fbo->abs_y != root_fbo->abs_y) + { + RARCH_WARN("[ Shaders ]: Pass %u abs_y", i); + continue_saving_reference = false; + } + + if (!continue_saving_reference) + { + RARCH_WARN(" Current Value doesn't match Referenced Value - Full Preset Will be Saved instead of Simple Preset\n"); + goto end; } - free(root_shader); } } + /* If the shader has parameters */ + if (shader->num_parameters) + { + for (i = 0; i < shader->num_parameters; i++) + { + /* If the parameter's current value is different than the referenced shader + * then write the value into the new preset */ + if (shader->parameters[i].current != referenced_shader->parameters[i].current) + config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current); + } + } + + /* If the shader has textures */ + if (shader->luts) + { + for (i = 0; i < shader->luts; i++) + { + /* If the current shader texture path is different than the referenced shader texture then + * write the current path into the new preset */ + if (!string_is_equal(referenced_shader->lut[i].path, shader->lut[i].path)) + { + char *path_for_save = (char*)malloc(PATH_MAX_LENGTH); + + fill_pathname_abbreviated_or_relative(path_for_save, conf->path, shader->lut[i].path, PATH_MAX_LENGTH); + pathname_make_slashes_portable(path_for_save); + config_set_string(conf, shader->lut[i].id, path_for_save); + RARCH_LOG("[ Shaders ]: Texture override %s = %s.\n", shader->lut[i].id, path_for_save); + + free(path_for_save); + } + } + } + + /* Write the file, return will be true if successful */ + RARCH_LOG("[ Shaders ]: Saving simple preset to: %s\n", path); + ret = config_file_write(conf, path, false); + end: config_file_free(conf); config_file_free(reference_conf); + free(referenced_shader); free(abs_temp_reference_path); free(relative_temp_reference_path); free(new_preset_basedir); @@ -1159,30 +1327,25 @@ end: /** * video_shader_write_preset: * @path : File to write to - * @shader : Shader preset to write - * @reference : Whether a reference preset should be written + * @shader : Shader to write + * @reference : Whether a simple preset should be written with the #reference to another preset in it * - * Writes a preset to disk. Can be written as a reference preset. - * See: video_shader_read_preset + * Writes a preset to disk. Can be written as a simple preset (With the #reference directive in it) or a full preset. **/ bool video_shader_write_preset(const char *path, - const char *shader_dir, - const struct video_shader *shader, bool reference) + const char *shader_dir, + const struct video_shader *shader, + bool reference) { /* We need to clean up paths to be able to properly process them * path and shader->loaded_preset_path can use '/' on Windows due to Qt being Qt */ char preset_dir[PATH_MAX_LENGTH]; - config_file_t *conf; bool ret; if (!shader || string_is_empty(path)) return false; - fill_pathname_join( - preset_dir, - shader_dir, - "presets", - sizeof(preset_dir)); + fill_pathname_join(preset_dir, shader_dir, "presets", sizeof(preset_dir)); /* If we should still save a referenced preset do it now */ if (reference) @@ -1193,262 +1356,65 @@ bool video_shader_write_preset(const char *path, } else { - RARCH_WARN("[ Shaders - Save Simple Preset ]: Failed writing Simple " - "Preset to %s - Full Preset Will be Saved instead.\n", path); + RARCH_WARN("[ Shaders ]: Failed writing Simple Preset to %s - " + "Full Preset Will be Saved instead.\n", path); } } /* If we aren't saving a referenced preset or weren't able to save one * then save a full preset */ - - /* Note: We always create a new/blank config - * file here. Loading and updating an existing - * file could leave us with unwanted/invalid - * parameters. */ - if (!(conf = config_file_new_alloc())) - return false; - - video_shader_write_conf_preset(conf, shader, path); - - ret = config_file_write(conf, path, false); - - config_file_free(conf); + ret = video_shader_write_root_preset(shader, path); return ret; } /** - * override_config_values: - * @conf : Config file to be affected - * @override_conf : Config file who's values will be copied on top of conf - * - * Takes values from override_config and overrides values of conf - * The 'parameters' value will be the combined parameter list from both configs - * - * Returns 0 if nothing is overridden - * Returns 1 if something is overridden - **/ -bool override_config_values(config_file_t *conf, config_file_t *override_conf) -{ - int return_val = 0; - size_t param_size = 4096 * sizeof(char); - const char *id = NULL; - char *save = NULL; - size_t path_size = PATH_MAX_LENGTH; - char *override_texture_path = (char*)malloc(path_size); - char *resolved_path = (char*)malloc(path_size); - char *textures_in_conf = (char*)malloc(param_size); - size_t tmp_size = PATH_MAX_LENGTH; - char *tmp = (char*)malloc(3*tmp_size); - char *tmp_rel = tmp + tmp_size; - char *tmp_base = tmp + 2*tmp_size; - struct config_entry_list *override_entry = NULL; - - textures_in_conf[0] = '\0'; - strlcpy(tmp_base, conf->path, tmp_size); - - if (conf == NULL || override_conf == NULL) return 0; - - /* --------------------------------------------------------------------------------- - * ------------- Resolve Override texture paths to absolute paths------------------- - * --------------------------------------------------------------------------------- */ - - /* ensure we use a clean base like the shader passes and texture paths do */ - path_resolve_realpath(tmp_base, tmp_size, false); - path_basedir(tmp_base); - - /* If there are textures in the referenced config */ - if (config_get_array(conf, "textures", textures_in_conf, param_size)) - { - for ( id = strtok_r(textures_in_conf, ";", &save); - id; - id = strtok_r(NULL, ";", &save)) - { - /* Get the texture path from the override config */ - if (config_get_path(override_conf, id, override_texture_path, path_size)) - { - /* Resolve the texture's path relative to the override config */ - if (!path_is_absolute(override_texture_path)) - fill_pathname_resolve_relative(resolved_path, - override_conf->path, - override_texture_path, - PATH_MAX_LENGTH); - else - strlcpy(resolved_path, override_texture_path, path_size); - - path_relative_to(tmp_rel, resolved_path, tmp_base, tmp_size); - config_set_path(override_conf, id, tmp_rel); - - return_val = 1; - } - } - } - - /* --------------------------------------------------------------------------------- - * ------------- Update entries to match the override entries ---------------------- - * --------------------------------------------------------------------------------- */ - - for (override_entry = override_conf->entries; override_entry; override_entry = override_entry->next) - /* Only override an entry if the its key is not "textures" */ - if (!string_is_empty(override_entry->key) && !string_is_equal(override_entry->key, "textures")) - { - RARCH_LOG("[ Shaders - Read Simple Preset ]: Parameter/Entry overridden %s = %s.\n", - override_entry->key, override_entry->value); - config_set_string(conf, override_entry->key, override_entry->value); - return_val = 1; - } - - free(tmp); - free(resolved_path); - free(override_texture_path); - free(textures_in_conf); - - return return_val; -} - -/** - * video_shader_read_preset: - * @path : File to read - * - * Reads a preset from disk. - * If the preset is a reference preset, the referenced preset - * is loaded instead. - * - * Returns the read preset as a config object. - * - * The returned config object needs to be freed. - **/ -config_file_t *video_shader_read_preset(const char *path) -{ - config_file_t *conf; - conf = config_file_new_from_path_to_string(path); - - if (conf != NULL) - { - int reference_depth = 1; - - if (conf->reference) - RARCH_LOG("[ Shaders - Read Preset ]: Start reading SIMPLE Preset: %s\n", path); - else - RARCH_LOG("[ Shaders - Read Preset ]: Start reading FULL Preset: %s\n", path); - - /* If the config has a reference then it is really an override config. - * We now load a new config from the reference then override it's values - * with the override config */ - while (conf->reference) - { - char* reference_preset_path = (char*)malloc(PATH_MAX_LENGTH); - /* Set override_conf to refer to the original config */ - config_file_t *override_conf = conf; - - /* Stop attempting to read the next reference when we have visited many links - * in the reference chain because we are likely in a self referential loop. - * 16 references deep seems like more than enough depth for expected usage */ - if (reference_depth > 16) - { - RARCH_ERR("[ Shaders - Read Simple Preset ]: Exceeded maximum reference " - "depth(16) without finding a full preset\n"); - free(reference_preset_path); - config_file_free(conf); - conf = NULL; - return NULL; - } - - /* Resolve the reference path relative to the config */ - if (path_is_absolute(conf->reference)) - strlcpy(reference_preset_path, conf->reference, PATH_MAX_LENGTH); - else - fill_pathname_resolve_relative(reference_preset_path, - conf->path, - conf->reference, - PATH_MAX_LENGTH); - - RARCH_LOG("[ Shaders - Read Simple Preset ]: #reference preset read " - "(Depth %u): %s\n", reference_depth, reference_preset_path); - - /* Create a new config from the root preset */ - conf = config_file_new_from_path_to_string(reference_preset_path); - - /* Only try to override values if the config is not NULL - * If it is NULL there is no shader*/ - if (conf != NULL) - /* override_conf is from the initial file we loaded which - * has the #reference directive*/ - override_config_values(conf, override_conf); - else - { - RARCH_WARN("[ Shaders - Read Simple Preset ]: Could not read shader preset " - "in #reference line: %s\n", reference_preset_path); - free(reference_preset_path); - config_file_free(override_conf); - break; - } - - reference_depth += 1; - - free(reference_preset_path); - config_file_free(override_conf); - } - - /* Set Path for originally loaded preset */ - config_set_path(conf, "loaded_preset_path", path); - } - else - RARCH_WARN("[ Shaders - Read Preset ]: Could not read preset: %s \n", path); - - return conf; -} - -/** - * video_shader_read_conf_preset: + * video_shader_load_root_config_into_shader: * @conf : Preset file to read from. - * @shader : Shader passes handle. + * @shader : Shader handle. * - * Loads preset file and all associated state (passes, - * textures, imports, etc). + * Loads preset file and all associated state (passes, textures, imports, etc). * * Returns: true (1) if successful, otherwise false (0). **/ -bool video_shader_read_conf_preset(config_file_t *conf, - struct video_shader *shader) +bool video_shader_load_root_config_into_shader(config_file_t *conf, struct video_shader *shader) { unsigned i; - unsigned shaders = 0; + unsigned num_passes = 0; settings_t *settings = config_get_ptr(); bool watch_files = settings->bools.video_shader_watch_files; - char loaded_preset_path[PATH_MAX_LENGTH]; + /* This sets the shader to empty */ memset(shader, 0, sizeof(*shader)); - if (!config_get_uint(conf, "shaders", &shaders)) + RARCH_LOG("\n"); + RARCH_LOG("[ Shaders ]: Reading ROOT PRESET: %s\n", conf->path); + + if (!config_get_uint(conf, "shaders", &num_passes)) { - RARCH_ERR("[ Shaders - Read Preset ]: Cannot find \"shaders\" param. " - "Preset is invalid.\n"); - return false; + RARCH_ERR("[ Shaders ]: Cannot find \"shaders\" param. Preset is invalid.\n"); + goto fail; } - if (!shaders) + if (!num_passes) { - RARCH_ERR("[ Shaders - Read Preset ]: Need to define at least 1 shader pass. " - "Preset is invalid.\n"); - return false; + RARCH_ERR("[ Shaders ]: Need to define at least 1 shader pass. Preset is invalid.\n"); + goto fail; } - if (!config_get_int(conf, "feedback_pass", - &shader->feedback_pass)) + if (!config_get_int(conf, "feedback_pass", &shader->feedback_pass)) shader->feedback_pass = -1; - shader->passes = MIN(shaders, GFX_MAX_SHADERS); + shader->passes = MIN(num_passes, GFX_MAX_SHADERS); /* Set the path of the root preset for this shader */ strlcpy(shader->path, conf->path, sizeof(shader->path)); - - /* Set the path of the original preset which was loaded, this would be - * different than the root preset in the case preset of use of the #reference directive - * in the original preset loaded */ - config_get_path(conf, "loaded_preset_path", loaded_preset_path, PATH_MAX_LENGTH); + + /* Set the path of the original preset which was loaded, for a full preset config this is the same as the root config + * For simple presets (using #reference) this different than the root preset and it is the path to the + * simple preset originally loaded, but that is set inside video_shader_load_preset_into_shader*/ strlcpy( shader->loaded_preset_path, - loaded_preset_path, + conf->path, sizeof(shader->loaded_preset_path)); if (watch_files) @@ -1464,8 +1430,7 @@ bool video_shader_read_conf_preset(config_file_t *conf, attr.i = 0; if (file_change_data) - frontend_driver_watch_path_for_changes(NULL, - 0, &file_change_data); + frontend_driver_watch_path_for_changes(NULL, 0, &file_change_data); file_change_data = NULL; string_list_initialize(&file_list); @@ -1479,15 +1444,13 @@ bool video_shader_read_conf_preset(config_file_t *conf, if (!video_shader_parse_pass(conf, &shader->pass[i], i)) { string_list_deinitialize(&file_list); - return false; + goto fail; } - string_list_append(&file_list, - shader->pass[i].source.path, attr); + string_list_append(&file_list, shader->pass[i].source.path, attr); } - frontend_driver_watch_path_for_changes(&file_list, - flags, &file_change_data); + frontend_driver_watch_path_for_changes(&file_list, flags, &file_change_data); string_list_deinitialize(&file_list); } else @@ -1495,230 +1458,234 @@ bool video_shader_read_conf_preset(config_file_t *conf, for (i = 0; i < shader->passes; i++) { if (!video_shader_parse_pass(conf, &shader->pass[i], i)) - return false; + goto fail; } } - return video_shader_parse_textures(conf, shader); + if (!video_shader_parse_textures(conf, shader)) + goto fail; + + /* Load the parameter values */ + video_shader_resolve_parameters(shader); + + /* Load the parameter values */ + video_shader_load_current_parameter_values(conf, shader); + + RARCH_LOG("[ Shaders ]: Number of Passes: %u\n", shader->passes); + RARCH_LOG("[ Shaders ]: Number of Textures: %u\n", shader->luts); + + /* Log Texture Names & Paths */ + for (i = 0; i < shader->luts; i++) + RARCH_LOG("[ Shaders ]: %s = %s.\n", shader->lut[i].id, shader->lut[i].path); + + return true; + + fail: + return false; } -/* CGP store */ -static const char *scale_type_to_str(enum gfx_scale_type type) + +/** + * override_shader_values: + * @override_conf : Config file who's values will be copied on top of conf + * @shader : Shader to be affected + * + * Takes values from override_config and overrides values of the shader + * + * Returns 0 if nothing is overridden + * Returns 1 if something is overridden + **/ +bool override_shader_values(config_file_t *override_conf, struct video_shader *shader) { - switch (type) + bool return_val = false; + unsigned i; + struct config_entry_list *entry = NULL; + char *override_tex_path = (char*)malloc(PATH_MAX_LENGTH); + + override_tex_path[0] = '\0'; + + if (shader == NULL || override_conf == NULL) return 0; + + /* If the shader has parameters */ + if (shader->num_parameters) { - case RARCH_SCALE_INPUT: - return "source"; - case RARCH_SCALE_VIEWPORT: - return "viewport"; - case RARCH_SCALE_ABSOLUTE: - return "absolute"; - default: - break; + /* Step through the parameters in the shader and see if there is an entry + * for each in the override config */ + for (i = 0; i < shader->num_parameters; i++) + { + entry = config_get_entry(override_conf, shader->parameters[i].id); + + /* If the parameter is in the reference config */ + if (entry) + { + struct video_shader_parameter *parameter = (struct video_shader_parameter*) + video_shader_parse_find_parameter( + shader->parameters, + shader->num_parameters, + shader->parameters[i].id); + + /* Set the shader's parameter value */ + config_get_float(override_conf, shader->parameters[i].id, ¶meter->current); + + RARCH_LOG("[ Shaders ]: Parameter: %s = %f.\n", + shader->parameters[i].id, + shader->parameters[i].current); + + return_val = true; + } + } } - return "?"; -} + /* --------------------------------------------------------------------------------- + * ------------- Resolve Override texture paths to absolute paths------------------- + * --------------------------------------------------------------------------------- */ -static void shader_write_scale_dim(config_file_t *conf, - const char *dim, - enum gfx_scale_type type, float scale, - unsigned absolute, unsigned i) -{ - char key[64]; + /* If the shader has textures */ + if (shader->luts) + { + /* Step through the textures in the shader and see if there is an entry + * for each in the override config */ + for (i = 0; i < shader->luts; i++) + { + entry = config_get_entry(override_conf, shader->lut[i].id); - key[0] = '\0'; + /* If the texture is defined in the reference config */ + if (entry) + { + /* Texture path from shader the config */ + config_get_path(override_conf, shader->lut[i].id, override_tex_path, PATH_MAX_LENGTH); - snprintf(key, sizeof(key), "scale_type_%s%u", dim, i); - config_set_string(conf, key, scale_type_to_str(type)); + /* Get the absolute path */ + fill_pathname_expanded_and_absolute(shader->lut[i].path, override_conf->path, override_tex_path); - snprintf(key, sizeof(key), "scale_%s%u", dim, i); - if (type == RARCH_SCALE_ABSOLUTE) - config_set_int(conf, key, absolute); - else - config_set_float(conf, key, scale); -} + RARCH_LOG("[ Shaders ]: Texture: %s = %s.\n", + shader->lut[i].id, + shader->lut[i].path); -static void shader_write_fbo(config_file_t *conf, - const struct gfx_fbo_scale *fbo, unsigned i) -{ - char key[64]; + return_val = true; + } + } - key[0] = '\0'; + free(override_tex_path); + } - snprintf(key, sizeof(key), "float_framebuffer%u", i); - config_set_bool(conf, key, fbo->fp_fbo); - snprintf(key, sizeof(key), "srgb_framebuffer%u", i); - config_set_bool(conf, key, fbo->srgb_fbo); - - if (!fbo->valid) - return; - - shader_write_scale_dim(conf, "x", fbo->type_x, - fbo->scale_x, fbo->abs_x, i); - shader_write_scale_dim(conf, "y", fbo->type_y, - fbo->scale_y, fbo->abs_y, i); + return return_val; } /** - * video_shader_write_conf_preset: - * @conf : Preset file to write to. - * @shader : Shader passes handle. - * @preset_path : Optional path to where the preset will be written. + * video_shader_load_preset_into_shader: + * @path : Path to preset file, could be a Simple Preset (including a #reference) or Full Preset + * @shader : Shader * - * Writes preset and all associated state (passes, - * textures, imports, etc) into @conf. - * If @preset_path is not NULL, shader paths are saved - * relative to it. + * Loads preset file to a shader including passes, textures and parameters + * + * Returns: true (1) if successful, otherwise false (0). **/ -void video_shader_write_conf_preset(config_file_t *conf, - const struct video_shader *shader, const char *preset_path) +bool video_shader_load_preset_into_shader(const char *path, struct video_shader *shader) { - unsigned i; - char key[64]; - size_t tmp_size = PATH_MAX_LENGTH; - char *tmp = (char*)malloc(3*tmp_size); - char *tmp_rel = tmp + tmp_size; - char *tmp_base = tmp + 2*tmp_size; + unsigned i = 0; + bool ret = true; + int reference_depth = 1; + char override_conf_paths[SHADER_MAX_REFERENCE_DEPTH][PATH_MAX_LENGTH]; + config_file_t *conf = NULL; + config_file_t *root_conf = NULL; + + /* Get the root config, If we were able to get a root_config that means the reference chain is valid */ + root_conf = video_shader_get_root_preset_config(path); - if (!tmp) - return; - - RARCH_LOG("[ Shaders - Save Full Preset ]: Saving full preset to: %s\n", preset_path); - - config_set_int(conf, "shaders", shader->passes); - if (shader->feedback_pass >= 0) - config_set_int(conf, "feedback_pass", shader->feedback_pass); - - if (preset_path) + if (!root_conf) { - strlcpy(tmp_base, preset_path, tmp_size); - - /* ensure we use a clean base like the shader passes and texture paths do */ - path_resolve_realpath(tmp_base, tmp_size, false); - path_basedir(tmp_base); + RARCH_LOG("\n"); + RARCH_WARN("[ Shaders ]: Could not read root preset: %s \n", path); + ret = false; + goto end; } - for (i = 0; i < shader->passes; i++) + /* If we were able to get a root_config that means that the whole reference chain is valid */ + + /* If the root_conf path matches the original path then there are no references so we just load it and go to the end */ + if (string_is_equal(root_conf->path, path)) { - const struct video_shader_pass *pass = &shader->pass[i]; + RARCH_LOG("\n"); + RARCH_LOG("[ Shaders ]: Start reading FULL Preset: %s\n", path); + video_shader_load_root_config_into_shader(root_conf, shader); + goto end; + } + /* Otherwise this is a Simple Preset with a #reference in it */ + else + { + RARCH_LOG("\n"); + RARCH_LOG("[ Shaders ]: Start reading SIMPLE Preset: %s\n", path); + /* Load the root full preset into the shader which should be empty at this point */ + video_shader_load_root_config_into_shader(root_conf, shader); + } + + /* Get the config from the initial preset file + * We don't need to check it's validity because it must have been valid to get the root preset */ + conf = config_file_new_from_path_to_string(path); - snprintf(key, sizeof(key), "shader%u", i); + /* Set all override_conf_paths to empty so we know which ones have been filled */ + for (i = 0; i < SHADER_MAX_REFERENCE_DEPTH; i++) + override_conf_paths[i][0] = '\0'; - if (preset_path) - { - strlcpy(tmp, pass->source.path, tmp_size); - path_relative_to(tmp_rel, tmp, tmp_base, tmp_size); -#ifdef _WIN32 - if (!path_is_absolute(tmp_rel)) - make_relative_path_portable(tmp_rel); -#endif + i = 0; - config_set_path(conf, key, tmp_rel); - } - else - config_set_path(conf, key, pass->source.path); + RARCH_LOG("\n"); + RARCH_LOG("[ Shaders ]: Crawl Preset Reference Chain\n"); + /* If the config has a reference then we need gather all presets from the + * chain of references to apply their values later */ + while (conf->reference) + { + char* reference_preset_path = (char*)malloc(PATH_MAX_LENGTH); + i++; - if (pass->filter != RARCH_FILTER_UNSPEC) - { - snprintf(key, sizeof(key), "filter_linear%u", i); - config_set_bool(conf, key, pass->filter == RARCH_FILTER_LINEAR); - } + RARCH_LOG("[ Shaders ]: #reference preset read (Depth %u): %s\n", i, conf->path); - snprintf(key, sizeof(key), "wrap_mode%u", i); - config_set_string(conf, key, wrap_mode_to_str(pass->wrap)); + /* Add the reference to the list */ + strcpy(override_conf_paths[i], conf->path); - if (pass->frame_count_mod) - { - snprintf(key, sizeof(key), "frame_count_mod%u", i); - config_set_int(conf, key, pass->frame_count_mod); - } + /* Get the absolute path for the reference */ + fill_pathname_expanded_and_absolute(reference_preset_path, conf->path, conf->reference); - snprintf(key, sizeof(key), "mipmap_input%u", i); - config_set_bool(conf, key, pass->mipmap); + /* Create a new config from this reference level */ + conf = config_file_new_from_path_to_string(reference_preset_path); - snprintf(key, sizeof(key), "alias%u", i); - config_set_string(conf, key, pass->alias); + free(reference_preset_path); + } + + /* Step back through the references starting with the one referencing the root config and apply overrides for each one */ + + RARCH_LOG("\n"); + RARCH_LOG("[ Shaders ]: Start Applying Simple Preset Overrides\n"); - shader_write_fbo(conf, &pass->fbo, i); + while (i) + { + config_file_t *override_conf = config_file_new_from_path_to_string(override_conf_paths[i]); + + RARCH_LOG("[ Shaders ]: Depth %u Apply Overrides\n", i); + RARCH_LOG("[ Shaders ]: Apply values from: %s\n", override_conf->path); + override_shader_values(override_conf, shader); + + config_file_free(override_conf); + i--; } - /* Write shader parameters which are different than the default - * shader values */ - if (shader->num_parameters) - for (i = 0; i < shader->num_parameters; i++) - if (shader->parameters[i].current != shader->parameters[i].initial) - config_set_float(conf, shader->parameters[i].id, - shader->parameters[i].current); + RARCH_LOG("[ Shaders ]: End Apply Overrides\n"); + RARCH_LOG("\n"); - if (shader->luts) - { - char textures[4096]; + /* Set Path for originally loaded preset because it is different than the root preset path */ + strlcpy( shader->loaded_preset_path, path, sizeof(shader->loaded_preset_path)); - textures[0] = '\0'; + end: - strlcpy(textures, shader->lut[0].id, sizeof(textures)); + config_file_free(conf); + config_file_free(root_conf); - for (i = 1; i < shader->luts; i++) - { - /* O(n^2), but number of textures is very limited. */ - strlcat(textures, ";", sizeof(textures)); - strlcat(textures, shader->lut[i].id, sizeof(textures)); - } - - config_set_string(conf, "textures", textures); - - for (i = 0; i < shader->luts; i++) - { - if (preset_path) - { - strlcpy(tmp, shader->lut[i].path, tmp_size); - path_relative_to(tmp_rel, tmp, tmp_base, tmp_size); -#ifdef _WIN32 - if (!path_is_absolute(tmp_rel)) - make_relative_path_portable(tmp_rel); -#endif - - config_set_path(conf, shader->lut[i].id, tmp_rel); - } - else - config_set_path(conf, shader->lut[i].id, shader->lut[i].path); - - if (shader->lut[i].filter != RARCH_FILTER_UNSPEC) - { - char key[128]; - key[0] = '\0'; - strlcpy(key, shader->lut[i].id, sizeof(key)); - strlcat(key, "_linear", sizeof(key)); - config_set_bool(conf, key, - shader->lut[i].filter == RARCH_FILTER_LINEAR); - } - - { - char key[128]; - key[0] = '\0'; - strlcpy(key, shader->lut[i].id, sizeof(key)); - strlcat(key, "_wrap_mode", sizeof(key)); - config_set_string(conf, key, - wrap_mode_to_str(shader->lut[i].wrap)); - } - - { - char key[128]; - key[0] = '\0'; - strlcpy(key, shader->lut[i].id, sizeof(key)); - strlcat(key, "_mipmap", sizeof(key)); - config_set_bool(conf, key, - shader->lut[i].mipmap); - } - } - } - - free(tmp); + return ret; } -const char *video_shader_to_str(enum rarch_shader_type type) +const char *video_shader_type_to_str(enum rarch_shader_type type) { switch (type) { @@ -1807,8 +1774,7 @@ bool video_shader_any_supported(void) BIT32_GET(flags.flags, GFX_CTX_FLAGS_SHADERS_HLSL); } -enum rarch_shader_type video_shader_get_type_from_ext(const char *ext, - bool *is_preset) +enum rarch_shader_type video_shader_get_type_from_ext(const char *ext, bool *is_preset) { if (string_is_empty(ext)) return RARCH_SHADER_NONE; diff --git a/gfx/video_shader_parse.h b/gfx/video_shader_parse.h index 2a079afb99..b581170994 100644 --- a/gfx/video_shader_parse.h +++ b/gfx/video_shader_parse.h @@ -33,10 +33,6 @@ RETRO_BEGIN_DECLS #define GFX_MAX_TEXTURES 64 #endif -#ifndef GFX_MAX_VARIABLES -#define GFX_MAX_VARIABLES 64 -#endif - #ifndef GFX_MAX_PARAMETERS #define GFX_MAX_PARAMETERS 512 #endif @@ -167,47 +163,59 @@ struct video_shader bool modified; }; -/** - * video_shader_write_preset: - * @path : File to write to - * @shader : Shader preset to write - * @reference : Whether a reference preset should be written - * - * Writes a preset to disk. Can be written as a reference preset. - * See: video_shader_read_preset - **/ -bool video_shader_write_preset(const char *path, - const char *shader_dir, - const struct video_shader *shader, bool reference); /** - * video_shader_read_preset: - * @path : File to read - * - * Reads a preset from disk. - * If the preset is a reference preset, the referenced preset - * is loaded instead. - * - * Returns: the read preset as a config object. - * - * The returned config object needs to be freed. - **/ -config_file_t *video_shader_read_preset(const char *path); - -/** - * video_shader_read_conf_preset: + * video_shader_resolve_parameters: * @conf : Preset file to read from. * @shader : Shader passes handle. + * + * Resolves all shader parameters belonging to shaders + * from the #pragma parameter lines in the shader for each pass. + * + * Returns: true (1) if successful, otherwise false (0). + **/ +bool video_shader_resolve_parameters(struct video_shader *shader); + + +/** + * video_shader_load_current_parameter_values: + * @conf : Preset file to read from. + * @shader : Shader passes handle. + * + * Reads the current value for all parameters from config file. + * + * Returns: true (1) if successful, otherwise false (0). + **/ +bool video_shader_load_current_parameter_values(config_file_t *conf, struct video_shader *shader); + + +/** + * video_shader_load_root_config_into_shader: + * @conf : Preset file to read from. + * @shader : Shader handle. + * * Loads preset file and all associated state (passes, * textures, imports, etc). * * Returns: true (1) if successful, otherwise false (0). **/ -bool video_shader_read_conf_preset(config_file_t *conf, - struct video_shader *shader); +bool video_shader_load_root_config_into_shader(config_file_t *conf, struct video_shader *shader); + /** - * video_shader_write_conf_preset: + * video_shader_load_preset_into_shader: + * @path : Path to preset file, could be a Simple Preset (including a #reference) or Full Preset + * @shader : Shader + * + * Loads preset file to a shader including passes, textures and parameters + * + * Returns: true (1) if successful, otherwise false (0). + **/ +bool video_shader_load_preset_into_shader(const char *path, struct video_shader *shader); + + +/** + * video_shader_write_root_preset: * @conf : Preset file to write to. * @shader : Shader passes handle. * @preset_path : Optional path to where the preset will be written. @@ -217,35 +225,24 @@ bool video_shader_read_conf_preset(config_file_t *conf, * If @preset_path is not NULL, shader paths are saved * relative to it. **/ -void video_shader_write_conf_preset(config_file_t *conf, - const struct video_shader *shader, const char *preset_path); +bool video_shader_write_root_preset(const struct video_shader *shader, const char *preset_path); + /** - * video_shader_resolve_parameters: - * @conf : Preset file to read from. - * @shader : Shader passes handle. + * video_shader_write_preset: + * @path : File to write to + * @shader : Shader to write + * @reference : Whether a simple preset should be written with the #reference to another preset in it * - * Reads the current value for all parameters from config file. - * - * Returns: true (1) if successful, otherwise false (0). + * Writes a preset to disk. Can be written as a simple preset (With the #reference directive in it) or a full preset. **/ -bool video_shader_resolve_current_parameters(config_file_t *conf, - struct video_shader *shader); +bool video_shader_write_preset(const char *path, + const char *shader_dir, + const struct video_shader *shader, + bool reference); -/** - * video_shader_resolve_parameters: - * @conf : Preset file to read from. - * @shader : Shader passes handle. - * - * Resolves all shader parameters belonging to shaders. - * - * Returns: true (1) if successful, otherwise false (0). - **/ -bool video_shader_resolve_parameters(config_file_t *conf, - struct video_shader *shader); -enum rarch_shader_type video_shader_get_type_from_ext(const char *ext, - bool *is_preset); +enum rarch_shader_type video_shader_get_type_from_ext(const char *ext, bool *is_preset); /** * video_shader_parse_type: @@ -264,7 +261,7 @@ bool video_shader_any_supported(void); bool video_shader_check_for_changes(void); -const char *video_shader_to_str(enum rarch_shader_type type); +const char *video_shader_type_to_str(enum rarch_shader_type type); const char *video_shader_get_preset_extension(enum rarch_shader_type type); diff --git a/libretro-common/file/config_file.c b/libretro-common/file/config_file.c index c9bb71f0ac..9f12fe19a6 100644 --- a/libretro-common/file/config_file.c +++ b/libretro-common/file/config_file.c @@ -648,8 +648,12 @@ static int config_file_from_string_internal( void config_file_set_reference_path(config_file_t *conf, char *path) { - /* If a relative path the input path is desired the caller is - * responsible for preparing and supplying the relative path*/ + /* It is expected that the conf has it's path already set */ + + char short_path[PATH_MAX_LENGTH]; + + short_path[0] = '\0'; + if (!conf) return; @@ -659,8 +663,9 @@ void config_file_set_reference_path(config_file_t *conf, char *path) conf->reference = NULL; } - - conf->reference = strdup(path); + fill_pathname_abbreviated_or_relative(short_path, conf->path, path, sizeof(short_path)); + + conf->reference = strdup(short_path); } bool config_file_deinitialize(config_file_t *conf) @@ -1295,7 +1300,10 @@ void config_file_dump_orbis(config_file_t *conf, int fd) struct config_include_list *includes = conf->includes; if (conf->reference) + { + pathname_make_slashes_portable(conf->reference); fprintf(file, "#reference \"%s\"\n", conf->reference); + } list = config_file_merge_sort_linked_list( @@ -1338,7 +1346,10 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort) struct config_include_list *includes = conf->includes; if (conf->reference) + { + pathname_make_slashes_portable(conf->reference); fprintf(file, "#reference \"%s\"\n", conf->reference); + } if (sort) list = config_file_merge_sort_linked_list( diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index 44ceb7249a..0ab95453da 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -1110,6 +1110,100 @@ void fill_pathname_abbreviate_special(char *out_path, retro_assert(strlcpy(out_path, in_path, size) < size); } +/* Changes the slashes to the correct kind for the os + * So forward slash on linux and backslash on Windows */ +void pathname_conform_slashes_to_os(char *path) +{ + /* Conform slashes to os standard so we get proper matching */ + char* p; + for (p = path; *p; p++) + if (*p == '/' || *p == '\\') + *p = PATH_DEFAULT_SLASH_C(); +} + +/* Change all shashes to forward so they are more portable between windows and linux */ +void pathname_make_slashes_portable(char *path) +{ + /* Conform slashes to os standard so we get proper matching */ + char* p; + for (p = path; *p; p++) + if (*p == '/' || *p == '\\') + *p = '/'; +} + +/* Get the number of slashes in a path, returns an integer */ +int get_pathname_num_slashes(const char *in_path) +{ + int num_slashes = 0; + int i = 0; + + for (i = 0; i < PATH_MAX_LENGTH; i++) + { + if (PATH_CHAR_IS_SLASH(in_path[i])) + num_slashes++; + if (in_path[i] == '\0') + break; + } + + return num_slashes; +} + +/* Fills the supplied path with either the abbreviated path or the relative path, which ever + * one is has less depth / number of slashes + * If lengths of abbreviated and relative paths are the same the relative path will be used + * in_path can be an absolute, relative or abbreviated path */ +void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size) +{ + unsigned relative_length = 0; + unsigned abbreviated_length = 0; + + char in_path_conformed[PATH_MAX_LENGTH]; + char in_refpath_conformed[PATH_MAX_LENGTH]; + char expanded_path[PATH_MAX_LENGTH]; + char absolute_path[PATH_MAX_LENGTH]; + char relative_path[PATH_MAX_LENGTH]; + char abbreviated_path[PATH_MAX_LENGTH]; + + in_path_conformed[0] = '\0'; + in_refpath_conformed[0] = '\0'; + absolute_path[0] = '\0'; + relative_path[0] = '\0'; + abbreviated_path[0] = '\0'; + + strcpy(in_path_conformed, in_path); + strcpy(in_refpath_conformed, in_refpath); + + pathname_conform_slashes_to_os(in_path_conformed); + pathname_conform_slashes_to_os(in_refpath_conformed); + + /* Expand paths which start with :\ to an absolute path */ + fill_pathname_expand_special(expanded_path, in_path_conformed, sizeof(expanded_path)); + + /* Get the absolute path if it is not already */ + if (path_is_absolute(expanded_path)) + strlcpy(absolute_path, expanded_path, PATH_MAX_LENGTH); + else + fill_pathname_resolve_relative(absolute_path, in_refpath_conformed, in_path_conformed, PATH_MAX_LENGTH); + + pathname_conform_slashes_to_os(absolute_path); + + /* Get the relative path and see how many directories long it is */ + path_relative_to(relative_path, absolute_path, in_refpath_conformed, sizeof(relative_path)); + + /* Get the abbreviated path and see how many directories long it is */ + fill_pathname_abbreviate_special(abbreviated_path, absolute_path, sizeof(abbreviated_path)); + + /* Use the shortest path, preferring the relative path*/ + if (get_pathname_num_slashes(relative_path) <= get_pathname_num_slashes(abbreviated_path)) + { + retro_assert(strlcpy(out_path, relative_path, size) < size); + } + else + { + retro_assert(strlcpy(out_path, abbreviated_path, size) < size); + } +} + /** * path_basedir: * @path : path diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index 6f1918d136..4d5ed1e219 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -442,6 +442,12 @@ void fill_pathname_expand_special(char *out_path, void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size); +void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size); + +void pathname_conform_slashes_to_os(char *path); + +void pathname_make_slashes_portable(char *path); + /** * path_basedir: * @path : path diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 265a15b4df..72827157bb 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -364,7 +364,7 @@ static int action_left_shader_num_passes(unsigned type, const char *label, menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL); - video_shader_resolve_parameters(NULL, shader); + video_shader_resolve_parameters(shader); shader->modified = true; diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 5093e55f91..0028bf7d6a 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -1752,7 +1752,7 @@ static int generic_action_ok(const char *path, shader_pass->source.path, action_path, sizeof(shader_pass->source.path)); - video_shader_resolve_parameters(NULL, shader); + video_shader_resolve_parameters(shader); shader->modified = true; } @@ -5995,7 +5995,7 @@ static int action_ok_push_dropdown_item_video_shader_num_pass(const char *path, shader->passes = idx; - video_shader_resolve_parameters(NULL, shader); + video_shader_resolve_parameters(shader); shader->modified = true; diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index fd5fd82e10..acc698f14f 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -380,7 +380,7 @@ static int action_right_shader_num_passes(unsigned type, const char *label, menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL); - video_shader_resolve_parameters(NULL, shader); + video_shader_resolve_parameters(shader); shader->modified = true; diff --git a/retroarch.c b/retroarch.c index 0893172b38..f439e2ba10 100644 --- a/retroarch.c +++ b/retroarch.c @@ -5183,22 +5183,12 @@ bool menu_shader_manager_init(void) if (is_preset) { - config_file_t *conf = NULL; - - conf = video_shader_read_preset(path_shader); - - if (!conf) + if (!video_shader_load_preset_into_shader(path_shader, menu_shader)) { ret = false; goto end; } - - if (video_shader_read_conf_preset(conf, menu_shader)) - video_shader_resolve_parameters(conf, menu_shader); - menu_shader->modified = false; - - config_file_free(conf); } else { @@ -5225,7 +5215,6 @@ end: bool menu_shader_manager_set_preset(struct video_shader *shader, enum rarch_shader_type type, const char *preset_path, bool apply) { - config_file_t *conf = NULL; bool refresh = false; bool ret = false; @@ -5249,19 +5238,13 @@ bool menu_shader_manager_set_preset(struct video_shader *shader, * No point in updating when the Preset was * created from the menu itself. */ if ( !shader || - !(conf = video_shader_read_preset(preset_path))) + !(video_shader_load_preset_into_shader(preset_path, shader))) { ret = false; goto end; } - RARCH_LOG("Setting Menu shader: %s.\n", preset_path); - - if (video_shader_read_conf_preset(conf, shader)) - video_shader_resolve_parameters(conf, shader); - - if (conf) - config_file_free(conf); + RARCH_LOG("Menu shader set to: %s.\n", preset_path); ret = true; @@ -5694,7 +5677,7 @@ int menu_shader_manager_clear_num_passes(struct video_shader *shader) menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); #endif - video_shader_resolve_parameters(NULL, shader); + video_shader_resolve_parameters(shader); shader->modified = true; @@ -10410,6 +10393,9 @@ bool retroarch_apply_shader( if (!string_is_empty(preset_path)) preset_file = path_basename(preset_path); + /* TODO This loads the shader into the video driver + * But then we load the shader from disk twice more to put it in the menu + * We need to reconfigure this at some point to only load it once */ if (p_rarch->current_video->set_shader) ret = p_rarch->current_video->set_shader( p_rarch->video_driver_data, type, preset_path); diff --git a/ui/drivers/qt/shaderparamsdialog.cpp b/ui/drivers/qt/shaderparamsdialog.cpp index a428938eb2..1114394626 100644 --- a/ui/drivers/qt/shaderparamsdialog.cpp +++ b/ui/drivers/qt/shaderparamsdialog.cpp @@ -707,7 +707,7 @@ void ShaderParamsDialog::onShaderAddPassClicked() menu_driver_set_last_shader_pass_dir(pathData); #endif - video_shader_resolve_parameters(NULL, menu_shader); + video_shader_resolve_parameters(menu_shader); command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL); }