video_shader_parse.c - reduce stack usage

This commit is contained in:
twinaphex 2017-09-09 22:54:55 +02:00
parent 9aa16ddfcc
commit ba77d862a3

View File

@ -119,8 +119,6 @@ static enum gfx_wrap_type wrap_str_to_mode(const char *wrap_mode)
static bool video_shader_parse_pass(config_file_t *conf, static bool video_shader_parse_pass(config_file_t *conf,
struct video_shader_pass *pass, unsigned i) struct video_shader_pass *pass, unsigned i)
{ {
char tmp_str[PATH_MAX_LENGTH];
char tmp_path[PATH_MAX_LENGTH];
char shader_name[64]; char shader_name[64];
char filter_name_buf[64]; char filter_name_buf[64];
char wrap_name_buf[64]; char wrap_name_buf[64];
@ -136,6 +134,9 @@ static bool video_shader_parse_pass(config_file_t *conf,
char scale_type_x[64]; char scale_type_x[64];
char scale_type_y[64]; char scale_type_y[64];
char frame_count_mod[64]; char frame_count_mod[64];
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
char *tmp_str = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
char *tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
struct gfx_fbo_scale *scale = NULL; struct gfx_fbo_scale *scale = NULL;
bool tmp_bool = false; bool tmp_bool = false;
float fattr = 0.0f; float fattr = 0.0f;
@ -150,14 +151,14 @@ static bool video_shader_parse_pass(config_file_t *conf,
/* Source */ /* Source */
snprintf(shader_name, sizeof(shader_name), "shader%u", i); snprintf(shader_name, sizeof(shader_name), "shader%u", i);
if (!config_get_path(conf, shader_name, tmp_str, sizeof(tmp_str))) if (!config_get_path(conf, shader_name, tmp_str, path_size))
{ {
RARCH_ERR("Couldn't parse shader source (%s).\n", shader_name); RARCH_ERR("Couldn't parse shader source (%s).\n", shader_name);
return false; goto error;
} }
strlcpy(tmp_path, tmp_str, sizeof(tmp_path)); strlcpy(tmp_path, tmp_str, path_size);
path_resolve_realpath(tmp_path, sizeof(tmp_path)); path_resolve_realpath(tmp_path, path_size);
if (!path_file_exists(tmp_path)) if (!path_file_exists(tmp_path))
strlcpy(pass->source.path, tmp_str, sizeof(pass->source.path)); strlcpy(pass->source.path, tmp_str, sizeof(pass->source.path));
@ -246,7 +247,7 @@ static bool video_shader_parse_pass(config_file_t *conf,
break; break;
default: default:
RARCH_ERR("Invalid attribute.\n"); RARCH_ERR("Invalid attribute.\n");
return false; goto error;
} }
} }
@ -267,7 +268,7 @@ static bool video_shader_parse_pass(config_file_t *conf,
break; break;
default: default:
RARCH_ERR("Invalid attribute.\n"); RARCH_ERR("Invalid attribute.\n");
return false; goto error;
} }
} }
@ -319,7 +320,14 @@ static bool video_shader_parse_pass(config_file_t *conf,
} }
} }
free(tmp_str);
free(tmp_path);
return true; return true;
error:
free(tmp_str);
free(tmp_path);
return false;
} }
/** /**
@ -334,15 +342,20 @@ static bool video_shader_parse_pass(config_file_t *conf,
static bool video_shader_parse_textures(config_file_t *conf, static bool video_shader_parse_textures(config_file_t *conf,
struct video_shader *shader) struct video_shader *shader)
{ {
char textures[1024]; size_t path_size = PATH_MAX_LENGTH * sizeof(char);
const char *id = NULL; const char *id = NULL;
char *save = NULL; char *save = NULL;
char tmp_path[PATH_MAX_LENGTH]; char *textures = (char*)malloc(1024 * sizeof(char));
char *tmp_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
textures[0] = '\0'; textures[0] = '\0';
if (!config_get_array(conf, "textures", textures, sizeof(textures))) if (!config_get_array(conf, "textures", textures, 1024 * sizeof(char)))
{
free(textures);
free(tmp_path);
return true; return true;
}
for (id = strtok_r(textures, ";", &save); for (id = strtok_r(textures, ";", &save);
id && shader->luts < GFX_MAX_TEXTURES; id && shader->luts < GFX_MAX_TEXTURES;
@ -361,11 +374,12 @@ static bool video_shader_parse_textures(config_file_t *conf,
sizeof(shader->lut[shader->luts].path))) sizeof(shader->lut[shader->luts].path)))
{ {
RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id); RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id);
return false; goto error;
} }
strlcpy(tmp_path, shader->lut[shader->luts].path, sizeof(tmp_path)); strlcpy(tmp_path, shader->lut[shader->luts].path,
path_resolve_realpath(tmp_path, sizeof(tmp_path)); path_size);
path_resolve_realpath(tmp_path, path_size);
if (path_file_exists(tmp_path)) if (path_file_exists(tmp_path))
{ {
@ -394,7 +408,14 @@ static bool video_shader_parse_textures(config_file_t *conf,
shader->lut[shader->luts].mipmap = false; shader->lut[shader->luts].mipmap = false;
} }
free(textures);
free(tmp_path);
return true; return true;
error:
free(textures);
free(tmp_path);
return false;
} }
/** /**
@ -434,25 +455,34 @@ static struct video_shader_parameter *video_shader_parse_find_parameter(
bool video_shader_resolve_current_parameters(config_file_t *conf, bool video_shader_resolve_current_parameters(config_file_t *conf,
struct video_shader *shader) struct video_shader *shader)
{ {
char parameters[4096]; size_t param_size = 4096 * sizeof(char);
char *parameters = (char*)malloc(4096 * sizeof(char));
const char *id = NULL; const char *id = NULL;
char *save = NULL; char *save = NULL;
if (!conf) if (!conf)
{
free(parameters);
return false; return false;
}
parameters[0] = '\0'; parameters[0] = '\0';
/* Read in parameters which override the defaults. */ /* Read in parameters which override the defaults. */
if (!config_get_array(conf, "parameters", if (!config_get_array(conf, "parameters",
parameters, sizeof(parameters))) parameters, param_size))
{
free(parameters);
return true; return true;
}
for (id = strtok_r(parameters, ";", &save); id; for (id = strtok_r(parameters, ";", &save); id;
id = strtok_r(NULL, ";", &save)) id = strtok_r(NULL, ";", &save))
{ {
struct video_shader_parameter *parameter = (struct video_shader_parameter*) struct video_shader_parameter *parameter =
video_shader_parse_find_parameter(shader->parameters, shader->num_parameters, id); (struct video_shader_parameter*)
video_shader_parse_find_parameter(
shader->parameters, shader->num_parameters, id);
if (!parameter) if (!parameter)
{ {
@ -463,6 +493,8 @@ bool video_shader_resolve_current_parameters(config_file_t *conf,
if (!config_get_float(conf, id, &parameter->current)) if (!config_get_float(conf, id, &parameter->current))
RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id); RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id);
} }
free(parameters);
return true; return true;
} }
@ -487,28 +519,36 @@ bool video_shader_resolve_parameters(config_file_t *conf,
for (i = 0; i < shader->passes; i++) for (i = 0; i < shader->passes; i++)
{ {
char line[4096];
RFILE *file = NULL; RFILE *file = NULL;
size_t line_size = 4096 * sizeof(char);
char *line = (char*)malloc(4096 * sizeof(char));
const char *path = shader->pass[i].source.path; const char *path = shader->pass[i].source.path;
#ifdef HAVE_SLANG #ifdef HAVE_SLANG
/* First try to use the more robust slang implementation to support #includes. */ /* First try to use the more robust slang implementation to support #includes. */
/* FIXME: The check for slang can be removed if it's sufficiently tested for /* FIXME: The check for slang can be removed if it's sufficiently tested for
* GLSL/Cg as well, it should be the same implementation. */ * GLSL/Cg as well, it should be the same implementation. */
if (!string_is_empty(path) && (string_is_equal_fast(path_get_extension(path), "slang", 5)) && if (!string_is_empty(path) && (string_is_equal_fast(path_get_extension(path), "slang", 5)) &&
slang_preprocess_parse_parameters(shader->pass[i].source.path, shader)) slang_preprocess_parse_parameters(shader->pass[i].source.path, shader))
{
free(line);
continue; continue;
}
/* If that doesn't work, fallback to the old path. /* If that doesn't work, fallback to the old path.
* Ideally, we'd get rid of this path sooner or later. */ * Ideally, we'd get rid of this path sooner or later. */
#endif #endif
file = filestream_open(path, RFILE_MODE_READ_TEXT, -1); file = filestream_open(path, RFILE_MODE_READ_TEXT, -1);
if (!file) if (!file)
{
free(line);
continue; continue;
}
line[0] = '\0'; line[0] = '\0';
while (shader->num_parameters < ARRAY_SIZE(shader->parameters) while (shader->num_parameters < ARRAY_SIZE(shader->parameters)
&& filestream_gets(file, line, sizeof(line))) && filestream_gets(file, line, line_size))
{ {
int ret = sscanf(line, int ret = sscanf(line,
"#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f",
@ -533,6 +573,7 @@ bool video_shader_resolve_parameters(config_file_t *conf,
param++; param++;
} }
free(line);
filestream_close(file); filestream_close(file);
} }
@ -554,15 +595,21 @@ bool video_shader_resolve_parameters(config_file_t *conf,
static bool video_shader_parse_imports(config_file_t *conf, static bool video_shader_parse_imports(config_file_t *conf,
struct video_shader *shader) struct video_shader *shader)
{ {
char imports[1024]; size_t path_size = PATH_MAX_LENGTH * sizeof(char);
char tmp_str[PATH_MAX_LENGTH]; char *imports = (char*)malloc(1024 * sizeof(char));
char *tmp_str = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
const char *id = NULL; const char *id = NULL;
char *save = NULL; char *save = NULL;
imports[0] = tmp_str[0] = '\0'; imports[0] = tmp_str[0] = '\0';
if (!config_get_array(conf, "imports", imports, sizeof(imports))) if (!config_get_array(conf, "imports", imports,
1024 * sizeof(char)))
{
free(imports);
free(tmp_str);
return true; return true;
}
for (id = strtok_r(imports, ";", &save); for (id = strtok_r(imports, ";", &save);
id && shader->variables < GFX_MAX_VARIABLES; id && shader->variables < GFX_MAX_VARIABLES;
@ -595,7 +642,7 @@ static bool video_shader_parse_imports(config_file_t *conf,
if (!config_get_array(conf, semantic_buf, semantic, sizeof(semantic))) if (!config_get_array(conf, semantic_buf, semantic, sizeof(semantic)))
{ {
RARCH_ERR("No semantic for import variable.\n"); RARCH_ERR("No semantic for import variable.\n");
return false; goto error;
} }
semantic_hash = djb2_calculate(semantic); semantic_hash = djb2_calculate(semantic);
@ -622,7 +669,7 @@ static bool video_shader_parse_imports(config_file_t *conf,
break; break;
default: default:
RARCH_ERR("Invalid semantic.\n"); RARCH_ERR("Invalid semantic.\n");
return false; goto error;
} }
@ -644,7 +691,7 @@ static bool video_shader_parse_imports(config_file_t *conf,
default: default:
RARCH_ERR("Invalid input slot for import.\n"); RARCH_ERR("Invalid input slot for import.\n");
return false; goto error;
} }
} }
else if (config_get_hex(conf, wram_buf, &addr)) else if (config_get_hex(conf, wram_buf, &addr))
@ -655,7 +702,7 @@ static bool video_shader_parse_imports(config_file_t *conf,
else else
{ {
RARCH_ERR("No address assigned to semantic.\n"); RARCH_ERR("No address assigned to semantic.\n");
return false; goto error;
} }
} }
@ -665,12 +712,19 @@ static bool video_shader_parse_imports(config_file_t *conf,
var->equal = equal; var->equal = equal;
} }
if (config_get_path(conf, "import_script", tmp_str, sizeof(tmp_str))) if (config_get_path(conf, "import_script", tmp_str, path_size))
strlcpy(shader->script_path, tmp_str, sizeof(shader->script_path)); strlcpy(shader->script_path, tmp_str, sizeof(shader->script_path));
config_get_array(conf, "import_script_class", config_get_array(conf, "import_script_class",
shader->script_class, sizeof(shader->script_class)); shader->script_class, sizeof(shader->script_class));
free(imports);
free(tmp_str);
return true; return true;
error:
free(imports);
free(tmp_str);
return false;
} }
/** /**
@ -879,18 +933,21 @@ void video_shader_write_conf_cgp(config_file_t *conf,
for (i = 0; i < shader->passes; i++) for (i = 0; i < shader->passes; i++)
{ {
char key[64]; char key[64];
char tmp[PATH_MAX_LENGTH]; size_t tmp_size = PATH_MAX_LENGTH * sizeof(char);
char *tmp = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
const struct video_shader_pass *pass = &shader->pass[i]; const struct video_shader_pass *pass = &shader->pass[i];
key[0] = '\0'; key[0] = '\0';
snprintf(key, sizeof(key), "shader%u", i); snprintf(key, sizeof(key), "shader%u", i);
strlcpy(tmp, pass->source.path, sizeof(tmp)); strlcpy(tmp, pass->source.path, tmp_size);
if (!path_is_absolute(tmp)) if (!path_is_absolute(tmp))
path_resolve_realpath(tmp, sizeof(tmp)); path_resolve_realpath(tmp, tmp_size);
config_set_string(conf, key, tmp); config_set_string(conf, key, tmp);
free(tmp);
if (pass->filter != RARCH_FILTER_UNSPEC) if (pass->filter != RARCH_FILTER_UNSPEC)
{ {
snprintf(key, sizeof(key), "filter_linear%u", i); snprintf(key, sizeof(key), "filter_linear%u", i);
@ -917,17 +974,18 @@ void video_shader_write_conf_cgp(config_file_t *conf,
if (shader->num_parameters) if (shader->num_parameters)
{ {
char parameters[4096]; size_t param_size = 4096 * sizeof(char);
char *parameters = (char*)malloc(4096 * sizeof(char));
parameters[0] = '\0'; parameters[0] = '\0';
strlcpy(parameters, shader->parameters[0].id, sizeof(parameters)); strlcpy(parameters, shader->parameters[0].id, param_size);
for (i = 1; i < shader->num_parameters; i++) for (i = 1; i < shader->num_parameters; i++)
{ {
/* O(n^2), but number of parameters is very limited. */ /* O(n^2), but number of parameters is very limited. */
strlcat(parameters, ";", sizeof(parameters)); strlcat(parameters, ";", param_size);
strlcat(parameters, shader->parameters[i].id, sizeof(parameters)); strlcat(parameters, shader->parameters[i].id, param_size);
} }
config_set_string(conf, "parameters", parameters); config_set_string(conf, "parameters", parameters);
@ -935,24 +993,28 @@ void video_shader_write_conf_cgp(config_file_t *conf,
for (i = 0; i < shader->num_parameters; i++) for (i = 0; i < shader->num_parameters; i++)
config_set_float(conf, shader->parameters[i].id, config_set_float(conf, shader->parameters[i].id,
shader->parameters[i].current); shader->parameters[i].current);
free(parameters);
} }
if (shader->luts) if (shader->luts)
{ {
char textures[4096]; size_t tex_size = 4096 * sizeof(char);
char *textures = (char*)malloc(4096 * sizeof(char));
textures[0] = '\0'; textures[0] = '\0';
strlcpy(textures, shader->lut[0].id, sizeof(textures)); strlcpy(textures, shader->lut[0].id, tex_size);
for (i = 1; i < shader->luts; i++) for (i = 1; i < shader->luts; i++)
{ {
/* O(n^2), but number of textures is very limited. */ /* O(n^2), but number of textures is very limited. */
strlcat(textures, ";", sizeof(textures)); strlcat(textures, ";", tex_size);
strlcat(textures, shader->lut[i].id, sizeof(textures)); strlcat(textures, shader->lut[i].id, tex_size);
} }
config_set_string(conf, "textures", textures); config_set_string(conf, "textures", textures);
free(textures);
for (i = 0; i < shader->luts; i++) for (i = 0; i < shader->luts; i++)
{ {
char key[64]; char key[64];
@ -983,22 +1045,24 @@ void video_shader_write_conf_cgp(config_file_t *conf,
if (shader->variables) if (shader->variables)
{ {
char variables[4096]; size_t var_tmp = 4096 * sizeof(char);
char *variables = (char*)malloc(4096 * sizeof(char));
variables[0] = '\0'; variables[0] = '\0';
strlcpy(variables, shader->variable[0].id, sizeof(variables)); strlcpy(variables, shader->variable[0].id, var_tmp);
for (i = 1; i < shader->variables; i++) for (i = 1; i < shader->variables; i++)
{ {
strlcat(variables, ";", sizeof(variables)); strlcat(variables, ";", var_tmp);
strlcat(variables, shader->variable[i].id, sizeof(variables)); strlcat(variables, shader->variable[i].id, var_tmp);
} }
config_set_string(conf, "imports", variables); config_set_string(conf, "imports", variables);
for (i = 0; i < shader->variables; i++) for (i = 0; i < shader->variables; i++)
shader_write_variable(conf, &shader->variable[i]); shader_write_variable(conf, &shader->variable[i]);
free(variables);
} }
} }
@ -1050,7 +1114,8 @@ void video_shader_resolve_relative(struct video_shader *shader,
const char *ref_path) const char *ref_path)
{ {
unsigned i; unsigned i;
char tmp_path[4096]; size_t tmp_path_size = 4096 * sizeof(char);
char *tmp_path = (char*)malloc(4096 * sizeof(char));
tmp_path[0] = '\0'; tmp_path[0] = '\0';
@ -1059,23 +1124,25 @@ void video_shader_resolve_relative(struct video_shader *shader,
if (!*shader->pass[i].source.path) if (!*shader->pass[i].source.path)
continue; continue;
strlcpy(tmp_path, shader->pass[i].source.path, sizeof(tmp_path)); strlcpy(tmp_path, shader->pass[i].source.path, tmp_path_size);
fill_pathname_resolve_relative(shader->pass[i].source.path, fill_pathname_resolve_relative(shader->pass[i].source.path,
ref_path, tmp_path, sizeof(shader->pass[i].source.path)); ref_path, tmp_path, sizeof(shader->pass[i].source.path));
} }
for (i = 0; i < shader->luts; i++) for (i = 0; i < shader->luts; i++)
{ {
strlcpy(tmp_path, shader->lut[i].path, sizeof(tmp_path)); strlcpy(tmp_path, shader->lut[i].path, tmp_path_size);
fill_pathname_resolve_relative(shader->lut[i].path, fill_pathname_resolve_relative(shader->lut[i].path,
ref_path, tmp_path, sizeof(shader->lut[i].path)); ref_path, tmp_path, sizeof(shader->lut[i].path));
} }
if (*shader->script_path) if (*shader->script_path)
{ {
strlcpy(tmp_path, shader->script_path, sizeof(tmp_path)); strlcpy(tmp_path, shader->script_path, tmp_path_size);
fill_pathname_resolve_relative(shader->script_path, fill_pathname_resolve_relative(shader->script_path,
ref_path, tmp_path, sizeof(shader->script_path)); ref_path, tmp_path, sizeof(shader->script_path));
} }
free(tmp_path);
} }