Merge pull request #9336 from LazyBumHorse/preset_reference

save unmodified auto-shaders as a reference instead of a copy
This commit is contained in:
Twinaphex 2019-08-23 03:38:04 +02:00 committed by GitHub
commit f7cda5f753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 589 additions and 237 deletions

View File

@ -1138,7 +1138,7 @@ typedef struct MTLALIGN(16)
[self _freeVideoShader:_shader];
_shader = nil;
config_file_t *conf = config_file_new_from_path_to_string(path.UTF8String);
config_file_t *conf = video_shader_read_preset(path.UTF8String);
struct video_shader *shader = (struct video_shader *)calloc(1, sizeof(*shader));
@try

View File

@ -360,7 +360,7 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const
return false;
}
if (!(conf = config_file_new_from_path_to_string(path)))
if (!(conf = video_shader_read_preset(path)))
return false;
d3d10->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d10->shader_preset));

View File

@ -378,7 +378,7 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
return false;
}
if (!(conf = config_file_new_from_path_to_string(path)))
if (!(conf = video_shader_read_preset(path)))
return false;
d3d11->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d11->shader_preset));

View File

@ -359,7 +359,7 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
return false;
}
if (!(conf = config_file_new_from_path_to_string(path)))
if (!(conf = video_shader_read_preset(path)))
return false;
d3d12->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d12->shader_preset));

View File

