Merge pull request #14008 from HyperspaceMadness/Shader_Load_Extra_Param_References

Shader Load Extra Parameter Reference Files
This commit is contained in:
LibretroAdmin 2022-06-08 00:52:14 +01:00 committed by GitHub
commit 21a942665c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 254 additions and 113 deletions

View File

@ -99,6 +99,39 @@ static void fill_pathname_expanded_and_absolute(char *out_path,
pathname_conform_slashes_to_os(out_path);
}
static void gather_reference_path_list(struct path_linked_list *in_path_linked_list,
char *path,
int reference_depth)
{
config_file_t *conf = NULL;
struct path_linked_list *reference_tmp = NULL;
if (reference_depth > SHADER_MAX_REFERENCE_DEPTH)
return;
conf = config_file_new_from_path_to_string(path);
if (conf)
{
reference_tmp = (struct path_linked_list*)conf->references;
while (reference_tmp)
{
char* reference_preset_path = (char*)malloc(PATH_MAX_LENGTH);
fill_pathname_expanded_and_absolute(reference_preset_path, conf->path, reference_tmp->path);
gather_reference_path_list(in_path_linked_list, reference_preset_path, reference_depth + 1);
free(reference_preset_path);
reference_tmp = reference_tmp->next;
}
path_linked_list_add_path(in_path_linked_list, path);
}
else
{
RARCH_WARN("\n [Shaders]: No Preset located at \"%s\".\n", path);
}
config_file_free(conf);
}
/**
* wrap_mode_to_str:
* @type : Wrap type.
@ -851,6 +884,17 @@ end:
return ret;
}
/* Check if the config is a valid shader chain config */
static bool video_shader_is_shader_chain_config(config_file_t *conf)
{
/* If the config has a shaders entry then it is considered
a shader chain config, vs a config which may only have
parameter values and texture overrides
*/
return config_get_entry(conf, "shaders");
}
static config_file_t *video_shader_get_root_preset_config(const char *path)
{
int reference_depth = 1;
@ -863,7 +907,7 @@ static config_file_t *video_shader_get_root_preset_config(const char *path)
return NULL;
}
while (conf->reference)
while (conf->references)
{
/* If we have reached the max depth of nested references,
* stop attempting to read the next reference,
@ -882,7 +926,7 @@ static config_file_t *video_shader_get_root_preset_config(const char *path)
}
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->reference);
fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->references->path);
/* Create a new config from the referenced path */
config_file_free(conf);
@ -900,6 +944,7 @@ static config_file_t *video_shader_get_root_preset_config(const char *path)
}
free(nested_reference_path);
return conf;
}
@ -950,7 +995,7 @@ static bool video_shader_check_reference_chain_for_save(
{
int reference_depth = 1;
while (conf->reference)
while (conf->references)
{
/* 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. */
@ -963,7 +1008,7 @@ static bool video_shader_check_reference_chain_for_save(
}
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->reference);
fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->references->path);
/* 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*/
@ -1106,11 +1151,11 @@ static bool video_shader_write_referenced_preset(
* If there is a reference in the initially loaded preset,
* we should check it against the preset path we are currently
* trying to save */
if (reference_conf->reference)
if (reference_conf->references)
{
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(abs_temp_reference_path,
reference_conf->path, reference_conf->reference);
reference_conf->path, reference_conf->references->path);
pathname_conform_slashes_to_os(abs_temp_reference_path);
@ -1142,16 +1187,16 @@ static bool video_shader_write_referenced_preset(
/* 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_to_save_conformed)
if (string_is_equal(path_to_reference, path_to_save_conformed)
|| !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)
if (reference_conf->references)
{
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(path_to_reference,
reference_conf->path, reference_conf->reference);
reference_conf->path, reference_conf->references->path);
/* If the reference path is also the same as what
* we are trying to save
@ -1168,11 +1213,11 @@ static bool video_shader_write_referenced_preset(
path_to_reference);
/* If the reference also has a reference inside it */
if (reference_conf->reference)
if (reference_conf->references)
{
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(path_to_reference,
reference_conf->path, reference_conf->reference);
reference_conf->path, reference_conf->references->path);
}
/* If the config referenced is a full preset */
else
@ -1232,7 +1277,7 @@ static bool video_shader_write_referenced_preset(
pathname_make_slashes_portable(relative_temp_reference_path);
/* Add the reference path to the config */
config_file_set_reference_path(conf, path_to_reference);
config_file_add_reference(conf, path_to_reference);
/* Set modified to true so when you run config_file_write
* it will save a file */
@ -1715,6 +1760,7 @@ bool video_shader_write_preset(const char *path,
}
/**
* video_shader_load_preset_into_shader:
* @path : Path to preset file, could be a
@ -1731,117 +1777,124 @@ bool video_shader_load_preset_into_shader(const char *path,
{
unsigned i = 0;
bool ret = true;
char override_conf_paths[SHADER_MAX_REFERENCE_DEPTH][PATH_MAX_LENGTH];
config_file_t *conf = NULL;
/* Get the root config, If we were able to get a root_config
* that means the reference chain is valid */
config_file_t *root_conf =
video_shader_get_root_preset_config(path);
config_file_t *root_conf = video_shader_get_root_preset_config(path);
struct path_linked_list* override_paths_list = NULL;
struct path_linked_list* path_list_tmp = NULL;
if (!root_conf)
{
#ifdef DEBUG
RARCH_LOG("\n");
RARCH_WARN("[Shaders]: Could not read root preset: \"%s\".\n", path);
#endif
ret = false;
goto end;
}
/* If we were able to get a root_config that means that the
* whole reference chain is valid */
#ifdef DEBUG
RARCH_DBG("\n");
#endif
video_shader_load_root_config_into_shader(root_conf,
config_get_ptr(), shader);
/* 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))
/* Check if the root preset is a valid shader chain */
if (!video_shader_is_shader_chain_config(root_conf))
{
RARCH_LOG("\n");
RARCH_WARN("[Shaders]: Root preset is not a valid shader chain because it has no shaders entry: \"%s\".\n", path);
ret = false;
goto end;
}
/* 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))
{
/* Load the config from the shader chain from the first reference into the shader */
video_shader_load_root_config_into_shader(root_conf, config_get_ptr(), shader);
goto end;
}
/* 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);
/* 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';
i = 0;
#ifdef DEBUG
RARCH_DBG("\n");
RARCH_DBG("[Shaders]: Crawl preset reference chain..\n");
RARCH_DBG("\n[Shaders]: Crawl preset reference chain..\n");
#endif
/* 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)
/**
* Check references starting with the second to make sure
* they do not have a shader chains in them
**/
path_list_tmp = (struct path_linked_list*)conf->references->next;
while (path_list_tmp)
{
char* reference_preset_path = (char*)malloc(PATH_MAX_LENGTH);
i++;
config_file_t *tmp_conf = NULL;
char *path_to_reference = (char*)malloc(PATH_MAX_LENGTH);
#ifdef DEBUG
RARCH_DBG("[Shaders]: Preset (depth %u): \"%s\".\n", i, conf->path);
#endif
fill_pathname_expanded_and_absolute(path_to_reference, conf->path, path_list_tmp->path);
/* Add the reference to the list */
strlcpy(override_conf_paths[i], conf->path, PATH_MAX_LENGTH);
/* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(reference_preset_path,
conf->path, conf->reference);
#ifdef DEBUG
RARCH_DBG("[Shaders]: #reference = \"%s\".\n",
reference_preset_path);
#endif
/* Create a new config from this reference level */
config_file_free(conf);
conf = config_file_new_from_path_to_string(reference_preset_path);
free(reference_preset_path);
tmp_conf = video_shader_get_root_preset_config(path_to_reference);
if (tmp_conf)
{
if (video_shader_is_shader_chain_config(tmp_conf))
{
RARCH_WARN("\n[Shaders]: Additional #reference entries pointing at shader chain presets are not supported: \"%s\".\n", path_to_reference);
config_file_free(tmp_conf);
ret = false;
goto end;
}
else
{
config_file_free(tmp_conf);
}
}
else
{
RARCH_WARN("\n[Shaders]: Could not load root preset for #reference entry: \"%s\".\n", path_to_reference);
ret = false;
goto end;
}
path_list_tmp = path_list_tmp->next;
}
/* Step back through the references starting with the one
* referencing the root config and apply overrides for each one */
/* Load the config from the shader chain from the first reference into the shader */
video_shader_load_root_config_into_shader(root_conf, config_get_ptr(), shader);
/* 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));
#ifdef DEBUG
RARCH_DBG("\n");
RARCH_DBG("[Shaders]: Start applying simple preset overrides..\n");
RARCH_DBG("\n[Shaders]: Start applying simple preset overrides..\n");
#endif
while (i)
/* Gather all the paths of all of the presets in all reference chains */
override_paths_list = path_linked_list_new();
gather_reference_path_list(override_paths_list, conf->path, 0);
/*
* Step through the references and apply overrides for each one
* Start on the second item since the first is empty
*/
path_list_tmp = (struct path_linked_list*)override_paths_list;
while (path_list_tmp)
{
config_file_t *override_conf = config_file_new_from_path_to_string(
override_conf_paths[i]);
config_file_t *override_conf = NULL;
override_conf = config_file_new_from_path_to_string(path_list_tmp->path);
#ifdef DEBUG
RARCH_DBG("[Shaders]: Depth %u apply overrides..\n", i);
RARCH_DBG("[Shaders]: Apply values from: \"%s\".\n",
override_conf->path);
RARCH_DBG("[Shaders]: Apply values from: \"%s\".\n", override_conf->path);
#endif
override_shader_values(override_conf, shader);
config_file_free(override_conf);
i--;
path_list_tmp = path_list_tmp->next;
}
#ifdef DEBUG
RARCH_DBG("[Shaders]: End apply overrides.\n");
RARCH_DBG("\n");
RARCH_DBG("[Shaders]: End apply overrides.\n\n");
#endif
/* 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));
end:
path_linked_list_free(override_paths_list);
config_file_free(conf);
config_file_free(root_conf);

View File

@ -408,6 +408,20 @@ static void config_file_add_sub_conf(config_file_t *conf, char *path,
conf->path);
}
void config_file_add_reference(config_file_t *conf, char *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->references)
conf->references = path_linked_list_new();
fill_pathname_abbreviated_or_relative(short_path, conf->path, path, sizeof(short_path));
path_linked_list_add_path(conf->references, short_path);
}
static int config_file_load_internal(
struct config_file *conf,
const char *path, unsigned depth, config_file_cb_t *cb)
@ -581,7 +595,7 @@ static bool config_file_parse_line(config_file_t *conf,
if (!path)
return false;
config_file_set_reference_path(conf, path);
config_file_add_reference(conf, path);
if (!path)
return false;
@ -702,32 +716,13 @@ static int config_file_from_string_internal(
return 0;
}
void config_file_set_reference_path(config_file_t *conf, char *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;
if (conf->reference)
{
free(conf->reference);
conf->reference = NULL;
}
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)
{
struct config_include_list *inc_tmp = NULL;
struct config_entry_list *tmp = NULL;
struct path_linked_list *ref_tmp = NULL;
if (!conf)
return false;
@ -762,8 +757,7 @@ bool config_file_deinitialize(config_file_t *conf)
free(hold);
}
if (conf->reference)
free(conf->reference);
path_linked_list_free(conf->references);
if (conf->path)
free(conf->path);
@ -905,7 +899,7 @@ void config_file_initialize(struct config_file *conf)
conf->entries = NULL;
conf->tail = NULL;
conf->last = NULL;
conf->reference = NULL;
conf->references = NULL;
conf->includes = NULL;
conf->include_depth = 0;
conf->guaranteed_no_duplicates = false;
@ -1363,11 +1357,13 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
{
struct config_entry_list *list = NULL;
struct config_include_list *includes = conf->includes;
struct path_linked_list *ref_tmp = conf->references;
if (conf->reference)
while (ref_tmp)
{
pathname_make_slashes_portable(conf->reference);
fprintf(file, "#reference \"%s\"\n", conf->reference);
pathname_make_slashes_portable(ref_tmp->path);
fprintf(file, "#reference \"%s\"\n", ref_tmp->path);
ref_tmp = ref_tmp->next;
}
if (sort)

View File

@ -70,6 +70,76 @@
#endif
/**
* Create a new linked list with one node in it
* The path on this node will be set to NULL
**/
struct path_linked_list* path_linked_list_new()
{
struct path_linked_list* paths_list = (struct path_linked_list*)malloc(sizeof(*paths_list));
paths_list->next = NULL;
paths_list->path = NULL;
return paths_list;
}
/* Free the entire linked list */
bool path_linked_list_free(struct path_linked_list *in_path_linked_list)
{
struct path_linked_list *node_tmp = NULL;
node_tmp = (struct path_linked_list*)in_path_linked_list;
while (node_tmp)
{
struct path_linked_list *hold = NULL;
if (node_tmp->path)
free(node_tmp->path);
hold = (struct path_linked_list*)node_tmp;
node_tmp = node_tmp->next;
if (hold)
free(hold);
}
return true;
}
/**
* Add a node to the linked list with this path
* If the first node's path if it's not yet set the path
* on this node instead
**/
void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path)
{
/* If the first item does not have a path this is
a list which has just been created, so we just fill
the path for the first item
*/
if (!in_path_linked_list->path)
{
in_path_linked_list->path = strdup(path);
}
else
{
struct path_linked_list *head = in_path_linked_list;
struct path_linked_list *node = (struct path_linked_list*) malloc(sizeof(*node));
if (node)
{
node->next = NULL;
node->path = strdup(path);
if (head)
{
while (head->next)
head = head->next;
head->next = node;
}
else
in_path_linked_list = node;
}
}
}
/**
* path_get_archive_delim:
* @path : path

View File

@ -54,12 +54,12 @@ RETRO_BEGIN_DECLS
struct config_file
{
char *path;
char *reference;
struct config_entry_list **entries_map;
struct config_entry_list *entries;
struct config_entry_list *tail;
struct config_entry_list *last;
struct config_include_list *includes;
struct path_linked_list *references;
unsigned include_depth;
bool guaranteed_no_duplicates;
bool modified;
@ -109,7 +109,7 @@ config_file_t *config_file_new_from_path_to_string(const char *path);
/* Frees config file. */
void config_file_free(config_file_t *conf);
void config_file_set_reference_path(config_file_t *conf, char *path);
void config_file_add_reference(config_file_t *conf, char *path);
bool config_file_deinitialize(config_file_t *conf);

View File

@ -51,6 +51,28 @@ enum
RARCH_FILE_UNSUPPORTED
};
struct path_linked_list
{
char *path;
struct path_linked_list *next;
};
/**
* Create a new linked list with one item in it
* The path on this item will be set to NULL
**/
struct path_linked_list* path_linked_list_new();
/* Free the entire linked list */
bool path_linked_list_free(struct path_linked_list *in_path_linked_list);
/**
* Add a node to the linked list with this path
* If the first node's path if it's not yet set,
* set this instead
**/
void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path);
/**
* path_is_compressed_file:
* @path : path