mirror of
https://github.com/libretro/RetroArch
synced 2025-02-05 15:40:04 +00:00
Shader_Preset_Simple_Save_Cleaned_2020_11_01
This commit is contained in:
parent
a2a58147e7
commit
70bf90c5d8
@ -343,6 +343,10 @@
|
|||||||
#define DEFAULT_SHADER_ENABLE false
|
#define DEFAULT_SHADER_ENABLE false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* When presets are saved they will be saved using the #reference
|
||||||
|
* directive by default */
|
||||||
|
#define DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE true
|
||||||
|
|
||||||
#define DEFAULT_SHADER_DELAY 0
|
#define DEFAULT_SHADER_DELAY 0
|
||||||
|
|
||||||
/* Only scale in integer steps.
|
/* Only scale in integer steps.
|
||||||
|
@ -1455,6 +1455,7 @@ static struct config_bool_setting *populate_settings_bool(
|
|||||||
SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, DEFAULT_SHADER_ENABLE, false);
|
SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, DEFAULT_SHADER_ENABLE, false);
|
||||||
SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, DEFAULT_VIDEO_SHADER_WATCH_FILES, false);
|
SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, DEFAULT_VIDEO_SHADER_WATCH_FILES, false);
|
||||||
SETTING_BOOL("video_shader_remember_last_dir", &settings->bools.video_shader_remember_last_dir, true, DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR, false);
|
SETTING_BOOL("video_shader_remember_last_dir", &settings->bools.video_shader_remember_last_dir, true, DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR, false);
|
||||||
|
SETTING_BOOL("video_shader_preset_save_reference_enable", &settings->bools.video_shader_preset_save_reference_enable, true, DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE, false);
|
||||||
|
|
||||||
/* Let implementation decide if automatic, or 1:1 PAR. */
|
/* Let implementation decide if automatic, or 1:1 PAR. */
|
||||||
SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, DEFAULT_ASPECT_RATIO_AUTO, false);
|
SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, DEFAULT_ASPECT_RATIO_AUTO, false);
|
||||||
|
@ -462,6 +462,7 @@ typedef struct settings
|
|||||||
bool video_shader_enable;
|
bool video_shader_enable;
|
||||||
bool video_shader_watch_files;
|
bool video_shader_watch_files;
|
||||||
bool video_shader_remember_last_dir;
|
bool video_shader_remember_last_dir;
|
||||||
|
bool video_shader_preset_save_reference_enable;
|
||||||
bool video_threaded;
|
bool video_threaded;
|
||||||
bool video_font_enable;
|
bool video_font_enable;
|
||||||
bool video_disable_composition;
|
bool video_disable_composition;
|
||||||
|
@ -417,6 +417,7 @@ static struct video_shader_parameter *video_shader_parse_find_parameter(
|
|||||||
* @shader : Shader passes handle.
|
* @shader : Shader passes handle.
|
||||||
*
|
*
|
||||||
* Reads the current value for all parameters from config file.
|
* Reads the current value for all parameters from config file.
|
||||||
|
* Checks for parameters in the parameter list which don't have a value set
|
||||||
*
|
*
|
||||||
* Returns: true (1) if successful, otherwise false (0).
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
**/
|
**/
|
||||||
@ -440,6 +441,7 @@ bool video_shader_resolve_current_parameters(config_file_t *conf,
|
|||||||
for ( id = strtok_r(parameters, ";", &save); id;
|
for ( id = strtok_r(parameters, ";", &save); id;
|
||||||
id = strtok_r(NULL, ";", &save))
|
id = strtok_r(NULL, ";", &save))
|
||||||
{
|
{
|
||||||
|
/* Get the parameter in the shader matching this name */
|
||||||
struct video_shader_parameter *parameter =
|
struct video_shader_parameter *parameter =
|
||||||
(struct video_shader_parameter*)
|
(struct video_shader_parameter*)
|
||||||
video_shader_parse_find_parameter(
|
video_shader_parse_find_parameter(
|
||||||
@ -465,6 +467,8 @@ bool video_shader_resolve_current_parameters(config_file_t *conf,
|
|||||||
* @shader : Shader passes handle.
|
* @shader : Shader passes handle.
|
||||||
*
|
*
|
||||||
* Resolves all shader parameters belonging to shaders.
|
* Resolves all shader parameters belonging to shaders.
|
||||||
|
* Fills the parameter definition list of the shader
|
||||||
|
* Does not read any of the config parameter values
|
||||||
*
|
*
|
||||||
* Returns: true (1) if successful, otherwise false (0).
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
**/
|
**/
|
||||||
@ -571,6 +575,375 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
|||||||
return video_shader_resolve_current_parameters(conf, shader);
|
return video_shader_resolve_current_parameters(conf, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static void make_relative_path_portable(char* path)
|
||||||
|
{
|
||||||
|
/* use '/' instead of '\' for maximum portability */
|
||||||
|
char* p;
|
||||||
|
for (p = path; *p; p++)
|
||||||
|
if (*p == '\\')
|
||||||
|
*p = '/';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* video_shader_write_referenced_preset:
|
||||||
|
* @path : File to write to
|
||||||
|
* @shader : Shader preset to write
|
||||||
|
*
|
||||||
|
* Writes a referenced preset to disk
|
||||||
|
* A referenced preset is a preset which includes the #reference directive
|
||||||
|
* 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,
|
||||||
|
const struct video_shader *shader)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
bool ret = false;
|
||||||
|
bool continue_saving_reference = true;
|
||||||
|
char preset_dir[PATH_MAX_LENGTH];
|
||||||
|
config_file_t *conf;
|
||||||
|
char *absolute_root_preset_path = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
char *absolute_new_preset_basedir = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
char *relative_root_preset_path = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
|
||||||
|
preset_dir[0] = '\0';
|
||||||
|
absolute_new_preset_basedir = strdup(path);
|
||||||
|
path_basedir(absolute_new_preset_basedir);
|
||||||
|
absolute_root_preset_path[0] = '\0';
|
||||||
|
relative_root_preset_path[0] = '\0';
|
||||||
|
|
||||||
|
/* Get the absolute path to the root preset, this is the one which is used in the #reference directive */
|
||||||
|
strlcpy(absolute_root_preset_path, shader->path, PATH_MAX_LENGTH);
|
||||||
|
if (string_is_empty(shader->path))
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can't save a reference to ourselves */
|
||||||
|
if (string_is_equal(shader->path, path))
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Saving Full Preset because we can't save a preset "
|
||||||
|
"which would reference itself.\n");
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auto-shaders can be written as copies or references.
|
||||||
|
* If we write a reference to a copy, we could then overwrite the copy
|
||||||
|
* with any reference, thus creating a reference to a reference.
|
||||||
|
* To prevent this, we disallow saving references to auto-shaders. */
|
||||||
|
fill_pathname_join(preset_dir,
|
||||||
|
shader_dir,
|
||||||
|
"presets",
|
||||||
|
sizeof(preset_dir));
|
||||||
|
if (continue_saving_reference && !strncmp(preset_dir, absolute_root_preset_path, strlen(preset_dir)))
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Saving Full Preset because we can't save a "
|
||||||
|
"reference to an auto-loaded shader (E.G. Game Preset, Core Preset).\n");
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't ever create a reference to the ever-changing retroarch preset
|
||||||
|
* TODO remove once we don't write this preset anymore */
|
||||||
|
if (continue_saving_reference && !strncmp(path_basename(absolute_root_preset_path), "retroarch", STRLEN_CONST("retroarch")))
|
||||||
|
{
|
||||||
|
continue_saving_reference = false;
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Saving Full Preset because we can't save a reference "
|
||||||
|
"to the ever-changing retroarch preset.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference)
|
||||||
|
{
|
||||||
|
config_file_t *root_conf;
|
||||||
|
|
||||||
|
path_relative_to(relative_root_preset_path,
|
||||||
|
absolute_root_preset_path,
|
||||||
|
absolute_new_preset_basedir,
|
||||||
|
PATH_MAX_LENGTH);
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!path_is_absolute(relative_root_preset_path))
|
||||||
|
make_relative_path_portable(relative_root_preset_path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create a new EMPTY config */
|
||||||
|
conf = config_file_new_alloc();
|
||||||
|
if (!(conf))
|
||||||
|
return false;
|
||||||
|
conf->path = strdup(path);
|
||||||
|
|
||||||
|
/* Add the reference path to the config */
|
||||||
|
config_file_set_reference_path(conf, relative_root_preset_path);
|
||||||
|
|
||||||
|
/* Set modified to true so when you run config_file_write it will save a file */
|
||||||
|
conf->modified = true;
|
||||||
|
|
||||||
|
/* Get a config from root preset which was defined by the #reference directive
|
||||||
|
* to compare the current shader against */
|
||||||
|
root_conf = config_file_new_from_path_to_string(absolute_root_preset_path);
|
||||||
|
|
||||||
|
/* root_conf could be NULL if the file was not found */
|
||||||
|
if (root_conf == NULL)
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Saving Full Preset because we could not "
|
||||||
|
"load the Root Preset: %s.\n",
|
||||||
|
absolute_root_preset_path);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Compare the shader to a shader created from the root config to see if
|
||||||
|
we can save a referenced preset and what parameters and textures of the
|
||||||
|
root_config are overridden
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct video_shader *root_shader = NULL;
|
||||||
|
root_shader = (struct video_shader*) calloc(1, sizeof(*root_shader));
|
||||||
|
video_shader_read_conf_preset(root_conf, root_shader);
|
||||||
|
|
||||||
|
/* Check number of passes match */
|
||||||
|
if (shader->passes != root_shader->passes)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: passes (Number of Passes)");
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* 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 Reference]: Pass %u path", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && pass->filter != root_pass->filter)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u filter", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && pass->wrap != root_pass->wrap)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: 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 Reference]: Pass %u frame_count", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && pass->mipmap != root_pass->mipmap)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u mipmap", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && !string_is_equal(pass->alias, root_pass->alias))
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u alias", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->type_x != root_fbo->type_x)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u type_x", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->type_y != root_fbo->type_y)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u type_y", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->scale_x != root_fbo->scale_x)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u scale_x", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->scale_y != root_fbo->scale_y)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u scale_y", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->fp_fbo != root_fbo->fp_fbo)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u fp_fbo", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->srgb_fbo != root_fbo->srgb_fbo)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u srgb_fbo", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->valid != root_fbo->valid)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u valid", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->abs_x != root_fbo->abs_x)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Pass %u abs_x", i);
|
||||||
|
continue_saving_reference = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference && fbo->abs_y != root_fbo->abs_y)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (continue_saving_reference)
|
||||||
|
{
|
||||||
|
const struct config_entry_list *entry = NULL;
|
||||||
|
|
||||||
|
/* If the shader has parameters */
|
||||||
|
if (shader->num_parameters)
|
||||||
|
{
|
||||||
|
size_t param_size = 4096 * sizeof(char);
|
||||||
|
char *override_parameters = (char*)malloc(param_size);
|
||||||
|
float parameter_value_reference;
|
||||||
|
|
||||||
|
param_size = 4096 * sizeof(char);
|
||||||
|
override_parameters[0] = '\0';
|
||||||
|
parameter_value_reference = 0.0f;
|
||||||
|
|
||||||
|
if (override_parameters)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < shader->num_parameters; i++)
|
||||||
|
{
|
||||||
|
bool add_param_to_override = false;
|
||||||
|
|
||||||
|
entry = config_get_entry(root_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(root_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 name to the parameters list */
|
||||||
|
if (add_param_to_override)
|
||||||
|
{
|
||||||
|
config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current);
|
||||||
|
strlcat(override_parameters, ";", param_size);
|
||||||
|
strlcat(override_parameters, shader->parameters[i].id, param_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the list of override parameter names if there are any*/
|
||||||
|
if (!string_is_empty(override_parameters))
|
||||||
|
config_set_string(conf, "parameters", override_parameters);
|
||||||
|
}
|
||||||
|
free(override_parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the shader has textures */
|
||||||
|
if (shader->luts)
|
||||||
|
{
|
||||||
|
char *shader_tex_path = (char*)malloc(3*PATH_MAX_LENGTH);
|
||||||
|
char *shader_tex_relative_path = shader_tex_path + PATH_MAX_LENGTH;
|
||||||
|
char *shader_tex_base_path = shader_tex_path + 2*PATH_MAX_LENGTH;
|
||||||
|
char *referenced_tex_absolute_path = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
char *referenced_tex_path = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
size_t tex_size = 4096 * sizeof(char);
|
||||||
|
char *textures = (char*)malloc(tex_size);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
shader_tex_path[0] = '\0';
|
||||||
|
shader_tex_relative_path[0] = '\0';
|
||||||
|
shader_tex_base_path[0] = '\0';
|
||||||
|
textures[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(root_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,
|
||||||
|
root_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 Reference]: 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Write the file, return will be true if successful */
|
||||||
|
ret = config_file_write(conf, path, false);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
RARCH_WARN("[Shaders-Save Reference]: Failed writing Referenced Preset to %s - "
|
||||||
|
"Full Preset Will be Saved instead of Simple Preset\n", path);
|
||||||
|
}
|
||||||
|
config_file_free(root_conf);
|
||||||
|
}
|
||||||
|
config_file_free(conf);
|
||||||
|
}
|
||||||
|
free(relative_root_preset_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* video_shader_write_preset:
|
* video_shader_write_preset:
|
||||||
* @path : File to write to
|
* @path : File to write to
|
||||||
@ -586,9 +959,9 @@ bool video_shader_write_preset(const char *path,
|
|||||||
{
|
{
|
||||||
/* We need to clean up paths to be able to properly process them
|
/* We need to clean up paths to be able to properly process them
|
||||||
* path and shader->path can use '/' on Windows due to Qt being Qt */
|
* path and shader->path can use '/' on Windows due to Qt being Qt */
|
||||||
char clean_path[PATH_MAX_LENGTH];
|
|
||||||
char clean_shader_path[PATH_MAX_LENGTH];
|
|
||||||
char preset_dir[PATH_MAX_LENGTH];
|
char preset_dir[PATH_MAX_LENGTH];
|
||||||
|
config_file_t *conf;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
if (!shader || string_is_empty(path))
|
if (!shader || string_is_empty(path))
|
||||||
return false;
|
return false;
|
||||||
@ -599,178 +972,160 @@ bool video_shader_write_preset(const char *path,
|
|||||||
"presets",
|
"presets",
|
||||||
sizeof(preset_dir));
|
sizeof(preset_dir));
|
||||||
|
|
||||||
strlcpy(clean_shader_path, shader->path, sizeof(clean_shader_path));
|
/* If we should still save a referenced preset do it now */
|
||||||
path_resolve_realpath(clean_shader_path, sizeof(clean_shader_path), false);
|
|
||||||
|
|
||||||
if (string_is_empty(shader->path))
|
|
||||||
reference = false;
|
|
||||||
|
|
||||||
/* Auto-shaders can be written as copies or references.
|
|
||||||
* If we write a reference to a copy, we could then overwrite the copy
|
|
||||||
* with any reference, thus creating a reference to a reference.
|
|
||||||
* To prevent this, we disallow saving references to auto-shaders. */
|
|
||||||
if (reference && !strncmp(preset_dir, clean_shader_path, strlen(preset_dir)))
|
|
||||||
reference = false;
|
|
||||||
|
|
||||||
/* Don't ever create a reference to the ever-changing retroarch preset
|
|
||||||
* TODO remove once we don't write this preset anymore */
|
|
||||||
if (reference && !strncmp(path_basename(clean_shader_path), "retroarch", STRLEN_CONST("retroarch")))
|
|
||||||
reference = false;
|
|
||||||
|
|
||||||
if (reference)
|
if (reference)
|
||||||
{
|
if (video_shader_write_referenced_preset(path, shader_dir, shader))
|
||||||
/* write a reference preset */
|
return true;
|
||||||
char buf[STRLEN_CONST("#reference \"") + PATH_MAX_LENGTH + 1] = "#reference \"";
|
|
||||||
size_t len = STRLEN_CONST("#reference \"");
|
|
||||||
char *preset_ref = buf + len;
|
|
||||||
|
|
||||||
strlcpy(clean_path, path, sizeof(clean_path));
|
/* If we aren't saving a referenced preset or weren't able to save one
|
||||||
path_resolve_realpath(clean_path, sizeof(clean_path), false);
|
* then save a full preset */
|
||||||
|
|
||||||
path_relative_to(preset_ref, clean_shader_path, clean_path, PATH_MAX_LENGTH);
|
/* Note: We always create a new/blank config
|
||||||
len += strlen(preset_ref);
|
* file here. Loading and updating an existing
|
||||||
|
* file could leave us with unwanted/invalid
|
||||||
|
* parameters. */
|
||||||
|
if (!(conf = config_file_new_alloc()))
|
||||||
|
return false;
|
||||||
|
|
||||||
buf[len++] = '\"';
|
video_shader_write_conf_preset(conf, shader, path);
|
||||||
|
|
||||||
return filestream_write_file(clean_path, (void *)buf, len);
|
ret = config_file_write(conf, path, false);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* regular saving function */
|
|
||||||
config_file_t *conf;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
/* Note: We always create a new/blank config
|
config_file_free(conf);
|
||||||
* 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);
|
return ret;
|
||||||
|
|
||||||
ret = config_file_write(conf, path, false);
|
|
||||||
|
|
||||||
config_file_free(conf);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* video_shader_read_reference_path:
|
* override_config_values:
|
||||||
* @path : File to read
|
* @conf : Config file to be affected
|
||||||
|
* @override_conf : Config file who's values will be copied on top of conf
|
||||||
*
|
*
|
||||||
* Returns: the reference path of a preset if it exists,
|
* Takes values from override_config and overrides values of conf
|
||||||
* otherwise returns NULL.
|
* The 'parameters' value will be the combined parameter list from both configs
|
||||||
*
|
*
|
||||||
* The returned string needs to be freed.
|
* Returns 0 if nothing is overridden
|
||||||
*/
|
* Returns 1 if something is overridden
|
||||||
static char *video_shader_read_reference_path(const char *path)
|
**/
|
||||||
|
bool override_config_values(config_file_t *conf, config_file_t *override_conf)
|
||||||
{
|
{
|
||||||
/* We want shader presets that point to other presets.
|
int return_val = 0;
|
||||||
*
|
size_t param_size = 4096 * sizeof(char);
|
||||||
* While config_file_new_from_path_to_string() does support the
|
const char *id = NULL;
|
||||||
* #include directive, it will not rebase relative paths on
|
char *save = NULL;
|
||||||
* the include path.
|
size_t path_size = PATH_MAX_LENGTH;
|
||||||
*
|
char *override_texture_path = (char*)malloc(path_size);
|
||||||
* There's a plethora of reasons why a general solution is hard:
|
char *resolved_path = (char*)malloc(path_size);
|
||||||
* - it's impossible to distinguish a generic string from a (relative) path
|
char *textures_in_conf = (char*)malloc(param_size);
|
||||||
* - config_file_new_from_path_to_string() doesn't return the include path,
|
size_t tmp_size = PATH_MAX_LENGTH;
|
||||||
* so we cannot rebase afterwards
|
char *tmp = (char*)malloc(3*tmp_size);
|
||||||
* - #include is recursive, so we'd actually need to track the include path
|
char *tmp_rel = tmp + tmp_size;
|
||||||
* for every setting
|
char *tmp_base = tmp + 2*tmp_size;
|
||||||
*
|
struct config_entry_list *override_entry = NULL;
|
||||||
* So instead, we use a custom #reference directive, which is just a
|
char *override_parameters = (char*)malloc(param_size);
|
||||||
* one-time/non-recursive redirection, e.g.
|
|
||||||
*
|
|
||||||
* #reference "<path to config>"
|
|
||||||
* or
|
|
||||||
* #reference <path to config>
|
|
||||||
*
|
|
||||||
* which we will load as config_file_new_from_path_to_string(<path to config>).
|
|
||||||
*/
|
|
||||||
char *reference = NULL;
|
|
||||||
RFILE *file = NULL;
|
|
||||||
char *line = NULL;
|
|
||||||
|
|
||||||
if (string_is_empty(path) || !path_is_valid(path))
|
override_parameters[0] = '\0';
|
||||||
return NULL;
|
textures_in_conf[0] = '\0';
|
||||||
file = filestream_open(path,
|
strlcpy(tmp_base, conf->path, tmp_size);
|
||||||
RETRO_VFS_FILE_ACCESS_READ,
|
|
||||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
|
||||||
if (!file)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
line = filestream_getline(file);
|
if (conf == NULL || override_conf == NULL) return 0;
|
||||||
filestream_close(file);
|
|
||||||
|
|
||||||
if (line && !strncmp("#reference", line, STRLEN_CONST("#reference")))
|
/* ---------------------------------------------------------------------------------
|
||||||
{
|
* ------------- Resolve Override texture paths to absolute paths-------------------
|
||||||
char *ref_path = line + STRLEN_CONST("#reference");
|
* --------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* have at least 1 whitespace */
|
/* ensure we use a clean base like the shader passes and texture paths do */
|
||||||
if (!isspace((unsigned char)*ref_path))
|
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))
|
||||||
{
|
{
|
||||||
free(line);
|
for ( id = strtok_r(textures_in_conf, ";", &save);
|
||||||
return NULL;
|
id;
|
||||||
}
|
id = strtok_r(NULL, ";", &save))
|
||||||
ref_path++;
|
|
||||||
|
|
||||||
while (isspace((unsigned char)*ref_path))
|
|
||||||
ref_path++;
|
|
||||||
|
|
||||||
if (*ref_path == '\"')
|
|
||||||
{
|
|
||||||
/* remove "" */
|
|
||||||
char *p;
|
|
||||||
ref_path++;
|
|
||||||
|
|
||||||
p = ref_path;
|
|
||||||
while (*p != '\0' && *p != '\"')
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (*p == '\"')
|
|
||||||
*p = '\0';
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* if there's no second ", remove whitespace at the end */
|
/* Get the texture path from the override config */
|
||||||
p--;
|
if (config_get_path(override_conf, id, override_texture_path, path_size))
|
||||||
while (isspace((unsigned char)*p))
|
{
|
||||||
*p-- = '\0';
|
/* 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/* ---------------------------------------------------------------------------------
|
||||||
|
* -------------Update Parameter List to include Override Parameters----------------
|
||||||
|
* --------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* If there is a 'parameters' entry in the override config we want to add these parameters
|
||||||
|
* to the referenced config if they are not already there */
|
||||||
|
if (config_get_array(override_conf, "parameters", override_parameters, param_size))
|
||||||
{
|
{
|
||||||
/* remove whitespace at the end (e.g. carriage return) */
|
/* Get the string for the parameters from the root config */
|
||||||
char *end = ref_path + strlen(ref_path) - 1;
|
char *parameters = NULL;
|
||||||
while (isspace((unsigned char)*end))
|
parameters = (char*)malloc(param_size);
|
||||||
*end-- = '\0';
|
parameters[0] = '\0';
|
||||||
|
|
||||||
|
/* If there are is no parameters entry in the root config, add one */
|
||||||
|
if (!config_get_array(conf, "parameters", parameters, param_size))
|
||||||
|
{
|
||||||
|
config_set_string(conf, "parameters", "");
|
||||||
|
config_get_array(conf, "parameters", parameters, param_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step through each parameter in override config */
|
||||||
|
for ( id = strtok_r(override_parameters, ";", &save);
|
||||||
|
id;
|
||||||
|
id = strtok_r(NULL, ";", &save))
|
||||||
|
{
|
||||||
|
/* If the parameter is not in the root config's parameter list add it */
|
||||||
|
if (!strstr(parameters, id))
|
||||||
|
{
|
||||||
|
strlcat(parameters, ";", param_size);
|
||||||
|
strlcat(parameters, id, param_size);
|
||||||
|
return_val = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config_set_string(conf, "parameters", strdup(parameters));
|
||||||
|
|
||||||
|
free(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string_is_empty(ref_path))
|
/* ---------------------------------------------------------------------------------
|
||||||
|
* ------------- Update entries to match the override entries ----------------------
|
||||||
|
* --------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
for (override_entry = override_conf->entries; override_entry; override_entry = override_entry->next)
|
||||||
{
|
{
|
||||||
free(line);
|
/* Only override an entry if the it's key is not "parameters", and not in list of textures */
|
||||||
return NULL;
|
if (!string_is_empty(override_entry->key) && !string_is_equal(override_entry->key, "parameters") && !string_is_equal(override_entry->key, "textures"))
|
||||||
|
{
|
||||||
|
RARCH_LOG("[Shaders-Load Reference]: Entry overridden %s = %s.\n",
|
||||||
|
override_entry->key, override_entry->value);
|
||||||
|
config_set_string(conf, override_entry->key, strdup(override_entry->value));
|
||||||
|
return_val = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reference = (char *)malloc(PATH_MAX_LENGTH);
|
free(tmp);
|
||||||
|
free(resolved_path);
|
||||||
|
free(override_texture_path);
|
||||||
|
free(override_parameters);
|
||||||
|
free(textures_in_conf);
|
||||||
|
|
||||||
if (!reference)
|
return return_val;
|
||||||
{
|
|
||||||
free(line);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rebase relative reference path */
|
|
||||||
fill_pathname_resolve_relative(reference,
|
|
||||||
path, ref_path, PATH_MAX_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line)
|
|
||||||
free(line);
|
|
||||||
|
|
||||||
return reference;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -787,15 +1142,52 @@ static char *video_shader_read_reference_path(const char *path)
|
|||||||
**/
|
**/
|
||||||
config_file_t *video_shader_read_preset(const char *path)
|
config_file_t *video_shader_read_preset(const char *path)
|
||||||
{
|
{
|
||||||
char *reference = video_shader_read_reference_path(path);
|
config_file_t *conf;
|
||||||
if (reference)
|
conf = config_file_new_from_path_to_string(path);
|
||||||
|
|
||||||
|
if (conf != NULL)
|
||||||
{
|
{
|
||||||
config_file_t *conf =
|
/* If the original config had a reference then it was really
|
||||||
config_file_new_from_path_to_string(reference);
|
* the override config. We now load a new config from the reference
|
||||||
free(reference);
|
* then override it's values with the override config */
|
||||||
return conf;
|
if (conf->reference)
|
||||||
|
{
|
||||||
|
char* root_preset_path = (char*)malloc(PATH_MAX_LENGTH);
|
||||||
|
/* Set override_conf to refer to the original config */
|
||||||
|
config_file_t *override_conf = conf;
|
||||||
|
|
||||||
|
/* Resolve the reference path relative to the config */
|
||||||
|
if (path_is_absolute(conf->reference))
|
||||||
|
strlcpy(root_preset_path, conf->reference, PATH_MAX_LENGTH);
|
||||||
|
else
|
||||||
|
fill_pathname_resolve_relative(root_preset_path,
|
||||||
|
conf->path,
|
||||||
|
conf->reference,
|
||||||
|
PATH_MAX_LENGTH);
|
||||||
|
|
||||||
|
/* Create a new config from the root preset */
|
||||||
|
conf = config_file_new_from_path_to_string(root_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("[ SHADER LOAD ] Could not read root shader preset in '#reference' line: %s\n", root_preset_path);
|
||||||
|
|
||||||
|
free(root_preset_path);
|
||||||
|
config_file_free(override_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Path for originally loaded preset */
|
||||||
|
config_set_path(conf, "loaded_preset_path", path);
|
||||||
}
|
}
|
||||||
return config_file_new_from_path_to_string(path);
|
else
|
||||||
|
RARCH_WARN("[ SHADER LOAD ] Could not read preset: %s", path);
|
||||||
|
|
||||||
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -815,6 +1207,7 @@ bool video_shader_read_conf_preset(config_file_t *conf,
|
|||||||
unsigned shaders = 0;
|
unsigned shaders = 0;
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
bool watch_files = settings->bools.video_shader_watch_files;
|
bool watch_files = settings->bools.video_shader_watch_files;
|
||||||
|
char loaded_preset_path[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
memset(shader, 0, sizeof(*shader));
|
memset(shader, 0, sizeof(*shader));
|
||||||
|
|
||||||
@ -826,7 +1219,7 @@ bool video_shader_read_conf_preset(config_file_t *conf,
|
|||||||
|
|
||||||
if (!shaders)
|
if (!shaders)
|
||||||
{
|
{
|
||||||
RARCH_ERR("[Shaders]: Need to define at least 1 shader.\n");
|
RARCH_ERR("[Shaders]: Need to define at least 1 shader pass.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,8 +1229,17 @@ bool video_shader_read_conf_preset(config_file_t *conf,
|
|||||||
|
|
||||||
shader->passes = MIN(shaders, GFX_MAX_SHADERS);
|
shader->passes = MIN(shaders, GFX_MAX_SHADERS);
|
||||||
|
|
||||||
|
/* Set the path of the root preset for this shader */
|
||||||
strlcpy(shader->path, conf->path, sizeof(shader->path));
|
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);
|
||||||
|
strlcpy( shader->loaded_preset_path,
|
||||||
|
loaded_preset_path,
|
||||||
|
sizeof(shader->loaded_preset_path));
|
||||||
|
|
||||||
if (watch_files)
|
if (watch_files)
|
||||||
{
|
{
|
||||||
union string_list_elem_attr attr;
|
union string_list_elem_attr attr;
|
||||||
@ -858,6 +1260,9 @@ bool video_shader_read_conf_preset(config_file_t *conf,
|
|||||||
string_list_initialize(&file_list);
|
string_list_initialize(&file_list);
|
||||||
string_list_append(&file_list, conf->path, attr);
|
string_list_append(&file_list, conf->path, attr);
|
||||||
|
|
||||||
|
/* TODO We aren't currently watching the originally loaded preset
|
||||||
|
* We should probably watch it for changes too */
|
||||||
|
|
||||||
for (i = 0; i < shader->passes; i++)
|
for (i = 0; i < shader->passes; i++)
|
||||||
{
|
{
|
||||||
if (!video_shader_parse_pass(conf, &shader->pass[i], i))
|
if (!video_shader_parse_pass(conf, &shader->pass[i], i))
|
||||||
@ -944,17 +1349,6 @@ static void shader_write_fbo(config_file_t *conf,
|
|||||||
fbo->scale_y, fbo->abs_y, i);
|
fbo->scale_y, fbo->abs_y, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static void make_relative_path_portable(char *path)
|
|
||||||
{
|
|
||||||
/* use '/' instead of '\' for maximum portability */
|
|
||||||
char *p;
|
|
||||||
for (p = path; *p; p++)
|
|
||||||
if (*p == '\\')
|
|
||||||
*p = '/';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* video_shader_write_conf_preset:
|
* video_shader_write_conf_preset:
|
||||||
* @conf : Preset file to write to.
|
* @conf : Preset file to write to.
|
||||||
|
@ -153,8 +153,14 @@ struct video_shader
|
|||||||
unsigned variables;
|
unsigned variables;
|
||||||
|
|
||||||
char prefix[64];
|
char prefix[64];
|
||||||
|
|
||||||
|
/* Path to the root preset */
|
||||||
char path[PATH_MAX_LENGTH];
|
char path[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
|
/* Path to the original preset loaded, if this is a preset with the #reference
|
||||||
|
* directive then this will be different than the path*/
|
||||||
|
char loaded_preset_path[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
bool modern; /* Only used for XML shaders. */
|
bool modern; /* Only used for XML shaders. */
|
||||||
/* indicative of whether shader was modified -
|
/* indicative of whether shader was modified -
|
||||||
* for instance from the menus */
|
* for instance from the menus */
|
||||||
|
@ -3230,6 +3230,10 @@ MSG_HASH(
|
|||||||
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE,
|
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE,
|
||||||
"video_shader_preset_save"
|
"video_shader_preset_save"
|
||||||
)
|
)
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
"video_shader_preset_save_reference"
|
||||||
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS,
|
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS,
|
||||||
"video_shader_preset_save_as"
|
"video_shader_preset_save_as"
|
||||||
|
@ -6674,6 +6674,16 @@ MSG_HASH(
|
|||||||
|
|
||||||
/* Quick Menu > Shaders > Save */
|
/* Quick Menu > Shaders > Save */
|
||||||
|
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
"Save Simple Preset"
|
||||||
|
)
|
||||||
|
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
"Saves a Shader Preset which has a link to the original preset loaded and includes only the parameter changes you made."
|
||||||
|
)
|
||||||
|
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS,
|
MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS,
|
||||||
"Save Shader Preset As"
|
"Save Shader Preset As"
|
||||||
|
@ -466,40 +466,48 @@ static bool config_file_parse_line(config_file_t *conf,
|
|||||||
char real_path[PATH_MAX_LENGTH];
|
char real_path[PATH_MAX_LENGTH];
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *include_line = NULL;
|
char *include_line = NULL;
|
||||||
|
char *reference_line = NULL;
|
||||||
|
|
||||||
/* Starting a line with an 'include' directive
|
/* Starting a line with an 'include' directive
|
||||||
* appends a sub-config file
|
* appends a sub-config file
|
||||||
* > All other comments are ignored */
|
* > All other comments are ignored */
|
||||||
if (!string_starts_with_size(comment, "include ",
|
if (!string_starts_with_size(comment, "include ",
|
||||||
STRLEN_CONST("include ")))
|
STRLEN_CONST("include ")) &&
|
||||||
|
!string_starts_with_size(comment, "reference ",
|
||||||
|
STRLEN_CONST("reference ")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
include_line = comment + STRLEN_CONST("include ");
|
/* Starting a line with an 'include' directive
|
||||||
|
* appends a sub-config file */
|
||||||
|
if (string_starts_with_size(comment, "include ",
|
||||||
|
STRLEN_CONST("include ")))
|
||||||
|
{
|
||||||
|
include_line = comment + STRLEN_CONST("include ");
|
||||||
|
|
||||||
if (string_is_empty(include_line))
|
if (string_is_empty(include_line))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
path = config_file_extract_value(include_line, false);
|
path = config_file_extract_value(include_line, false);
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( string_is_empty(path)
|
if ( string_is_empty(path)
|
||||||
|| conf->include_depth >= MAX_INCLUDE_DEPTH)
|
|| conf->include_depth >= MAX_INCLUDE_DEPTH)
|
||||||
{
|
{
|
||||||
free(path);
|
free(path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
real_path[0] = '\0';
|
real_path[0] = '\0';
|
||||||
config_file_add_sub_conf(conf, path,
|
config_file_add_sub_conf(conf, path,
|
||||||
real_path, sizeof(real_path), cb);
|
real_path, sizeof(real_path), cb);
|
||||||
|
|
||||||
config_file_initialize(&sub_conf);
|
config_file_initialize(&sub_conf);
|
||||||
|
|
||||||
switch (config_file_load_internal(&sub_conf, real_path,
|
switch (config_file_load_internal(&sub_conf, real_path,
|
||||||
conf->include_depth + 1, cb))
|
conf->include_depth + 1, cb))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
/* Pilfer internal list. */
|
/* Pilfer internal list. */
|
||||||
config_file_add_child_list(conf, &sub_conf);
|
config_file_add_child_list(conf, &sub_conf);
|
||||||
@ -510,6 +518,27 @@ static bool config_file_parse_line(config_file_t *conf,
|
|||||||
case 1:
|
case 1:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's a 'reference' directive */
|
||||||
|
if (string_starts_with_size(comment, "reference ",
|
||||||
|
STRLEN_CONST("reference ")))
|
||||||
|
{
|
||||||
|
reference_line = comment + STRLEN_CONST("reference ");
|
||||||
|
|
||||||
|
if (string_is_empty(reference_line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
path = config_file_extract_value(reference_line, false);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config_file_set_reference_path(conf, path);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(path);
|
free(path);
|
||||||
@ -617,6 +646,16 @@ static int config_file_from_string_internal(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void config_file_set_reference_path(config_file_t *conf, char *path)
|
||||||
|
{
|
||||||
|
if (conf)
|
||||||
|
{
|
||||||
|
/* Assumes if you wanted a relative path the input path is
|
||||||
|
* already relative to the config
|
||||||
|
*/
|
||||||
|
conf->reference = strdup(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool config_file_deinitialize(config_file_t *conf)
|
bool config_file_deinitialize(config_file_t *conf)
|
||||||
{
|
{
|
||||||
@ -774,6 +813,7 @@ void config_file_initialize(struct config_file *conf)
|
|||||||
conf->entries = NULL;
|
conf->entries = NULL;
|
||||||
conf->tail = NULL;
|
conf->tail = NULL;
|
||||||
conf->last = NULL;
|
conf->last = NULL;
|
||||||
|
conf->reference = NULL;
|
||||||
conf->includes = NULL;
|
conf->includes = NULL;
|
||||||
conf->include_depth = 0;
|
conf->include_depth = 0;
|
||||||
conf->guaranteed_no_duplicates = false;
|
conf->guaranteed_no_duplicates = false;
|
||||||
@ -1245,6 +1285,10 @@ void config_file_dump_orbis(config_file_t *conf, int fd)
|
|||||||
{
|
{
|
||||||
struct config_entry_list *list = NULL;
|
struct config_entry_list *list = NULL;
|
||||||
struct config_include_list *includes = conf->includes;
|
struct config_include_list *includes = conf->includes;
|
||||||
|
|
||||||
|
if (conf->reference)
|
||||||
|
fprintf(file, "#reference \"%s\"\n", conf->reference);
|
||||||
|
|
||||||
while (includes)
|
while (includes)
|
||||||
{
|
{
|
||||||
char cad[256];
|
char cad[256];
|
||||||
@ -1278,6 +1322,9 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
|
|||||||
struct config_entry_list *list = NULL;
|
struct config_entry_list *list = NULL;
|
||||||
struct config_include_list *includes = conf->includes;
|
struct config_include_list *includes = conf->includes;
|
||||||
|
|
||||||
|
if (conf->reference)
|
||||||
|
fprintf(file, "#reference \"%s\"\n", conf->reference);
|
||||||
|
|
||||||
while (includes)
|
while (includes)
|
||||||
{
|
{
|
||||||
fprintf(file, "#include \"%s\"\n", includes->path);
|
fprintf(file, "#include \"%s\"\n", includes->path);
|
||||||
|
@ -54,6 +54,7 @@ RETRO_BEGIN_DECLS
|
|||||||
struct config_file
|
struct config_file
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
|
char *reference;
|
||||||
struct config_entry_list *entries;
|
struct config_entry_list *entries;
|
||||||
struct config_entry_list *tail;
|
struct config_entry_list *tail;
|
||||||
struct config_entry_list *last;
|
struct config_entry_list *last;
|
||||||
@ -107,6 +108,8 @@ config_file_t *config_file_new_from_path_to_string(const char *path);
|
|||||||
/* Frees config file. */
|
/* Frees config file. */
|
||||||
void config_file_free(config_file_t *conf);
|
void config_file_free(config_file_t *conf);
|
||||||
|
|
||||||
|
void config_file_set_reference_path(config_file_t *conf, char *path);
|
||||||
|
|
||||||
bool config_file_deinitialize(config_file_t *conf);
|
bool config_file_deinitialize(config_file_t *conf);
|
||||||
|
|
||||||
/* Loads a new config, and appends its data to conf.
|
/* Loads a new config, and appends its data to conf.
|
||||||
|
@ -2893,6 +2893,11 @@ static int generic_action_ok_shader_preset_save(const char *path,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save Auto Preset and have it immediately reapply the preset
|
||||||
|
* TODO: This seems necessary so that the loaded shader gains a link to the file saved
|
||||||
|
* But this is slow and seems like a redundant way to do this
|
||||||
|
* It seems like it would be better to just set the path and shader_preset_loaded
|
||||||
|
* on the current shader */
|
||||||
if (menu_shader_manager_save_auto_preset(menu_shader_get(), preset_type,
|
if (menu_shader_manager_save_auto_preset(menu_shader_get(), preset_type,
|
||||||
dir_video_shader, dir_menu_config,
|
dir_video_shader, dir_menu_config,
|
||||||
true))
|
true))
|
||||||
|
@ -5311,6 +5311,10 @@ unsigned menu_displaylist_build_list(
|
|||||||
case DISPLAYLIST_SHADER_PRESET_SAVE:
|
case DISPLAYLIST_SHADER_PRESET_SAVE:
|
||||||
{
|
{
|
||||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||||
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
|
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
PARSE_ONLY_BOOL, false) == 0)
|
||||||
|
count++;
|
||||||
if (menu_entries_append_enum(list,
|
if (menu_entries_append_enum(list,
|
||||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS),
|
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS),
|
||||||
msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS),
|
msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS),
|
||||||
|
@ -9170,6 +9170,21 @@ static bool setting_append_list(
|
|||||||
general_read_handler,
|
general_read_handler,
|
||||||
SD_FLAG_NONE);
|
SD_FLAG_NONE);
|
||||||
|
|
||||||
|
CONFIG_BOOL(
|
||||||
|
list, list_info,
|
||||||
|
&settings->bools.video_shader_preset_save_reference_enable,
|
||||||
|
MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_REFERENCE,
|
||||||
|
DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE,
|
||||||
|
MENU_ENUM_LABEL_VALUE_OFF,
|
||||||
|
MENU_ENUM_LABEL_VALUE_ON,
|
||||||
|
&group_info,
|
||||||
|
&subgroup_info,
|
||||||
|
parent_group,
|
||||||
|
general_write_handler,
|
||||||
|
general_read_handler,
|
||||||
|
SD_FLAG_NONE);
|
||||||
|
|
||||||
END_SUB_GROUP(list, list_info, parent_group);
|
END_SUB_GROUP(list, list_info, parent_group);
|
||||||
END_GROUP(list, list_info, parent_group);
|
END_GROUP(list, list_info, parent_group);
|
||||||
}
|
}
|
||||||
|
@ -2325,6 +2325,7 @@ enum msg_hash_enums
|
|||||||
MENU_LABEL(VIDEO_SHADER_PRESET_REMOVE_PARENT),
|
MENU_LABEL(VIDEO_SHADER_PRESET_REMOVE_PARENT),
|
||||||
MENU_LABEL(VIDEO_SHADER_PRESET_REMOVE_GAME),
|
MENU_LABEL(VIDEO_SHADER_PRESET_REMOVE_GAME),
|
||||||
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE),
|
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE),
|
||||||
|
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_REFERENCE),
|
||||||
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_AS),
|
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_AS),
|
||||||
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_GLOBAL),
|
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_GLOBAL),
|
||||||
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_CORE),
|
MENU_LABEL(VIDEO_SHADER_PRESET_SAVE_CORE),
|
||||||
|
20
retroarch.c
20
retroarch.c
@ -8063,7 +8063,9 @@ bool menu_shader_manager_init(void)
|
|||||||
video_shader_driver_get_current_shader(&shader_info);
|
video_shader_driver_get_current_shader(&shader_info);
|
||||||
|
|
||||||
if (shader_info.data)
|
if (shader_info.data)
|
||||||
path_shader = shader_info.data->path;
|
/* Use the path of the originally loaded preset because it could
|
||||||
|
* have been a preset with a #reference in it to another preset */
|
||||||
|
path_shader = shader_info.data->loaded_preset_path;
|
||||||
else
|
else
|
||||||
path_shader = retroarch_get_shader_preset();
|
path_shader = retroarch_get_shader_preset();
|
||||||
|
|
||||||
@ -8195,9 +8197,10 @@ clear:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool menu_shader_manager_save_preset_internal(
|
static bool menu_shader_manager_save_preset_internal(
|
||||||
const struct video_shader *shader, const char *basename,
|
const struct video_shader *shader,
|
||||||
|
const char *basename,
|
||||||
const char *dir_video_shader,
|
const char *dir_video_shader,
|
||||||
bool apply, bool save_reference,
|
bool apply,
|
||||||
const char **target_dirs,
|
const char **target_dirs,
|
||||||
size_t num_target_dirs)
|
size_t num_target_dirs)
|
||||||
{
|
{
|
||||||
@ -8208,6 +8211,10 @@ static bool menu_shader_manager_save_preset_internal(
|
|||||||
char fullname[PATH_MAX_LENGTH];
|
char fullname[PATH_MAX_LENGTH];
|
||||||
char buffer[PATH_MAX_LENGTH];
|
char buffer[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
|
struct rarch_state *p_rarch = &rarch_st;
|
||||||
|
settings_t *settings = p_rarch->configuration_settings;
|
||||||
|
bool save_reference = settings->bools.video_shader_preset_save_reference_enable;
|
||||||
|
|
||||||
fullname[0] = buffer[0] = '\0';
|
fullname[0] = buffer[0] = '\0';
|
||||||
|
|
||||||
if (!shader || !shader->passes)
|
if (!shader || !shader->passes)
|
||||||
@ -8218,9 +8225,6 @@ static bool menu_shader_manager_save_preset_internal(
|
|||||||
if (type == RARCH_SHADER_NONE)
|
if (type == RARCH_SHADER_NONE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (shader->modified)
|
|
||||||
save_reference = false;
|
|
||||||
|
|
||||||
if (!string_is_empty(basename))
|
if (!string_is_empty(basename))
|
||||||
{
|
{
|
||||||
/* We are comparing against a fixed list of file
|
/* We are comparing against a fixed list of file
|
||||||
@ -8396,7 +8400,7 @@ static bool menu_shader_manager_operate_auto_preset(
|
|||||||
return menu_shader_manager_save_preset_internal(
|
return menu_shader_manager_save_preset_internal(
|
||||||
shader, file,
|
shader, file,
|
||||||
dir_video_shader,
|
dir_video_shader,
|
||||||
apply, true,
|
apply,
|
||||||
auto_preset_dirs,
|
auto_preset_dirs,
|
||||||
ARRAY_SIZE(auto_preset_dirs));
|
ARRAY_SIZE(auto_preset_dirs));
|
||||||
case AUTO_SHADER_OP_REMOVE:
|
case AUTO_SHADER_OP_REMOVE:
|
||||||
@ -8546,7 +8550,7 @@ bool menu_shader_manager_save_preset(const struct video_shader *shader,
|
|||||||
return menu_shader_manager_save_preset_internal(
|
return menu_shader_manager_save_preset_internal(
|
||||||
shader, basename,
|
shader, basename,
|
||||||
dir_video_shader,
|
dir_video_shader,
|
||||||
apply, false,
|
apply,
|
||||||
preset_dirs,
|
preset_dirs,
|
||||||
ARRAY_SIZE(preset_dirs));
|
ARRAY_SIZE(preset_dirs));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user