@ -329,7 +329,7 @@ static bool d3d9_init_multipass(d3d9_video_t *d3d, const char *shader_path)
unsigned i;
bool use_extra_pass = false;
struct video_shader_pass *pass = NULL;
config_file_t *conf = config_file_new_from_path_to_string(shader_path);
config_file_t *conf = video_shader_read_preset(shader_path);
if (!conf)
{

View File

@ -1425,7 +1425,7 @@ static bool wiiu_gfx_set_shader(void *data,
return false;
}
if (!(conf = config_file_new_from_path_to_string(path)))
if (!(conf = video_shader_read_preset(path)))
return false;
wiiu->shader_preset = calloc(1, sizeof(*wiiu->shader_preset));

View File

@ -678,7 +678,7 @@ static bool gl_cg_load_preset(void *data, const char *path)
return false;
RARCH_LOG("[CG]: Loading Cg meta-shader: %s\n", path);
conf = config_file_new_from_path_to_string(path);
conf = video_shader_read_preset(path);
if (!conf)
{
RARCH_ERR("Failed to load preset.\n");

View File

@ -2406,7 +2406,7 @@ gl_core_filter_chain_t *gl_core_filter_chain_create_from_preset(
if (!shader)
return nullptr;
unique_ptr<config_file_t, gl_core::ConfigDeleter> conf{ config_file_new_from_path_to_string(path) };
unique_ptr<config_file_t, gl_core::ConfigDeleter> conf{ video_shader_read_preset(path) };
if (!conf)
return nullptr;

View File

@ -900,7 +900,7 @@ static void *gl_glsl_init(void *data, const char *path)
if (is_preset)
{
conf = config_file_new_from_path_to_string(path);
conf = video_shader_read_preset(path);
if (conf)
{
ret = video_shader_read_conf_preset(conf, glsl->shader);

View File

@ -2887,7 +2887,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
if (!shader)
return nullptr;
unique_ptr<config_file_t, ConfigDeleter> conf{ config_file_new_from_path_to_string(path) };
unique_ptr<config_file_t, ConfigDeleter> conf{ video_shader_read_preset(path) };
if (!conf)
return nullptr;

View File

@ -571,6 +571,234 @@ bool video_shader_resolve_parameters(config_file_t *conf,
return video_shader_resolve_current_parameters(conf, shader);
}
/**
* video_shader_write_preset:
* @path : File to write to
* @shader : Shader preset to write
* @reference : Whether a reference preset should be written
*
* Writes a preset to disk. Can be written as a reference preset.
* See: video_shader_read_preset
**/
bool video_shader_write_preset(const char *path,
const struct video_shader *shader, bool reference)
{
/* 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 */
char clean_path[PATH_MAX_LENGTH];
char clean_shader_path[PATH_MAX_LENGTH];
char preset_dir[PATH_MAX_LENGTH];
if (!shader || string_is_empty(path))
return false;
fill_pathname_join(
preset_dir,
config_get_ptr()->paths.directory_video_shader,
"presets",
sizeof(preset_dir));
strlcpy(clean_shader_path, shader->path, PATH_MAX_LENGTH);
path_resolve_realpath(clean_shader_path, PATH_MAX_LENGTH, 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)
{
/* write a reference preset */
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, PATH_MAX_LENGTH);
path_resolve_realpath(clean_path, PATH_MAX_LENGTH, false);
path_relative_to(preset_ref, clean_shader_path, clean_path, PATH_MAX_LENGTH);
len += strlen(preset_ref);
buf[len++] = '\"';
return filestream_write_file(clean_path, (void *)buf, len);
}
else
{
/* regular saving function */
config_file_t *conf;
bool ret;
if (!(conf = config_file_new_alloc()))
return false;
video_shader_write_conf_preset(conf, shader, path);
ret = config_file_write(conf, path, false);
config_file_free(conf);
return ret;
}
}
/**
* video_shader_read_reference_path:
* @path : File to read
*
* Returns: the reference path of a preset if it exists,
* otherwise returns NULL.
*
* The returned string needs to be freed.
*/
char *video_shader_read_reference_path(const char *path)
{
/* We want shader presets that point to other presets.
*
* While config_file_new_from_path_to_string() does support the
* #include directive, it will not rebase relative paths on
* the include path.
*
* There's a plethora of reasons why a general solution is hard:
* - it's impossible to distinguish a generic string from a (relative) path
* - config_file_new_from_path_to_string() doesn't return the include path,
* so we cannot rebase afterwards
* - #include is recursive, so we'd actually need to track the include path
* for every setting
*
* So instead, we use a custom #reference directive, which is just a
* 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;
config_file_t *conf = NULL;
RFILE *file = NULL;
char *line = NULL;
if (string_is_empty(path))
goto end;
if (!path_is_valid(path))
goto end;
file = filestream_open(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!file)
goto end;
line = filestream_getline(file);
filestream_close(file);
if (line && !strncmp("#reference", line, STRLEN_CONST("#reference")))
{
char *ref_path = line + STRLEN_CONST("#reference");
/* have at least 1 whitespace */
if (!isspace(*ref_path))
goto end;
ref_path++;
while (isspace(*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 */
p--;
while (isspace(*p))
*p-- = '\0';
}
}
else
{
/* remove whitespace at the end (e.g. carriage return) */
char *end = ref_path + strlen(ref_path) - 1;
while (isspace(*end))
*end-- = '\0';
}
if (string_is_empty(ref_path))
goto end;
reference = (char *)malloc(PATH_MAX_LENGTH);
if (!reference)
goto end;
/* rebase relative reference path */
if (!path_is_absolute(ref_path))
{
fill_pathname_resolve_relative(reference,
path, ref_path, PATH_MAX_LENGTH);
}
else
strlcpy(reference, ref_path, PATH_MAX_LENGTH);
}
end:
if (line)
free(line);
return reference;
}
/**
* video_shader_read_preset:
* @path : File to read
*
* Reads a preset from disk.
* If the preset is a reference preset, the referenced preset
* is loaded instead.
*
* Returns the read preset as a config object.
*
* The returned config object needs to be freed.
**/
config_file_t *video_shader_read_preset(const char *path)
{
config_file_t *conf;
char *reference = video_shader_read_reference_path(path);
if (reference)
{
conf = config_file_new_from_path_to_string(reference);
free(reference);
}
else
conf = config_file_new_from_path_to_string(path);
return conf;
}
/**
* video_shader_read_conf_preset:
* @conf : Preset file to read from.
@ -745,7 +973,7 @@ static void make_relative_path_portable(char *path)
* relative to it.
**/
void video_shader_write_conf_preset(config_file_t *conf,
struct video_shader *shader, const char *preset_path)
const struct video_shader *shader, const char *preset_path)
{
unsigned i;
char key[64];

View File

@ -159,6 +159,43 @@ struct video_shader
struct video_shader_parameter parameters[GFX_MAX_PARAMETERS];
};
/**
* video_shader_write_preset:
* @path : File to write to
* @shader : Shader preset to write
* @reference : Whether a reference preset should be written
*
* Writes a preset to disk. Can be written as a reference preset.
* See: video_shader_read_preset
**/
bool video_shader_write_preset(const char *path,
const struct video_shader *shader, bool reference);
/**
* video_shader_read_reference_path:
* @path : File to read
*
* Returns: the reference path of a preset if it exists,
* otherwise returns NULL.
*
* The returned string needs to be freed.
*/
char *video_shader_read_reference_path(const char *path);
/**
* video_shader_read_preset:
* @path : File to read
*
* Reads a preset from disk.
* If the preset is a reference preset, the referenced preset
* is loaded instead.
*
* Returns: the read preset as a config object.
*
* The returned config object needs to be freed.
**/
config_file_t *video_shader_read_preset(const char *path);
/**
* video_shader_read_conf_preset:
* @conf : Preset file to read from.
@ -183,7 +220,7 @@ bool video_shader_read_conf_preset(config_file_t *conf,
* relative to it.
**/
void video_shader_write_conf_preset(config_file_t *conf,
struct video_shader *shader, const char *preset_path);
const struct video_shader *shader, const char *preset_path);
/**
* video_shader_resolve_parameters:

View File

@ -84,6 +84,8 @@ static int shader_action_parameter_left(unsigned type, const char *label, bool w
param_menu->current = param_prev->current;
menu_shader_set_modified(true);
return ret;
}
#endif
@ -292,6 +294,9 @@ static int action_left_shader_scale_pass(unsigned type, const char *label,
shader_pass->fbo.valid = current_scale;
shader_pass->fbo.scale_x = current_scale;
shader_pass->fbo.scale_y = current_scale;
menu_shader_set_modified(true);
return 0;
}
@ -307,6 +312,9 @@ static int action_left_shader_filter_pass(unsigned type, const char *label,
return menu_cbs_exit();
shader_pass->filter = ((shader_pass->filter + delta) % 3);
menu_shader_set_modified(true);
return 0;
}
@ -355,6 +363,8 @@ static int action_left_shader_num_passes(unsigned type, const char *label,
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
video_shader_resolve_parameters(NULL, shader);
menu_shader_set_modified(true);
return 0;
}

View File

@ -1610,6 +1610,8 @@ static int generic_action_ok(const char *path,
action_path,
sizeof(shader_pass->source.path));
video_shader_resolve_parameters(NULL, shader);
menu_shader_set_modified(true);
}
}
#endif
@ -2591,7 +2593,7 @@ static void menu_input_st_string_cb_enable_settings(void *userdata,
static void menu_input_st_string_cb_save_preset(void *userdata,
const char *str)
{
if (str && *str)
if (!string_is_empty(str))
{
rarch_setting_t *setting = NULL;
bool ret = false;
@ -2607,7 +2609,7 @@ static void menu_input_st_string_cb_save_preset(void *userdata,
}
else if (!string_is_empty(label))
ret = menu_shader_manager_save_preset(menu_shader_get(),
str, false, false);
str, true);
if (ret)
runloop_msg_queue_push(
@ -2703,73 +2705,26 @@ static int generic_action_ok_shader_preset_save(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx,
unsigned action_type)
{
char directory[PATH_MAX_LENGTH];
char file[PATH_MAX_LENGTH];
char tmp[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
struct retro_system_info *system = runloop_get_libretro_system_info();
const char *core_name = system ? system->library_name : NULL;
directory[0] = file[0] = tmp[0] = '\0';
if (action_type != ACTION_OK_SHADER_PRESET_SAVE_GLOBAL)
{
if (!string_is_empty(core_name))
{
fill_pathname_join(
tmp,
settings->paths.directory_video_shader,
"presets",
sizeof(tmp));
fill_pathname_join(
directory,
tmp,
core_name,
sizeof(directory));
}
if (!path_is_directory(directory))
path_mkdir(directory);
}
else
{
fill_pathname_join(
directory,
settings->paths.directory_video_shader,
"presets",
sizeof(directory));
if (!path_is_directory(directory))
path_mkdir(directory);
fill_pathname_join(
file,
directory,
"global",
sizeof(file));
}
enum auto_shader_type preset_type;
switch (action_type)
{
case ACTION_OK_SHADER_PRESET_SAVE_GLOBAL:
preset_type = SHADER_PRESET_GLOBAL;
break;
case ACTION_OK_SHADER_PRESET_SAVE_CORE:
if (!string_is_empty(core_name))
fill_pathname_join(file, directory, core_name, sizeof(file));
break;
case ACTION_OK_SHADER_PRESET_SAVE_GAME:
{
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
fill_pathname_join(file, directory, game_name, sizeof(file));
}
preset_type = SHADER_PRESET_CORE;
break;
case ACTION_OK_SHADER_PRESET_SAVE_PARENT:
fill_pathname_parent_dir_name(tmp, path_get(RARCH_PATH_BASENAME), sizeof(tmp));
fill_pathname_join(file, directory, tmp, sizeof(file));
preset_type = SHADER_PRESET_PARENT;
break;
case ACTION_OK_SHADER_PRESET_SAVE_GAME:
preset_type = SHADER_PRESET_GAME;
break;
default:
return 0;
}
if (menu_shader_manager_save_preset(menu_shader_get(), file, false, true))
if (menu_shader_manager_save_auto_preset(menu_shader_get(), preset_type, true))
runloop_msg_queue_push(
msg_hash_to_str(MSG_SHADER_PRESET_SAVED_SUCCESSFULLY),
1, 100, true,

View File

@ -84,6 +84,8 @@ int shader_action_parameter_right(unsigned type, const char *label, bool wraparo
param_menu->current = param_prev->current;
menu_shader_set_modified(true);
return ret;
}
#endif
@ -315,6 +317,9 @@ static int action_right_shader_scale_pass(unsigned type, const char *label,
shader_pass->fbo.valid = current_scale;
shader_pass->fbo.scale_x = shader_pass->fbo.scale_y = current_scale;
menu_shader_set_modified(true);
return 0;
}
@ -330,6 +335,9 @@ static int action_right_shader_filter_pass(unsigned type, const char *label,
return menu_cbs_exit();
shader_pass->filter = ((shader_pass->filter + delta) % 3);
menu_shader_set_modified(true);
return 0;
}
@ -377,6 +385,8 @@ static int action_right_shader_num_passes(unsigned type, const char *label,
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
video_shader_resolve_parameters(NULL, shader);
menu_shader_set_modified(true);
return 0;
}
#endif

View File

@ -5909,6 +5909,7 @@ void general_write_handler(rarch_setting_t *setting)
struct video_shader *shader = menu_shader_get();
shader->passes = 0;
menu_shader_set_modified(true);
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);

View File

@ -37,6 +37,13 @@
/* Menu shader */
static struct video_shader *menu_driver_shader = NULL;
/* indicative of whether shader was modified from the menus: */
static bool menu_driver_shader_modified = true;
void menu_shader_set_modified(bool modified)
{
menu_driver_shader_modified = modified;
}
struct video_shader *menu_shader_get(void)
{
@ -62,7 +69,6 @@ bool menu_shader_manager_init(void)
enum rarch_shader_type type = RARCH_SHADER_NONE;
bool ret = true;
bool is_preset = false;
config_file_t *conf = NULL;
const char *path_shader = NULL;
struct video_shader *menu_shader = NULL;
@ -104,8 +110,22 @@ bool menu_shader_manager_init(void)
if (is_preset)
{
if (path_is_valid(path_shader))
conf = config_file_new_from_path_to_string(path_shader);
config_file_t *conf = NULL;
conf = video_shader_read_preset(path_shader);
if (!conf)
{
ret = false;
goto end;
}
if (video_shader_read_conf_preset(conf, menu_shader))
video_shader_resolve_parameters(conf, menu_shader);
menu_driver_shader_modified = false;
config_file_free(conf);
}
else
{
@ -114,12 +134,6 @@ bool menu_shader_manager_init(void)
menu_shader->passes = 1;
}
if (conf && video_shader_read_conf_preset(conf, menu_shader))
video_shader_resolve_parameters(conf, menu_shader);
if (conf)
config_file_free(conf);
end:
menu_driver_shader = menu_shader;
command_event(CMD_EVENT_SHADER_PRESET_LOADED, NULL);
@ -173,7 +187,7 @@ bool menu_shader_manager_set_preset(struct video_shader *shader,
* Used when a preset is directly loaded.
* No point in updating when the Preset was
* created from the menu itself. */
if (!(conf = config_file_new_from_path_to_string(preset_path)))
if (!(conf = video_shader_read_preset(preset_path)))
{
ret = false;
goto end;
@ -197,31 +211,20 @@ end:
return ret;
}
/**
* menu_shader_manager_save_preset:
* @basename : basename of preset
* @apply : immediately set preset after saving
*
* Save a shader preset to disk.
**/
bool menu_shader_manager_save_preset(
struct video_shader *shader,
const char *basename, bool apply, bool fullpath)
static bool menu_shader_manager_save_preset_internal(
const struct video_shader *shader, const char *basename,
bool apply, bool save_reference)
{
bool ret = false;
enum rarch_shader_type type = RARCH_SHADER_NONE;
char *preset_path = NULL;
size_t i = 0;
char fullname[PATH_MAX_LENGTH];
char buffer[PATH_MAX_LENGTH];
char preset_path[PATH_MAX_LENGTH];
char config_directory[PATH_MAX_LENGTH];
bool ret = false;
unsigned d;
enum rarch_shader_type type = RARCH_SHADER_NONE;
const char *dirs[3] = {0};
config_file_t *conf = NULL;
config_directory[0] = '\0';
buffer[0] = '\0';
preset_path[0] = '\0';
fullname[0] = buffer[0] = '\0';
if (!shader)
if (!shader || !shader->passes)
return false;
type = menu_shader_manager_get_type(shader);
@ -229,33 +232,47 @@ bool menu_shader_manager_save_preset(
if (type == RARCH_SHADER_NONE)
return false;
if (basename)
if (menu_driver_shader_modified)
save_reference = false;
if (!string_is_empty(basename))
{
strlcpy(buffer, basename, sizeof(buffer));
strlcpy(fullname, basename, sizeof(fullname));
/* Append extension automatically as appropriate. */
if ( !strstr(basename,
file_path_str(FILE_PATH_CGP_EXTENSION))
&& !strstr(basename,
file_path_str(FILE_PATH_GLSLP_EXTENSION))
&& !strstr(basename,
file_path_str(FILE_PATH_SLANGP_EXTENSION)))
if ( !strstr(basename, file_path_str(FILE_PATH_CGP_EXTENSION))
&& !strstr(basename, file_path_str(FILE_PATH_GLSLP_EXTENSION))
&& !strstr(basename, file_path_str(FILE_PATH_SLANGP_EXTENSION)))
{
const char *preset_ext = video_shader_get_preset_extension(type);
if (!string_is_empty(preset_ext))
strlcat(buffer, preset_ext, sizeof(buffer));
strlcat(fullname, preset_ext, sizeof(fullname));
}
}
else
{
const char *preset_ext = video_shader_get_preset_extension(type);
strlcpy(buffer, "retroarch", sizeof(buffer));
strlcat(buffer, preset_ext, sizeof(buffer));
strlcpy(fullname, "retroarch", sizeof(fullname));
strlcat(fullname, preset_ext, sizeof(fullname));
}
if (!fullpath)
if (path_is_absolute(fullname))
{
preset_path = fullname;
ret = video_shader_write_preset(preset_path, shader, save_reference);
if (ret)
RARCH_LOG("Saved shader preset to %s.\n", preset_path);
else
RARCH_ERR("Failed writing shader preset to %s.\n", preset_path);
}
else
{
const char *dirs[3] = {0};
settings_t *settings = config_get_ptr();
char config_directory[PATH_MAX_LENGTH];
config_directory[0] = '\0';
if (!path_is_empty(RARCH_PATH_CONFIG))
fill_pathname_basedir(
@ -263,63 +280,137 @@ bool menu_shader_manager_save_preset(
path_get(RARCH_PATH_CONFIG),
sizeof(config_directory));
dirs[0] = settings->paths.directory_video_shader;
dirs[1] = settings->paths.directory_menu_config;
dirs[2] = config_directory;
}
dirs[0] = settings->paths.directory_video_shader;
dirs[1] = settings->paths.directory_menu_config;
dirs[2] = config_directory;
if (!(conf = config_file_new_alloc()))
return false;
if (fullpath)
{
if (!string_is_empty(basename))
strlcpy(preset_path, buffer, sizeof(preset_path));
video_shader_write_conf_preset(conf, shader, preset_path);
if (config_file_write(conf, preset_path, false))
for (i = 0; i < ARRAY_SIZE(dirs); i++)
{
RARCH_LOG("Saved shader preset to %s.\n", preset_path);
if (apply)
menu_shader_manager_set_preset(NULL, type, preset_path, true);
ret = true;
}
else
RARCH_LOG("Failed writing shader preset to %s.\n", preset_path);
}
else
{
for (d = 0; d < ARRAY_SIZE(dirs); d++)
{
if (!*dirs[d])
if (string_is_empty(dirs[i]))
continue;
fill_pathname_join(preset_path, dirs[d],
buffer, sizeof(preset_path));
fill_pathname_join(buffer, dirs[i],
fullname, sizeof(buffer));
video_shader_write_conf_preset(conf, shader, preset_path);
preset_path = buffer;
if (config_file_write(conf, preset_path, false))
ret = video_shader_write_preset(preset_path, shader, save_reference);
if (ret)
{
RARCH_LOG("Saved shader preset to %s.\n", preset_path);
if (apply)
menu_shader_manager_set_preset(NULL, type, preset_path, true);
ret = true;
break;
}
else
RARCH_LOG("Failed writing shader preset to %s.\n", preset_path);
RARCH_WARN("Failed writing shader preset to %s.\n", preset_path);
}
if (!ret)
RARCH_ERR("Failed to write shader preset. Make sure shader directory"
" and/or config directory are writable.\n");
}
config_file_free(conf);
if (ret)
return true;
if (ret && apply)
menu_shader_manager_set_preset(NULL, type, preset_path, true);
RARCH_ERR("Failed to save shader preset. Make sure config directory"
" and/or shader dir are writable.\n");
return false;
return ret;
}
/**
* menu_shader_manager_save_auto_preset:
* @shader : shader to save
* @type : type of shader preset which determines save path
* @apply : immediately set preset after saving
*
* Save a shader as an auto-shader to it's appropriate path:
* SHADER_PRESET_GLOBAL: <shader dir>/presets/global
* SHADER_PRESET_CORE: <shader dir>/presets/<core name>/<core name>
* SHADER_PRESET_PARENT: <shader dir>/presets/<core name>/<parent>
* SHADER_PRESET_GAME: <shader dir>/presets/<core name>/<game name>
* Needs to be consistent with retroarch_load_shader_preset()
* Auto-shaders will be saved as a reference if possible
**/
bool menu_shader_manager_save_auto_preset(const struct video_shader *shader,
enum auto_shader_type type, bool apply)
{
char tmp[PATH_MAX_LENGTH];
char directory[PATH_MAX_LENGTH];
char file[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
struct retro_system_info *system = runloop_get_libretro_system_info();
const char *core_name = system ? system->library_name : NULL;
tmp[0] = directory[0] = file[0] = '\0';
if (type == SHADER_PRESET_GLOBAL)
{
fill_pathname_join(
directory,
settings->paths.directory_video_shader,
"presets",
sizeof(directory));
}
else if (string_is_empty(core_name))
{
return false;
}
else
{
fill_pathname_join(
tmp,
settings->paths.directory_video_shader,
"presets",
sizeof(tmp));
fill_pathname_join(
directory,
tmp,
core_name,
sizeof(directory));
}
switch (type)
{
case SHADER_PRESET_GLOBAL:
fill_pathname_join(file, directory, "global", sizeof(file));
break;
case SHADER_PRESET_CORE:
fill_pathname_join(file, directory, core_name, sizeof(file));
break;
case SHADER_PRESET_PARENT:
{
fill_pathname_parent_dir_name(tmp, path_get(RARCH_PATH_BASENAME), sizeof(tmp));
fill_pathname_join(file, directory, tmp, sizeof(file));
break;
}
case SHADER_PRESET_GAME:
{
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
fill_pathname_join(file, directory, game_name, sizeof(file));
break;
}
default:
return false;
}
if (!path_is_directory(directory))
path_mkdir(directory);
return menu_shader_manager_save_preset_internal(shader, file, apply, true);
}
/**
* menu_shader_manager_save_preset:
* @shader : shader to save
* @type : type of shader preset which determines save path
* @basename : basename of preset
* @apply : immediately set preset after saving
*
* Save a shader preset to disk.
**/
bool menu_shader_manager_save_preset(const struct video_shader *shader,
const char *basename, bool apply)
{
return menu_shader_manager_save_preset_internal(shader, basename, apply, false);
}
int menu_shader_manager_clear_num_passes(struct video_shader *shader)
@ -337,6 +428,8 @@ int menu_shader_manager_clear_num_passes(struct video_shader *shader)
video_shader_resolve_parameters(NULL, shader);
menu_driver_shader_modified = true;
return 0;
}
@ -353,6 +446,8 @@ int menu_shader_manager_clear_parameter(struct video_shader *shader,
param->current = MIN(MAX(param->minimum,
param->current), param->maximum);
menu_driver_shader_modified = true;
return 0;
}
@ -367,6 +462,8 @@ int menu_shader_manager_clear_pass_filter(struct video_shader *shader,
shader_pass->filter = RARCH_FILTER_UNSPEC;
menu_driver_shader_modified = true;
return 0;
}
@ -382,6 +479,8 @@ void menu_shader_manager_clear_pass_scale(struct video_shader *shader,
shader_pass->fbo.scale_x = 0;
shader_pass->fbo.scale_y = 0;
shader_pass->fbo.valid = false;
menu_driver_shader_modified = true;
}
void menu_shader_manager_clear_pass_path(struct video_shader *shader,
@ -392,6 +491,8 @@ void menu_shader_manager_clear_pass_path(struct video_shader *shader,
if (shader_pass)
*shader_pass->source.path = '\0';
menu_driver_shader_modified = true;
}
/**
@ -460,7 +561,7 @@ void menu_shader_manager_apply_changes(struct video_shader *shader)
if (shader->passes && type != RARCH_SHADER_NONE)
{
menu_shader_manager_save_preset(shader, NULL, true, false);
menu_shader_manager_save_preset(shader, NULL, true);
return;
}

View File

@ -24,6 +24,14 @@
RETRO_BEGIN_DECLS
enum auto_shader_type
{
SHADER_PRESET_GLOBAL,
SHADER_PRESET_CORE,
SHADER_PRESET_PARENT,
SHADER_PRESET_GAME
};
struct video_shader *menu_shader_get(void);
void menu_shader_manager_free(void);
@ -48,16 +56,33 @@ bool menu_shader_manager_set_preset(
struct video_shader *shader,
enum rarch_shader_type type, const char *preset_path, bool apply);
/**
* menu_shader_manager_save_auto_preset:
* @shader : shader to save
* @type : type of shader preset which determines save path
* @apply : immediately set preset after saving
*
* Save a shader as an auto-shader to it's appropriate path:
* SHADER_PRESET_GLOBAL: <shader dir>/presets/global
* SHADER_PRESET_CORE: <shader dir>/presets/<core name>/<core name>
* SHADER_PRESET_PARENT: <shader dir>/presets/<core name>/<parent>
* SHADER_PRESET_GAME: <shader dir>/presets/<core name>/<game name>
* Needs to be consistent with retroarch_load_shader_preset()
* Auto-shaders will be saved as a reference if possible
**/
bool menu_shader_manager_save_auto_preset(const struct video_shader *shader,
enum auto_shader_type type, bool apply);
/**
* menu_shader_manager_save_preset:
* @shader : shader to save
* @basename : basename of preset
* @apply : immediately set preset after saving
*
* Save a shader preset to disk.
**/
bool menu_shader_manager_save_preset(
struct video_shader *shader,
const char *basename, bool apply, bool fullpath);
bool menu_shader_manager_save_preset(const struct video_shader *shader,
const char *basename, bool apply);
/**
* menu_shader_manager_get_type:
@ -91,6 +116,8 @@ void menu_shader_manager_clear_pass_scale(struct video_shader *shader,
void menu_shader_manager_clear_pass_path(struct video_shader *shader,
unsigned i);
void menu_shader_set_modified(bool modified);
RETRO_END_DECLS
#endif

View File

@ -2222,11 +2222,14 @@ bool retroarch_apply_shader(enum rarch_shader_type type, const char *preset_path
retroarch_set_runtime_shader_preset(preset_path);
/* reflect in shader manager */
menu_shader_manager_set_preset(menu_shader_get(), type, preset_path, false);
if (menu_shader_manager_set_preset(menu_shader_get(), type, preset_path, false))
if (!string_is_empty(preset_path))
menu_shader_set_modified(false);
/* Display message */
snprintf(msg, sizeof(msg),
"Shader: \"%s\"", preset_file ? preset_file : "(null)");
preset_file ? "Shader: \"%s\"" : "Shader: %s",
preset_file ? preset_file : "None");
#ifdef HAVE_MENU_WIDGETS
if (menu_widgets_inited)
menu_widgets_set_message(msg);
@ -2236,7 +2239,7 @@ bool retroarch_apply_shader(enum rarch_shader_type type, const char *preset_path
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
RARCH_LOG("%s \"%s\".\n",
msg_hash_to_str(MSG_APPLYING_SHADER),
preset_path);
preset_path ? preset_path : "null");
}
else
{
@ -2248,7 +2251,7 @@ bool retroarch_apply_shader(enum rarch_shader_type type, const char *preset_path
/* Display error message */
snprintf(msg, sizeof(msg), "%s %s",
msg_hash_to_str(MSG_FAILED_TO_APPLY_SHADER_PRESET),
preset_file ? preset_file : "(null)");
preset_file ? preset_file : "null");
runloop_msg_queue_push(
msg, 1, 180, true, NULL,

View File

@ -51,10 +51,10 @@ extern "C" {
enum
{
SHADER_PRESET_SAVE_CORE = 0,
SHADER_PRESET_SAVE_GAME,
SHADER_PRESET_SAVE_GLOBAL = 0,
SHADER_PRESET_SAVE_CORE,
SHADER_PRESET_SAVE_PARENT,
SHADER_PRESET_SAVE_GLOBAL,
SHADER_PRESET_SAVE_GAME,
SHADER_PRESET_SAVE_NORMAL
};
@ -263,6 +263,8 @@ void ShaderParamsDialog::onFilterComboBoxIndexChanged(int)
if (video_shader)
video_shader->pass[pass].filter = filter;
menu_shader_set_modified(true);
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
}
}
@ -317,6 +319,8 @@ void ShaderParamsDialog::onScaleComboBoxIndexChanged(int)
video_shader->pass[pass].fbo.valid = scale;
}
menu_shader_set_modified(true);
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
}
}
@ -393,6 +397,8 @@ void ShaderParamsDialog::onShaderPassMoveDownClicked()
memcpy(&menu_shader->pass[pass + 1], tempPass.pass, sizeof(struct video_shader_pass));
}
menu_shader_set_modified(true);
reload();
}
@ -466,6 +472,8 @@ void ShaderParamsDialog::onShaderPassMoveUpClicked()
memcpy(&menu_shader->pass[pass], tempPass.pass, sizeof(struct video_shader_pass));
}
menu_shader_set_modified(true);
reload();
}
@ -550,6 +558,8 @@ void ShaderParamsDialog::onShaderResetPass(int pass)
}
}
menu_shader_set_modified(true);
reload();
}
@ -594,6 +604,8 @@ void ShaderParamsDialog::onShaderResetParameter(QString parameter)
param->current = param->initial;
}
menu_shader_set_modified(true);
reload();
}
@ -647,6 +659,8 @@ void ShaderParamsDialog::onShaderAddPassClicked()
else
return;
menu_shader_set_modified(true);
shader_pass = &menu_shader->pass[menu_shader->passes - 1];
if (!shader_pass)
@ -679,76 +693,35 @@ void ShaderParamsDialog::onShaderSavePresetAsClicked()
void ShaderParamsDialog::saveShaderPreset(const char *path, unsigned action_type)
{
char directory[PATH_MAX_LENGTH];
char file[PATH_MAX_LENGTH];
char tmp[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
struct retro_system_info *system = runloop_get_libretro_system_info();
const char *core_name = system ? system->library_name : NULL;
directory[0] = file[0] = tmp[0] = '\0';
if (action_type != SHADER_PRESET_SAVE_GLOBAL)
{
if (!string_is_empty(core_name))
{
fill_pathname_join(
tmp,
settings->paths.directory_video_shader,
"presets",
sizeof(tmp));
fill_pathname_join(
directory,
tmp,
core_name,
sizeof(directory));
}
if (!path_is_directory(directory))
path_mkdir(directory);
}
else
{
fill_pathname_join(
directory,
settings->paths.directory_video_shader,
"presets",
sizeof(directory));
if (!path_is_directory(directory))
path_mkdir(directory);
fill_pathname_join(
file,
directory,
"global",
sizeof(file));
}
bool ret;
enum auto_shader_type preset_type;
switch (action_type)
{
case SHADER_PRESET_SAVE_GLOBAL:
preset_type = SHADER_PRESET_GLOBAL;
break;
case SHADER_PRESET_SAVE_CORE:
if (!string_is_empty(core_name))
fill_pathname_join(file, directory, core_name, sizeof(file));
preset_type = SHADER_PRESET_PARENT;
break;
case SHADER_PRESET_SAVE_PARENT:
preset_type = SHADER_PRESET_PARENT;
break;
case SHADER_PRESET_SAVE_GAME:
{
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
fill_pathname_join(file, directory, game_name, sizeof(file));
break;
}
case SHADER_PRESET_SAVE_PARENT:
fill_pathname_parent_dir_name(tmp, path_get(RARCH_PATH_BASENAME), sizeof(tmp));
fill_pathname_join(file, directory, tmp, sizeof(file));
preset_type = SHADER_PRESET_GAME;
break;
case SHADER_PRESET_SAVE_NORMAL:
default:
if (!string_is_empty(path))
strlcpy(file, path, sizeof(file));
break;
default:
return;
}
if (menu_shader_manager_save_preset(menu_shader_get(), file, false, true))
if (action_type == SHADER_PRESET_SAVE_NORMAL)
ret = menu_shader_manager_save_preset(menu_shader_get(), path, true);
else
ret = menu_shader_manager_save_auto_preset(menu_shader_get(), preset_type, true);
if (ret)
runloop_msg_queue_push(
msg_hash_to_str(MSG_SHADER_PRESET_SAVED_SUCCESSFULLY),
1, 100, true, NULL,
@ -766,22 +739,22 @@ void ShaderParamsDialog::saveShaderPreset(const char *path, unsigned action_type
void ShaderParamsDialog::onShaderSaveGlobalPresetClicked()
{
saveShaderPreset(NULL, SHADER_PRESET_SAVE_GLOBAL);
saveShaderPreset(NULL, SHADER_PRESET_GLOBAL);
}
void ShaderParamsDialog::onShaderSaveCorePresetClicked()
{
saveShaderPreset(NULL, SHADER_PRESET_SAVE_CORE);
saveShaderPreset(NULL, SHADER_PRESET_CORE);
}
void ShaderParamsDialog::onShaderSaveParentPresetClicked()
{
saveShaderPreset(NULL, SHADER_PRESET_SAVE_PARENT);
saveShaderPreset(NULL, SHADER_PRESET_PARENT);
}
void ShaderParamsDialog::onShaderSaveGamePresetClicked()
{
saveShaderPreset(NULL, SHADER_PRESET_SAVE_GAME);
saveShaderPreset(NULL, SHADER_PRESET_GAME);
}
void ShaderParamsDialog::onShaderClearAllPassesClicked()
@ -794,8 +767,9 @@ void ShaderParamsDialog::onShaderClearAllPassesClicked()
if (!menu_shader)
return;
while (menu_shader->passes > 0)
menu_shader->passes--;
menu_shader->passes = 0;
menu_shader_set_modified(true);
onShaderApplyClicked();
}
@ -834,6 +808,8 @@ void ShaderParamsDialog::onShaderRemovePassClicked()
menu_shader->passes--;
menu_shader_set_modified(true);
onShaderApplyClicked();
}
@ -1230,10 +1206,6 @@ void ShaderParamsDialog::addShaderParam(struct video_shader_parameter *param, QF
slider->setValue(value);
slider->setProperty("param", parameter);
struct video_shader *video_shader = NULL;
getShaders(NULL, &video_shader);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int)));
box->addWidget(slider);
@ -1323,6 +1295,8 @@ void ShaderParamsDialog::onShaderParamCheckBoxClicked()
if (param)
param->current = (checkBox->isChecked() ? param->maximum : param->minimum);
}
menu_shader_set_modified(true);
}
}
@ -1386,6 +1360,8 @@ void ShaderParamsDialog::onShaderParamSliderValueChanged(int)
param->current = newValue;
}
}
menu_shader_set_modified(true);
}
if (spinBoxVariant.isValid())
@ -1490,6 +1466,8 @@ void ShaderParamsDialog::onShaderParamSpinBoxValueChanged(int value)
slider->blockSignals(false);
}
}
menu_shader_set_modified(true);
}
}
@ -1570,5 +1548,7 @@ void ShaderParamsDialog::onShaderParamDoubleSpinBoxValueChanged(double value)
slider->blockSignals(false);
}
}
menu_shader_set_modified(true);
}
}