Shader Loading of Multiple References for settings

Multi reference settings working

Config fixes

Multi-Reference Loading Working, Checking for shader chain not working

Checking References is working

Improved path_linked_list_add_path

Simplify path list stuff

Fixed Static Definition

Fixes

Fixes

Fix to Trigger PR Update

Removed Legacy Orbis which got left in a merge

Memory Leak Fix
This commit is contained in:
Remi McGill 2022-05-24 14:07:55 -04:00
parent 49370f1f26
commit 684889507b
5 changed files with 263 additions and 157 deletions

View File

@ -99,6 +99,39 @@ static void fill_pathname_expanded_and_absolute(char *out_path,
pathname_conform_slashes_to_os(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: * wrap_mode_to_str:
* @type : Wrap type. * @type : Wrap type.
@ -851,6 +884,17 @@ end:
return ret; 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) static config_file_t *video_shader_get_root_preset_config(const char *path)
{ {
int reference_depth = 1; int reference_depth = 1;
@ -863,7 +907,7 @@ static config_file_t *video_shader_get_root_preset_config(const char *path)
return NULL; return NULL;
} }
while (conf->reference) while (conf->references)
{ {
/* If we have reached the max depth of nested references, /* If we have reached the max depth of nested references,
* stop attempting to read the next reference, * 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 */ /* 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 */ /* Create a new config from the referenced path */
config_file_free(conf); 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); free(nested_reference_path);
return conf; return conf;
} }
@ -950,7 +995,7 @@ static bool video_shader_check_reference_chain_for_save(
{ {
int reference_depth = 1; int reference_depth = 1;
while (conf->reference) while (conf->references)
{ {
/* If we have reached the max depth of nested references stop attempting to read /* 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. */ * 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 */ /* 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 /* 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*/ * 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, * If there is a reference in the initially loaded preset,
* we should check it against the preset path we are currently * we should check it against the preset path we are currently
* trying to save */ * trying to save */
if (reference_conf->reference) if (reference_conf->references)
{ {
/* Get the absolute path for the reference */ /* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(abs_temp_reference_path, 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); pathname_conform_slashes_to_os(abs_temp_reference_path);
@ -1147,11 +1192,11 @@ static bool video_shader_write_referenced_preset(
{ {
/* If the config from the reference path has a reference in it, /* If the config from the reference path has a reference in it,
* we will use this same nested reference for the new preset */ * 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 */ /* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(path_to_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 /* If the reference path is also the same as what
* we are trying to save * we are trying to save
@ -1168,11 +1213,11 @@ static bool video_shader_write_referenced_preset(
path_to_reference); path_to_reference);
/* If the reference also has a reference inside it */ /* If the reference also has a reference inside it */
if (reference_conf->reference) if (reference_conf->references)
{ {
/* Get the absolute path for the reference */ /* Get the absolute path for the reference */
fill_pathname_expanded_and_absolute(path_to_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 */ /* If the config referenced is a full preset */
else else
@ -1232,7 +1277,7 @@ static bool video_shader_write_referenced_preset(
pathname_make_slashes_portable(relative_temp_reference_path); pathname_make_slashes_portable(relative_temp_reference_path);
/* Add the reference path to the config */ /* 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 /* Set modified to true so when you run config_file_write
* it will save a file */ * it will save a file */
@ -1715,6 +1760,7 @@ bool video_shader_write_preset(const char *path,
} }
/** /**
* video_shader_load_preset_into_shader: * video_shader_load_preset_into_shader:
* @path : Path to preset file, could be a * @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; unsigned i = 0;
bool ret = true; bool ret = true;
char override_conf_paths[SHADER_MAX_REFERENCE_DEPTH][PATH_MAX_LENGTH];
config_file_t *conf = NULL; config_file_t *conf = NULL;
/* Get the root config, If we were able to get a root_config config_file_t *root_conf = video_shader_get_root_preset_config(path);
* that means the reference chain is valid */ struct path_linked_list* override_paths_list = NULL;
config_file_t *root_conf = struct path_linked_list* path_list_tmp = NULL;
video_shader_get_root_preset_config(path);
if (!root_conf) if (!root_conf)
{ {
#ifdef DEBUG
RARCH_LOG("\n"); RARCH_LOG("\n");
RARCH_WARN("[Shaders]: Could not read root preset: \"%s\".\n", path); RARCH_WARN("[Shaders]: Could not read root preset: \"%s\".\n", path);
#endif
ret = false; ret = false;
goto end; goto end;
} }
/* If we were able to get a root_config that means that the /* Check if the root preset is a valid shader chain */
* whole reference chain is valid */ if (!video_shader_is_shader_chain_config(root_conf))
#ifdef DEBUG {
RARCH_DBG("\n"); RARCH_LOG("\n");
#endif RARCH_WARN("[Shaders]: Root preset is not a valid shader chain because it has no shaders entry: \"%s\".\n", path);
ret = false;
goto end;
}
video_shader_load_root_config_into_shader(root_conf,
config_get_ptr(), shader);
/* If the root_conf path matches the original path then /* If the root_conf path matches the original path then
* there are no references so we just load it and go to the end */ * there are no references so we just load it and go to the end */
if (string_is_equal(root_conf->path, path)) 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; goto end;
}
/* Get the config from the initial preset file /* Get the config from the initial preset file
* We don't need to check it's validity because it must * We don't need to check it's validity because it must
* have been valid to get the root preset */ * have been valid to get the root preset */
conf = config_file_new_from_path_to_string(path); 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 #ifdef DEBUG
RARCH_DBG("\n"); RARCH_DBG("\n[Shaders]: Crawl preset reference chain..\n");
RARCH_DBG("[Shaders]: Crawl preset reference chain..\n");
#endif #endif
/* If the config has a reference then we need gather all presets from the /**
* chain of references to apply their values later */ * Check references starting with the second to make sure
while (conf->reference) * 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); config_file_t *tmp_conf = NULL;
i++; char *path_to_reference = (char*)malloc(PATH_MAX_LENGTH);
#ifdef DEBUG fill_pathname_expanded_and_absolute(path_to_reference, conf->path, path_list_tmp->path);
RARCH_DBG("[Shaders]: Preset (depth %u): \"%s\".\n", i, conf->path);
#endif
/* Add the reference to the list */ tmp_conf = video_shader_get_root_preset_config(path_to_reference);
strlcpy(override_conf_paths[i], conf->path, PATH_MAX_LENGTH); if (tmp_conf)
{
/* Get the absolute path for the reference */ if (video_shader_is_shader_chain_config(tmp_conf))
fill_pathname_expanded_and_absolute(reference_preset_path, {
conf->path, conf->reference); 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);
#ifdef DEBUG ret = false;
RARCH_DBG("[Shaders]: #reference = \"%s\".\n", goto end;
reference_preset_path); }
#endif else
{
/* Create a new config from this reference level */ config_file_free(tmp_conf);
config_file_free(conf); }
conf = config_file_new_from_path_to_string(reference_preset_path); }
else
free(reference_preset_path); {
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 /* Load the config from the shader chain from the first reference into the shader */
* referencing the root config and apply overrides for each one */ 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 #ifdef DEBUG
RARCH_DBG("\n"); RARCH_DBG("\n[Shaders]: Start applying simple preset overrides..\n");
RARCH_DBG("[Shaders]: Start applying simple preset overrides..\n");
#endif #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( config_file_t *override_conf = NULL;
override_conf_paths[i]);
override_conf = config_file_new_from_path_to_string(path_list_tmp->path);
#ifdef DEBUG #ifdef DEBUG
RARCH_DBG("[Shaders]: Depth %u apply overrides..\n", i); RARCH_DBG("[Shaders]: Depth %u apply overrides..\n", i);
RARCH_DBG("[Shaders]: Apply values from: \"%s\".\n", RARCH_DBG("[Shaders]: Apply values from: \"%s\".\n", override_conf->path);
override_conf->path);
#endif #endif
override_shader_values(override_conf, shader);
override_shader_values(override_conf, shader);
config_file_free(override_conf); config_file_free(override_conf);
i--; path_list_tmp = path_list_tmp->next;
} }
#ifdef DEBUG #ifdef DEBUG
RARCH_DBG("[Shaders]: End apply overrides.\n"); RARCH_DBG("[Shaders]: End apply overrides.\n\n");
RARCH_DBG("\n");
#endif #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: end:
path_linked_list_free(override_paths_list);
config_file_free(conf); config_file_free(conf);
config_file_free(root_conf); config_file_free(root_conf);

View File

@ -39,12 +39,6 @@
#define MAX_INCLUDE_DEPTH 16 #define MAX_INCLUDE_DEPTH 16
struct config_include_list
{
char *path;
struct config_include_list *next;
};
/* Forward declaration */ /* Forward declaration */
static bool config_file_parse_line(config_file_t *conf, static bool config_file_parse_line(config_file_t *conf,
struct config_entry_list *list, char *line, config_file_cb_t *cb); struct config_entry_list *list, char *line, config_file_cb_t *cb);
@ -383,29 +377,26 @@ static void config_file_get_realpath(char *s, size_t len,
static void config_file_add_sub_conf(config_file_t *conf, char *path, static void config_file_add_sub_conf(config_file_t *conf, char *path,
char *real_path, size_t len, config_file_cb_t *cb) char *real_path, size_t len, config_file_cb_t *cb)
{ {
struct config_include_list *head = conf->includes; if (!conf->includes)
struct config_include_list *node = (struct config_include_list*) conf->includes = path_linked_list_new();
malloc(sizeof(*node));
if (node) path_linked_list_add_path(conf->includes, path);
{
node->next = NULL;
/* Add include list */
node->path = strdup(path);
if (head) config_file_get_realpath(real_path, len, path, conf->path);
{
while (head->next)
head = head->next;
head->next = node;
}
else
conf->includes = node;
} }
config_file_get_realpath(real_path, len, path, void config_file_add_reference(config_file_t *conf, char *path)
conf->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( static int config_file_load_internal(
@ -581,7 +572,7 @@ static bool config_file_parse_line(config_file_t *conf,
if (!path) if (!path)
return false; return false;
config_file_set_reference_path(conf, path); config_file_add_reference(conf, path);
if (!path) if (!path)
return false; return false;
@ -702,31 +693,11 @@ static int config_file_from_string_internal(
return 0; 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) bool config_file_deinitialize(config_file_t *conf)
{ {
struct config_include_list *inc_tmp = NULL; struct path_linked_list *inc_tmp = NULL;
struct path_linked_list *ref_tmp = NULL;
struct config_entry_list *tmp = NULL; struct config_entry_list *tmp = NULL;
if (!conf) if (!conf)
return false; return false;
@ -750,20 +721,8 @@ bool config_file_deinitialize(config_file_t *conf)
free(hold); free(hold);
} }
inc_tmp = (struct config_include_list*)conf->includes; path_linked_list_free(conf->includes);
while (inc_tmp) path_linked_list_free(conf->references);
{
struct config_include_list *hold = NULL;
if (inc_tmp->path)
free(inc_tmp->path);
hold = (struct config_include_list*)inc_tmp;
inc_tmp = inc_tmp->next;
if (hold)
free(hold);
}
if (conf->reference)
free(conf->reference);
if (conf->path) if (conf->path)
free(conf->path); free(conf->path);
@ -905,7 +864,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->references = 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;
@ -1362,12 +1321,14 @@ bool config_file_write(config_file_t *conf, const char *path, bool sort)
void config_file_dump(config_file_t *conf, FILE *file, bool sort) 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 path_linked_list *inc_tmp = conf->includes;
struct path_linked_list *ref_tmp = conf->references;
if (conf->reference) while (ref_tmp)
{ {
pathname_make_slashes_portable(conf->reference); pathname_make_slashes_portable(ref_tmp->path);
fprintf(file, "#reference \"%s\"\n", conf->reference); fprintf(file, "#reference \"%s\"\n", ref_tmp->path);
ref_tmp = ref_tmp->next;
} }
if (sort) if (sort)
@ -1392,10 +1353,10 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
* '#include' directives must go *after* individual * '#include' directives must go *after* individual
* config entries, otherwise they will override * config entries, otherwise they will override
* any custom-set values */ * any custom-set values */
while (includes) while (inc_tmp)
{ {
fprintf(file, "#include \"%s\"\n", includes->path); fprintf(file, "#include \"%s\"\n", inc_tmp->path);
includes = includes->next; inc_tmp = inc_tmp->next;
} }
} }

View File

@ -70,6 +70,76 @@
#endif #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_get_archive_delim:
* @path : path * @path : path

View File

@ -54,12 +54,12 @@ RETRO_BEGIN_DECLS
struct config_file struct config_file
{ {
char *path; char *path;
char *reference;
struct config_entry_list **entries_map; struct config_entry_list **entries_map;
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;
struct config_include_list *includes; struct path_linked_list *includes;
struct path_linked_list *references;
unsigned include_depth; unsigned include_depth;
bool guaranteed_no_duplicates; bool guaranteed_no_duplicates;
bool modified; bool modified;
@ -92,6 +92,8 @@ config_file_t *config_file_new_alloc(void);
void config_file_initialize(struct config_file *conf); void config_file_initialize(struct config_file *conf);
void config_file_add_reference(config_file_t *conf, char *path);
/* Loads a config file. Returns NULL if file doesn't exist. /* Loads a config file. Returns NULL if file doesn't exist.
* NULL path will create an empty config file. * NULL path will create an empty config file.
* Includes cb callbacks to run custom code during config file processing.*/ * Includes cb callbacks to run custom code during config file processing.*/
@ -109,8 +111,6 @@ 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.

View File

@ -51,6 +51,28 @@ enum
RARCH_FILE_UNSUPPORTED 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_is_compressed_file:
* @path : path * @path : path