mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 00:20:01 +00:00
Merge pull request #706 from libretro/shader-parameter
Shader parameter
This commit is contained in:
commit
a56d57c615
2
driver.h
2
driver.h
@ -358,6 +358,8 @@ typedef struct video_poke_interface
|
||||
|
||||
void (*show_mouse)(void *data, bool state);
|
||||
void (*grab_mouse_toggle)(void *data);
|
||||
|
||||
struct gfx_shader *(*get_current_shader)(void *data);
|
||||
} video_poke_interface_t;
|
||||
|
||||
typedef struct video_driver
|
||||
|
@ -43,6 +43,17 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SHADER_MANAGER
|
||||
static inline struct gfx_shader *shader_manager_get_current_shader(rgui_handle_t *rgui, unsigned type)
|
||||
{
|
||||
struct gfx_shader *shader = type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS ? &rgui->shader : NULL;
|
||||
if (!shader && driver.video_poke && driver.video_data && driver.video_poke->get_current_shader)
|
||||
shader = driver.video_poke->get_current_shader(driver.video_data);
|
||||
|
||||
return shader;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void menu_common_entries_init(void *data, unsigned menu_type)
|
||||
{
|
||||
rgui_handle_t *rgui = (rgui_handle_t*)data;
|
||||
@ -51,6 +62,18 @@ static void menu_common_entries_init(void *data, unsigned menu_type)
|
||||
switch (menu_type)
|
||||
{
|
||||
#ifdef HAVE_SHADER_MANAGER
|
||||
case RGUI_SETTINGS_SHADER_PARAMETERS:
|
||||
case RGUI_SETTINGS_SHADER_PRESET_PARAMETERS:
|
||||
{
|
||||
file_list_clear(rgui->selection_buf);
|
||||
|
||||
struct gfx_shader *shader = shader_manager_get_current_shader(rgui, menu_type);
|
||||
if (shader)
|
||||
for (i = 0; i < shader->num_parameters; i++)
|
||||
file_list_push(rgui->selection_buf, shader->parameters[i].desc, RGUI_SETTINGS_SHADER_PARAMETER_0 + i, 0);
|
||||
rgui->parameter_shader = shader;
|
||||
break;
|
||||
}
|
||||
case RGUI_SETTINGS_SHADER_OPTIONS:
|
||||
file_list_clear(rgui->selection_buf);
|
||||
file_list_push(rgui->selection_buf, "Apply Shader Changes",
|
||||
@ -60,6 +83,10 @@ static void menu_common_entries_init(void *data, unsigned menu_type)
|
||||
RGUI_SETTINGS_SHADER_PRESET, 0);
|
||||
file_list_push(rgui->selection_buf, "Save As Shader Preset",
|
||||
RGUI_SETTINGS_SHADER_PRESET_SAVE, 0);
|
||||
file_list_push(rgui->selection_buf, "Parameters (Current)",
|
||||
RGUI_SETTINGS_SHADER_PARAMETERS, 0);
|
||||
file_list_push(rgui->selection_buf, "Parameters (RGUI)",
|
||||
RGUI_SETTINGS_SHADER_PRESET_PARAMETERS, 0);
|
||||
file_list_push(rgui->selection_buf, "Shader Passes",
|
||||
RGUI_SETTINGS_SHADER_PASSES, 0);
|
||||
|
||||
@ -506,6 +533,8 @@ static unsigned menu_common_type_is(unsigned type)
|
||||
type == RGUI_SETTINGS_VIDEO_OPTIONS ||
|
||||
type == RGUI_SETTINGS_FONT_OPTIONS ||
|
||||
type == RGUI_SETTINGS_SHADER_OPTIONS ||
|
||||
type == RGUI_SETTINGS_SHADER_PARAMETERS ||
|
||||
type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS ||
|
||||
type == RGUI_SETTINGS_AUDIO_OPTIONS ||
|
||||
type == RGUI_SETTINGS_DISK_OPTIONS ||
|
||||
type == RGUI_SETTINGS_PATH_OPTIONS ||
|
||||
@ -673,7 +702,7 @@ static int menu_settings_iterate(void *data, unsigned action)
|
||||
file_list_get_last(rgui->menu_stack, &dir, &menu_type);
|
||||
|
||||
if (rgui->need_refresh && !(menu_type == RGUI_FILE_DIRECTORY ||
|
||||
menu_common_type_is(menu_type) == RGUI_SETTINGS_SHADER_OPTIONS||
|
||||
menu_common_type_is(menu_type) == RGUI_SETTINGS_SHADER_OPTIONS ||
|
||||
menu_common_type_is(menu_type) == RGUI_FILE_DIRECTORY ||
|
||||
menu_type == RGUI_SETTINGS_VIDEO_SOFTFILTER ||
|
||||
menu_type == RGUI_SETTINGS_AUDIO_DSP_FILTER ||
|
||||
@ -700,6 +729,8 @@ static int menu_settings_iterate(void *data, unsigned action)
|
||||
|| menu_type == RGUI_SETTINGS_VIDEO_OPTIONS
|
||||
|| menu_type == RGUI_SETTINGS_FONT_OPTIONS
|
||||
|| menu_type == RGUI_SETTINGS_SHADER_OPTIONS
|
||||
|| menu_type == RGUI_SETTINGS_SHADER_PARAMETERS
|
||||
|| menu_type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS
|
||||
)
|
||||
menu_common_entries_init(rgui, menu_type);
|
||||
else
|
||||
@ -1363,6 +1394,9 @@ static int menu_common_iterate(void *data, unsigned action)
|
||||
unsigned pass = (menu_type - RGUI_SETTINGS_SHADER_0) / 3;
|
||||
fill_pathname_join(rgui->shader.pass[pass].source.path,
|
||||
dir, path, sizeof(rgui->shader.pass[pass].source.path));
|
||||
|
||||
// This will reset any changed parameters.
|
||||
gfx_shader_resolve_parameters(NULL, &rgui->shader);
|
||||
}
|
||||
|
||||
// Pop stack until we hit shader manager again.
|
||||
@ -1673,7 +1707,10 @@ static void menu_common_shader_manager_init(void *data)
|
||||
if (conf)
|
||||
{
|
||||
if (gfx_shader_read_conf_cgp(conf, &rgui->shader))
|
||||
{
|
||||
gfx_shader_resolve_relative(&rgui->shader, g_settings.video.shader_path);
|
||||
gfx_shader_resolve_parameters(conf, &rgui->shader);
|
||||
}
|
||||
config_file_free(conf);
|
||||
}
|
||||
}
|
||||
@ -1700,7 +1737,10 @@ static void menu_common_shader_manager_init(void *data)
|
||||
if (conf)
|
||||
{
|
||||
if (gfx_shader_read_conf_cgp(conf, &rgui->shader))
|
||||
{
|
||||
gfx_shader_resolve_relative(&rgui->shader, cgp_path);
|
||||
gfx_shader_resolve_parameters(conf, &rgui->shader);
|
||||
}
|
||||
config_file_free(conf);
|
||||
}
|
||||
}
|
||||
@ -1733,6 +1773,7 @@ static void menu_common_shader_manager_set_preset(void *data, unsigned type, con
|
||||
{
|
||||
gfx_shader_read_conf_cgp(conf, shader);
|
||||
gfx_shader_resolve_relative(shader, path);
|
||||
gfx_shader_resolve_parameters(conf, shader);
|
||||
config_file_free(conf);
|
||||
}
|
||||
|
||||
@ -1758,9 +1799,20 @@ static void menu_common_shader_manager_get_str(void *data, char *type_str, size_
|
||||
struct gfx_shader *shader = (struct gfx_shader*)data;
|
||||
if (type == RGUI_SETTINGS_SHADER_APPLY)
|
||||
*type_str = '\0';
|
||||
else if (type >= RGUI_SETTINGS_SHADER_PARAMETER_0 && type <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
|
||||
{
|
||||
// rgui->parameter_shader here.
|
||||
if (shader)
|
||||
{
|
||||
const struct gfx_shader_parameter *param = &shader->parameters[type - RGUI_SETTINGS_SHADER_PARAMETER_0];
|
||||
snprintf(type_str, type_str_size, "%.2f [%.2f %.2f]", param->current, param->minimum, param->maximum);
|
||||
}
|
||||
else
|
||||
*type_str = '\0';
|
||||
}
|
||||
else if (type == RGUI_SETTINGS_SHADER_PASSES)
|
||||
snprintf(type_str, type_str_size, "%u", shader->passes);
|
||||
else
|
||||
else if (type >= RGUI_SETTINGS_SHADER_0 && type <= RGUI_SETTINGS_SHADER_LAST)
|
||||
{
|
||||
unsigned pass = (type - RGUI_SETTINGS_SHADER_0) / 3;
|
||||
switch ((type - RGUI_SETTINGS_SHADER_0) % 3)
|
||||
@ -1801,6 +1853,8 @@ static void menu_common_shader_manager_get_str(void *data, char *type_str, size_
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
*type_str = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1959,10 +2013,42 @@ static int menu_common_shader_manager_setting_toggle(void *data, unsigned settin
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((setting == RGUI_SETTINGS_SHADER_PARAMETERS || setting == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS) && action == RGUI_ACTION_OK)
|
||||
{
|
||||
file_list_push(rgui->menu_stack, "", setting, rgui->selection_ptr);
|
||||
menu_clear_navigation(rgui);
|
||||
rgui->need_refresh = true;
|
||||
}
|
||||
else if (setting >= RGUI_SETTINGS_SHADER_PARAMETER_0 && setting <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
|
||||
{
|
||||
if (!rgui->parameter_shader)
|
||||
return 0;
|
||||
|
||||
struct gfx_shader_parameter *param = &rgui->parameter_shader->parameters[setting - RGUI_SETTINGS_SHADER_PARAMETER_0];
|
||||
switch (action)
|
||||
{
|
||||
case RGUI_ACTION_START:
|
||||
param->current = param->initial;
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_LEFT:
|
||||
param->current -= param->step;
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_RIGHT:
|
||||
param->current += param->step;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
param->current = min(max(param->minimum, param->current), param->maximum);
|
||||
}
|
||||
else if ((setting == RGUI_SETTINGS_SHADER_APPLY || setting == RGUI_SETTINGS_SHADER_PASSES) &&
|
||||
(driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->setting_set))
|
||||
driver.menu_ctx->backend->setting_set(rgui, setting, action);
|
||||
else if ((dist_shader % 3) == 0 || setting == RGUI_SETTINGS_SHADER_PRESET)
|
||||
else if (((dist_shader % 3) == 0 || setting == RGUI_SETTINGS_SHADER_PRESET))
|
||||
{
|
||||
dist_shader /= 3;
|
||||
struct gfx_shader_pass *pass = setting == RGUI_SETTINGS_SHADER_PRESET ?
|
||||
@ -3603,6 +3689,7 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action
|
||||
{
|
||||
case RGUI_ACTION_START:
|
||||
rgui->shader.passes = 0;
|
||||
rgui->need_refresh = true;
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_LEFT:
|
||||
@ -3626,9 +3713,8 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef HAVE_RMENU
|
||||
rgui->need_refresh = true;
|
||||
#endif
|
||||
if (rgui->need_refresh)
|
||||
gfx_shader_resolve_parameters(NULL, &rgui->shader);
|
||||
break;
|
||||
case RGUI_SETTINGS_SHADER_APPLY:
|
||||
{
|
||||
|
@ -62,7 +62,11 @@ typedef enum
|
||||
RGUI_SETTINGS_SHADER_FILTER,
|
||||
RGUI_SETTINGS_SHADER_PRESET,
|
||||
RGUI_SETTINGS_SHADER_APPLY,
|
||||
RGUI_SETTINGS_SHADER_PARAMETERS, // Modifies current shader directly. Will not get saved to CGP.
|
||||
RGUI_SETTINGS_SHADER_PRESET_PARAMETERS, // Modifies shader preset currently in RGUI.
|
||||
RGUI_SETTINGS_SHADER_PASSES,
|
||||
RGUI_SETTINGS_SHADER_PARAMETER_0,
|
||||
RGUI_SETTINGS_SHADER_PARAMETER_LAST = RGUI_SETTINGS_SHADER_PARAMETER_0 + (GFX_MAX_PARAMETERS - 1),
|
||||
RGUI_SETTINGS_SHADER_0,
|
||||
RGUI_SETTINGS_SHADER_0_FILTER,
|
||||
RGUI_SETTINGS_SHADER_0_SCALE,
|
||||
|
@ -316,6 +316,10 @@ static void rgui_render(void *data)
|
||||
#ifdef HAVE_SHADER_MANAGER
|
||||
else if (menu_type == RGUI_SETTINGS_SHADER_OPTIONS)
|
||||
strlcpy(title, "SHADER OPTIONS", sizeof(title));
|
||||
else if (menu_type == RGUI_SETTINGS_SHADER_PARAMETERS)
|
||||
strlcpy(title, "SHADER PARAMETERS (CURRENT)", sizeof(title));
|
||||
else if (menu_type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS)
|
||||
strlcpy(title, "SHADER PARAMETERS (RGUI PRESET)", sizeof(title));
|
||||
#endif
|
||||
else if (menu_type == RGUI_SETTINGS_FONT_OPTIONS)
|
||||
strlcpy(title, "FONT OPTIONS", sizeof(title));
|
||||
@ -453,13 +457,18 @@ static void rgui_render(void *data)
|
||||
strlcpy(type_str, "(DIR)", sizeof(type_str));
|
||||
w = 5;
|
||||
}
|
||||
else if (type == RGUI_SETTINGS_SHADER_OPTIONS || type == RGUI_SETTINGS_SHADER_PRESET)
|
||||
else if (type == RGUI_SETTINGS_SHADER_OPTIONS || type == RGUI_SETTINGS_SHADER_PRESET || type == RGUI_SETTINGS_SHADER_PARAMETERS || type == RGUI_SETTINGS_SHADER_PRESET_PARAMETERS)
|
||||
strlcpy(type_str, "...", sizeof(type_str));
|
||||
else if (type == RGUI_SETTINGS_SHADER_FILTER)
|
||||
snprintf(type_str, sizeof(type_str), "%s",
|
||||
g_settings.video.smooth ? "Linear" : "Nearest");
|
||||
else if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->shader_manager_get_str)
|
||||
driver.menu_ctx->backend->shader_manager_get_str(&rgui->shader, type_str, sizeof(type_str), type);
|
||||
{
|
||||
if (type >= RGUI_SETTINGS_SHADER_PARAMETER_0 && type <= RGUI_SETTINGS_SHADER_PARAMETER_LAST)
|
||||
driver.menu_ctx->backend->shader_manager_get_str(rgui->parameter_shader, type_str, sizeof(type_str), type);
|
||||
else
|
||||
driver.menu_ctx->backend->shader_manager_get_str(&rgui->shader, type_str, sizeof(type_str), type);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -164,6 +164,7 @@ typedef struct
|
||||
|
||||
#ifdef HAVE_SHADER_MANAGER
|
||||
struct gfx_shader shader;
|
||||
struct gfx_shader *parameter_shader; // Points to either shader or graphics driver current shader.
|
||||
#endif
|
||||
unsigned current_pad;
|
||||
|
||||
|
22
gfx/gl.c
22
gfx/gl.c
@ -978,6 +978,7 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
|
||||
fbo_info->tex_size[0] = prev_rect->width;
|
||||
fbo_info->tex_size[1] = prev_rect->height;
|
||||
memcpy(fbo_info->coord, fbo_tex_coords, sizeof(fbo_tex_coords));
|
||||
fbo_tex_info_cnt++;
|
||||
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo[i]);
|
||||
|
||||
@ -1002,8 +1003,6 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
|
||||
|
||||
gl_shader_set_coords(gl, &gl->coords, &gl->mvp);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
fbo_tex_info_cnt++;
|
||||
}
|
||||
|
||||
#if defined(GL_FRAMEBUFFER_SRGB) && !defined(HAVE_OPENGLES)
|
||||
@ -1018,6 +1017,16 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
|
||||
|
||||
set_texture_coords(fbo_tex_coords, xamt, yamt);
|
||||
|
||||
// Push final FBO to list.
|
||||
fbo_info = &fbo_tex_info[gl->fbo_pass - 1];
|
||||
fbo_info->tex = gl->fbo_texture[gl->fbo_pass - 1];
|
||||
fbo_info->input_size[0] = prev_rect->img_width;
|
||||
fbo_info->input_size[1] = prev_rect->img_height;
|
||||
fbo_info->tex_size[0] = prev_rect->width;
|
||||
fbo_info->tex_size[1] = prev_rect->height;
|
||||
memcpy(fbo_info->coord, fbo_tex_coords, sizeof(fbo_tex_coords));
|
||||
fbo_tex_info_cnt++;
|
||||
|
||||
// Render our FBO texture to back buffer.
|
||||
gl_bind_backbuffer();
|
||||
if (gl->shader)
|
||||
@ -2909,6 +2918,12 @@ static void gl_show_mouse(void *data, bool state)
|
||||
gl->ctx_driver->show_mouse(gl, state);
|
||||
}
|
||||
|
||||
static struct gfx_shader *gl_get_current_shader(void *data)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
return gl->shader ? gl->shader->get_current_shader() : NULL;
|
||||
}
|
||||
|
||||
static const video_poke_interface_t gl_poke_interface = {
|
||||
NULL,
|
||||
#ifdef HAVE_FBO
|
||||
@ -2924,6 +2939,9 @@ static const video_poke_interface_t gl_poke_interface = {
|
||||
gl_set_osd_msg,
|
||||
|
||||
gl_show_mouse,
|
||||
NULL,
|
||||
|
||||
gl_get_current_shader,
|
||||
};
|
||||
|
||||
static void gl_get_poke_interface(void *data, const video_poke_interface_t **iface)
|
||||
|
@ -132,7 +132,6 @@ struct cg_program
|
||||
};
|
||||
|
||||
static struct cg_program prg[GFX_MAX_SHADERS];
|
||||
static const char **cg_arguments;
|
||||
static bool cg_active;
|
||||
static CGprofile cgVProf, cgFProf;
|
||||
static unsigned active_index;
|
||||
@ -145,6 +144,8 @@ static GLuint lut_textures[GFX_MAX_TEXTURES];
|
||||
static CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
|
||||
static unsigned cg_attrib_index;
|
||||
|
||||
static char cg_alias_define[GFX_MAX_SHADERS][128];
|
||||
|
||||
static void gl_cg_reset_attrib(void)
|
||||
{
|
||||
unsigned i;
|
||||
@ -288,7 +289,7 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
}
|
||||
|
||||
// Set FBO textures.
|
||||
if (active_index > 2)
|
||||
if (active_index)
|
||||
{
|
||||
for (i = 0; i < fbo_info_cnt; i++)
|
||||
{
|
||||
@ -313,6 +314,15 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma parameters
|
||||
for (i = 0; i < cg_shader->num_parameters; i++)
|
||||
{
|
||||
CGparameter param_v = cgGetNamedParameter(prg[active_index].vprg, cg_shader->parameters[i].id);
|
||||
CGparameter param_f = cgGetNamedParameter(prg[active_index].fprg, cg_shader->parameters[i].id);
|
||||
set_param_1f(param_v, cg_shader->parameters[i].current);
|
||||
set_param_1f(param_f, cg_shader->parameters[i].current);
|
||||
}
|
||||
|
||||
// Set state parameters
|
||||
if (state_tracker)
|
||||
{
|
||||
@ -414,18 +424,30 @@ static bool load_program(unsigned index, const char *prog, bool path_is_file)
|
||||
char *listing_f = NULL;
|
||||
char *listing_v = NULL;
|
||||
|
||||
unsigned i, argc = 1;
|
||||
const char *argv[2 + GFX_MAX_SHADERS] = {
|
||||
"-DPARAMETER_UNIFORM",
|
||||
NULL,
|
||||
};
|
||||
|
||||
for (i = 0; i < GFX_MAX_SHADERS; i++)
|
||||
{
|
||||
if (*(cg_alias_define[i]))
|
||||
argv[argc++] = cg_alias_define[i];
|
||||
}
|
||||
|
||||
if (path_is_file)
|
||||
{
|
||||
prg[index].fprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", cg_arguments);
|
||||
prg[index].fprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", argv);
|
||||
SET_LISTING(f);
|
||||
prg[index].vprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", cg_arguments);
|
||||
prg[index].vprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", argv);
|
||||
SET_LISTING(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
prg[index].fprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", cg_arguments);
|
||||
prg[index].fprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgFProf, "main_fragment", argv);
|
||||
SET_LISTING(f);
|
||||
prg[index].vprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", cg_arguments);
|
||||
prg[index].vprg = cgCreateProgram(cgCtx, CG_SOURCE, prog, cgVProf, "main_vertex", argv);
|
||||
SET_LISTING(v);
|
||||
}
|
||||
|
||||
@ -489,6 +511,7 @@ static bool load_plain(const char *path)
|
||||
prg[1] = prg[0];
|
||||
}
|
||||
|
||||
gfx_shader_resolve_parameters(NULL, cg_shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -580,14 +603,20 @@ static bool load_preset(const char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
config_file_free(conf);
|
||||
gfx_shader_resolve_relative(cg_shader, path);
|
||||
gfx_shader_resolve_parameters(conf, cg_shader);
|
||||
config_file_free(conf);
|
||||
|
||||
if (cg_shader->passes > GFX_MAX_SHADERS - 3)
|
||||
{
|
||||
RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", GFX_MAX_SHADERS - 3);
|
||||
cg_shader->passes = GFX_MAX_SHADERS - 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < cg_shader->passes; i++)
|
||||
if (*cg_shader->pass[i].alias)
|
||||
snprintf(cg_alias_define[i], sizeof(cg_alias_define[i]), "-D%s_ALIAS", cg_shader->pass[i].alias);
|
||||
|
||||
for (i = 0; i < cg_shader->passes; i++)
|
||||
{
|
||||
if (!load_shader(i))
|
||||
@ -741,13 +770,16 @@ static void set_program_attributes(unsigned i)
|
||||
prg[i].prev[j].coord = cgGetNamedParameter(prg[i].vprg, attr_buf_coord);
|
||||
}
|
||||
|
||||
for (j = 0; j < i - 1; j++)
|
||||
for (j = 0; j + 1 < i; j++)
|
||||
{
|
||||
char pass_str[64];
|
||||
snprintf(pass_str, sizeof(pass_str), "PASS%u", j + 1);
|
||||
set_pass_attrib(&prg[i], &prg[i].fbo[j], pass_str);
|
||||
snprintf(pass_str, sizeof(pass_str), "PASSPREV%u", i - (j + 1));
|
||||
set_pass_attrib(&prg[i], &prg[i].fbo[j], pass_str);
|
||||
|
||||
if (*cg_shader->pass[j].alias)
|
||||
set_pass_attrib(&prg[i], &prg[i].fbo[j], cg_shader->pass[j].alias);
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,6 +821,8 @@ static bool gl_cg_init(void *data, const char *path)
|
||||
cgGLEnableProfile(cgFProf);
|
||||
cgGLEnableProfile(cgVProf);
|
||||
|
||||
memset(cg_alias_define, 0, sizeof(cg_alias_define));
|
||||
|
||||
if (path && strcmp(path_get_extension(path), "cgp") == 0)
|
||||
{
|
||||
if (!load_preset(path))
|
||||
@ -898,9 +932,9 @@ static bool gl_cg_mipmap_input(unsigned index)
|
||||
return false;
|
||||
}
|
||||
|
||||
void gl_cg_set_compiler_args(const char **argv)
|
||||
static struct gfx_shader *gl_cg_get_current_shader(void)
|
||||
{
|
||||
cg_arguments = argv;
|
||||
return cg_active ? cg_shader : NULL;
|
||||
}
|
||||
|
||||
void gl_cg_invalidate_context(void)
|
||||
@ -921,6 +955,7 @@ const gl_shader_backend_t gl_cg_backend = {
|
||||
gl_cg_set_mvp,
|
||||
gl_cg_get_prev_textures,
|
||||
gl_cg_mipmap_input,
|
||||
gl_cg_get_current_shader,
|
||||
|
||||
RARCH_SHADER_CG,
|
||||
};
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "shader_common.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void gl_cg_set_compiler_args(const char **argv);
|
||||
void gl_cg_invalidate_context(void); // Call when resetting GL context on PS3.
|
||||
extern const gl_shader_backend_t gl_cg_backend;
|
||||
|
||||
|
@ -54,6 +54,8 @@ struct gl_shader_backend
|
||||
unsigned (*get_prev_textures)(void);
|
||||
bool (*mipmap_input)(unsigned index);
|
||||
|
||||
struct gfx_shader *(*get_current_shader)(void);
|
||||
|
||||
enum rarch_shader_type type;
|
||||
};
|
||||
|
||||
|
@ -58,6 +58,8 @@ static state_tracker_t *gl_state_tracker;
|
||||
static GLint gl_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
|
||||
static unsigned gl_attrib_index;
|
||||
|
||||
static char glsl_alias_define[1024];
|
||||
|
||||
// Cache the VBO.
|
||||
struct cache_vbo
|
||||
{
|
||||
@ -325,7 +327,7 @@ static bool compile_shader(GLuint shader, const char *define, const char *progra
|
||||
RARCH_LOG("[GL]: Using GLSL version %u.\n", version_no);
|
||||
}
|
||||
|
||||
const char *source[] = { version, define, program };
|
||||
const char *source[] = { version, define, glsl_alias_define, program };
|
||||
glShaderSource(shader, ARRAY_SIZE(source), source, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
@ -366,7 +368,7 @@ static GLuint compile_program(const char *vertex, const char *fragment, unsigned
|
||||
{
|
||||
RARCH_LOG("Found GLSL vertex shader.\n");
|
||||
vert = glCreateShader(GL_VERTEX_SHADER);
|
||||
if (!compile_shader(vert, "#define VERTEX\n", vertex))
|
||||
if (!compile_shader(vert, "#define VERTEX\n#define PARAMETER_UNIFORM\n", vertex))
|
||||
{
|
||||
RARCH_ERR("Failed to compile vertex shader #%u\n", i);
|
||||
return false;
|
||||
@ -379,7 +381,7 @@ static GLuint compile_program(const char *vertex, const char *fragment, unsigned
|
||||
{
|
||||
RARCH_LOG("Found GLSL fragment shader.\n");
|
||||
frag = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!compile_shader(frag, "#define FRAGMENT\n", fragment))
|
||||
if (!compile_shader(frag, "#define FRAGMENT\n#define PARAMETER_UNIFORM\n", fragment))
|
||||
{
|
||||
RARCH_ERR("Failed to compile fragment shader #%u\n", i);
|
||||
return false;
|
||||
@ -566,6 +568,9 @@ static void find_uniforms(unsigned pass, GLuint prog, struct shader_uniforms *un
|
||||
find_uniforms_frame(prog, &uni->pass[i], frame_base);
|
||||
snprintf(frame_base, sizeof(frame_base), "PassPrev%u", pass - (i + 1));
|
||||
find_uniforms_frame(prog, &uni->pass[i], frame_base);
|
||||
|
||||
if (*glsl_shader->pass[i].alias)
|
||||
find_uniforms_frame(prog, &uni->pass[i], glsl_shader->pass[i].alias);
|
||||
}
|
||||
|
||||
clear_uniforms_frame(&uni->prev[0]);
|
||||
@ -662,6 +667,8 @@ static bool gl_glsl_init(void *data, const char *path)
|
||||
if (!glsl_shader)
|
||||
return false;
|
||||
|
||||
config_file_t *conf = NULL;
|
||||
|
||||
if (path)
|
||||
{
|
||||
bool ret;
|
||||
@ -674,12 +681,11 @@ static bool gl_glsl_init(void *data, const char *path)
|
||||
}
|
||||
else if (strcmp(path_get_extension(path), "glslp") == 0)
|
||||
{
|
||||
config_file_t *conf = config_file_new(path);
|
||||
conf = config_file_new(path);
|
||||
if (conf)
|
||||
{
|
||||
ret = gfx_shader_read_conf_cgp(conf, glsl_shader);
|
||||
glsl_shader->modern = true;
|
||||
config_file_free(conf);
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
@ -703,6 +709,13 @@ static bool gl_glsl_init(void *data, const char *path)
|
||||
}
|
||||
|
||||
gfx_shader_resolve_relative(glsl_shader, path);
|
||||
gfx_shader_resolve_parameters(conf, glsl_shader);
|
||||
|
||||
if (conf)
|
||||
{
|
||||
config_file_free(conf);
|
||||
conf = NULL;
|
||||
}
|
||||
|
||||
const char *stock_vertex = glsl_shader->modern ?
|
||||
stock_vertex_modern : stock_vertex_legacy;
|
||||
@ -729,6 +742,19 @@ static bool gl_glsl_init(void *data, const char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find all aliases we use in our GLSLP and add #defines for them so
|
||||
// that a shader can choose a fallback if we are not using a preset.
|
||||
*glsl_alias_define = '\0';
|
||||
for (i = 0; i < glsl_shader->passes; i++)
|
||||
{
|
||||
if (*glsl_shader->pass[i].alias)
|
||||
{
|
||||
char define[128];
|
||||
snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl_shader->pass[i].alias);
|
||||
strlcat(glsl_alias_define, define, sizeof(glsl_alias_define));
|
||||
}
|
||||
}
|
||||
|
||||
if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0)))
|
||||
{
|
||||
RARCH_ERR("GLSL stock programs failed to compile.\n");
|
||||
@ -810,12 +836,6 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
const struct gl_tex_info *fbo_info, unsigned fbo_info_cnt)
|
||||
{
|
||||
(void)data;
|
||||
// We enforce a certain layout for our various texture types in the texunits.
|
||||
// - Regular frame (Texture) (always bound).
|
||||
// - LUT textures (always bound).
|
||||
// - Original texture (always bound if meaningful).
|
||||
// - FBO textures (always bound if available).
|
||||
// - Previous textures.
|
||||
|
||||
if (!glsl_enable || (gl_program[active_index] == 0))
|
||||
return;
|
||||
@ -853,21 +873,22 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
if (uni->frame_direction >= 0)
|
||||
glUniform1i(uni->frame_direction, g_extern.frame_is_reverse ? -1 : 1);
|
||||
|
||||
unsigned texunit = 1;
|
||||
|
||||
for (i = 0; i < glsl_shader->luts; i++)
|
||||
{
|
||||
if (uni->lut_texture[i] >= 0)
|
||||
{
|
||||
// Have to rebind as HW render could override this.
|
||||
glActiveTexture(GL_TEXTURE0 + i + 1);
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, gl_teximage[i]);
|
||||
glUniform1i(uni->lut_texture[i], i + 1);
|
||||
glUniform1i(uni->lut_texture[i], texunit);
|
||||
texunit++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned texunit = glsl_shader->luts + 1;
|
||||
|
||||
// Set original texture unless we're in first pass (pointless).
|
||||
if (active_index > 1)
|
||||
// Set original texture.
|
||||
if (active_index)
|
||||
{
|
||||
if (uni->orig.texture >= 0)
|
||||
{
|
||||
@ -875,10 +896,9 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glUniform1i(uni->orig.texture, texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, info->tex);
|
||||
texunit++;
|
||||
}
|
||||
|
||||
texunit++;
|
||||
|
||||
if (uni->orig.texture_size >= 0)
|
||||
glUniform2fv(uni->orig.texture_size, 1, info->tex_size);
|
||||
|
||||
@ -898,20 +918,16 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
size += 8;
|
||||
}
|
||||
|
||||
// Bind new texture in the chain.
|
||||
if (fbo_info_cnt > 0)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + texunit + fbo_info_cnt - 1);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_info[fbo_info_cnt - 1].tex);
|
||||
}
|
||||
|
||||
// Bind FBO textures.
|
||||
for (i = 0; i < fbo_info_cnt; i++)
|
||||
{
|
||||
if (uni->pass[i].texture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_info[i].tex);
|
||||
glUniform1i(uni->pass[i].texture, texunit);
|
||||
|
||||
texunit++;
|
||||
texunit++;
|
||||
}
|
||||
|
||||
if (uni->pass[i].texture_size >= 0)
|
||||
glUniform2fv(uni->pass[i].texture_size, 1, fbo_info[i].tex_size);
|
||||
@ -932,23 +948,6 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// First pass, so unbind everything to avoid collitions.
|
||||
// Unbind ORIG.
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
GLuint base_tex = texunit + 1;
|
||||
// Unbind any lurking FBO passes.
|
||||
// Rendering to a texture that is bound to a texture unit
|
||||
// sounds very shaky ... ;)
|
||||
for (i = 0; i < glsl_shader->passes; i++)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + base_tex + i);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Set previous textures. Only bind if they're actually used.
|
||||
for (i = 0; i < PREV_TEXTURES; i++)
|
||||
@ -957,11 +956,10 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, prev_info[i].tex);
|
||||
glUniform1i(uni->prev[i].texture, texunit++);
|
||||
glUniform1i(uni->prev[i].texture, texunit);
|
||||
texunit++;
|
||||
}
|
||||
|
||||
texunit++;
|
||||
|
||||
if (uni->prev[i].texture_size >= 0)
|
||||
glUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size);
|
||||
|
||||
@ -992,6 +990,14 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// #pragma parameters
|
||||
for (i = 0; i < glsl_shader->num_parameters; i++)
|
||||
{
|
||||
int location = glGetUniformLocation(gl_program[active_index], glsl_shader->parameters[i].id);
|
||||
glUniform1f(location, glsl_shader->parameters[i].current);
|
||||
}
|
||||
|
||||
// Set state parameters
|
||||
if (gl_state_tracker)
|
||||
{
|
||||
static struct state_tracker_uniform info[GFX_MAX_VARIABLES];
|
||||
@ -1163,6 +1169,11 @@ static bool gl_glsl_mipmap_input(unsigned index)
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct gfx_shader *gl_glsl_get_current_shader(void)
|
||||
{
|
||||
return glsl_enable ? glsl_shader : NULL;
|
||||
}
|
||||
|
||||
void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*))
|
||||
{
|
||||
glsl_get_proc_address = proc;
|
||||
@ -1188,6 +1199,7 @@ const gl_shader_backend_t gl_glsl_backend = {
|
||||
gl_glsl_set_mvp,
|
||||
gl_glsl_get_prev_textures,
|
||||
gl_glsl_mipmap_input,
|
||||
gl_glsl_get_current_shader,
|
||||
|
||||
RARCH_SHADER_GLSL,
|
||||
};
|
||||
|
@ -435,6 +435,11 @@ static bool hlsl_mipmap_input(unsigned index)
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct gfx_shader *hlsl_get_current_shader(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const gl_shader_backend_t hlsl_backend = {
|
||||
hlsl_init,
|
||||
hlsl_deinit,
|
||||
@ -448,6 +453,7 @@ const gl_shader_backend_t hlsl_backend = {
|
||||
hlsl_set_mvp,
|
||||
NULL, /* hlsl_get_prev_textures */
|
||||
hlsl_mipmap_input,
|
||||
hlsl_get_current_shader,
|
||||
|
||||
RARCH_SHADER_HLSL,
|
||||
};
|
||||
|
@ -105,6 +105,11 @@ static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass,
|
||||
print_buf(mipmap_buf, "mipmap_input%u", i);
|
||||
config_get_bool(conf, mipmap_buf, &pass->mipmap);
|
||||
|
||||
char alias_buf[64];
|
||||
print_buf(alias_buf, "alias%u", i);
|
||||
if (!config_get_array(conf, alias_buf, pass->alias, sizeof(pass->alias)))
|
||||
*pass->alias = '\0';
|
||||
|
||||
// Scale
|
||||
struct gfx_fbo_scale *scale = &pass->fbo;
|
||||
char scale_type[64] = {0};
|
||||
@ -268,10 +273,88 @@ static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct gfx_shader_parameter *find_parameter(struct gfx_shader_parameter *params, unsigned num_params, const char *id)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < num_params; i++)
|
||||
{
|
||||
if (!strcmp(params[i].id, id))
|
||||
return ¶ms[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gfx_shader_resolve_parameters(config_file_t *conf, struct gfx_shader *shader)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
shader->num_parameters = 0;
|
||||
struct gfx_shader_parameter *param = &shader->parameters[shader->num_parameters];
|
||||
|
||||
// Find all parameters in our shaders.
|
||||
for (i = 0; i < shader->passes; i++)
|
||||
{
|
||||
char line[2048];
|
||||
FILE *file = fopen(shader->pass[i].source.path, "r");
|
||||
if (!file)
|
||||
continue;
|
||||
|
||||
while (shader->num_parameters < ARRAY_SIZE(shader->parameters) && fgets(line, sizeof(line), file))
|
||||
{
|
||||
int ret = sscanf(line, "#pragma parameter %64s \"%64[^\"]\" %f %f %f %f",
|
||||
param->id, param->desc, ¶m->initial, ¶m->minimum, ¶m->maximum, ¶m->step);
|
||||
|
||||
if (ret >= 5)
|
||||
{
|
||||
param->id[63] = '\0';
|
||||
param->desc[63] = '\0';
|
||||
|
||||
if (ret == 5)
|
||||
param->step = 0.1f * (param->maximum - param->minimum);
|
||||
|
||||
RARCH_LOG("Found #pragma parameter %s (%s) %f %f %f %f\n",
|
||||
param->desc, param->id, param->initial, param->minimum, param->maximum, param->step);
|
||||
param->current = param->initial;
|
||||
|
||||
shader->num_parameters++;
|
||||
param++;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// Read in parameters which override the defaults.
|
||||
if (conf)
|
||||
{
|
||||
char parameters[1024];
|
||||
char *save = NULL;
|
||||
const char *id;
|
||||
|
||||
if (!config_get_array(conf, "parameters", parameters, sizeof(parameters)))
|
||||
return true;
|
||||
|
||||
for (id = strtok_r(parameters, ";", &save); id; id = strtok_r(NULL, ";", &save))
|
||||
{
|
||||
struct gfx_shader_parameter *param = find_parameter(shader->parameters, shader->num_parameters, id);
|
||||
if (!param)
|
||||
{
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is set in the preset, but no shader uses this parameter, ignoring.\n", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_get_float(conf, id, ¶m->current))
|
||||
RARCH_WARN("[CGP/GLSLP]: Parameter %s is not set in preset.\n", id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool shader_parse_imports(config_file_t *conf, struct gfx_shader *shader)
|
||||
{
|
||||
char imports[1024];
|
||||
char *save;
|
||||
char *save = NULL;
|
||||
const char *id;
|
||||
if (!config_get_array(conf, "imports", imports, sizeof(imports)))
|
||||
return true;
|
||||
@ -538,9 +621,32 @@ void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *sha
|
||||
print_buf(key, "mipmap_input%u", i);
|
||||
config_set_bool(conf, key, pass->mipmap);
|
||||
|
||||
print_buf(key, "alias%u", i);
|
||||
config_set_string(conf, key, pass->alias);
|
||||
|
||||
shader_write_fbo(conf, &pass->fbo, i);
|
||||
}
|
||||
|
||||
if (shader->num_parameters)
|
||||
{
|
||||
char parameters[4096] = {0};
|
||||
strlcpy(parameters, shader->parameters[0].id, sizeof(parameters));
|
||||
for (i = 1; i < shader->num_parameters; i++)
|
||||
{
|
||||
// O(n^2), but number of parameters is very limited.
|
||||
strlcat(parameters, ";", sizeof(parameters));
|
||||
strlcat(parameters, shader->parameters[i].id, sizeof(parameters));
|
||||
}
|
||||
|
||||
config_set_string(conf, "parameters", parameters);
|
||||
|
||||
for (i = 0; i < shader->num_parameters; i++)
|
||||
{
|
||||
char key[64];
|
||||
config_set_float(conf, shader->parameters[i].id, shader->parameters[i].current);
|
||||
}
|
||||
}
|
||||
|
||||
if (shader->luts)
|
||||
{
|
||||
char textures[4096] = {0};
|
||||
|
@ -28,6 +28,7 @@ extern "C" {
|
||||
#define GFX_MAX_SHADERS 16
|
||||
#define GFX_MAX_TEXTURES 8
|
||||
#define GFX_MAX_VARIABLES 64
|
||||
#define GFX_MAX_PARAMETERS 64
|
||||
|
||||
enum gfx_scale_type
|
||||
{
|
||||
@ -65,6 +66,17 @@ struct gfx_fbo_scale
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct gfx_shader_parameter
|
||||
{
|
||||
char id[64];
|
||||
char desc[64];
|
||||
float current;
|
||||
float minimum;
|
||||
float initial;
|
||||
float maximum;
|
||||
float step;
|
||||
};
|
||||
|
||||
struct gfx_shader_pass
|
||||
{
|
||||
struct
|
||||
@ -77,6 +89,7 @@ struct gfx_shader_pass
|
||||
} string;
|
||||
} source;
|
||||
|
||||
char alias[64];
|
||||
struct gfx_fbo_scale fbo;
|
||||
enum gfx_filter_type filter;
|
||||
enum gfx_wrap_type wrap;
|
||||
@ -108,6 +121,9 @@ struct gfx_shader
|
||||
unsigned luts;
|
||||
struct gfx_shader_lut lut[GFX_MAX_TEXTURES];
|
||||
|
||||
struct gfx_shader_parameter parameters[GFX_MAX_PARAMETERS];
|
||||
unsigned num_parameters;
|
||||
|
||||
unsigned variables;
|
||||
struct state_tracker_uniform_info variable[GFX_MAX_VARIABLES];
|
||||
char script_path[PATH_MAX];
|
||||
@ -119,6 +135,7 @@ bool gfx_shader_read_conf_cgp(config_file_t *conf, struct gfx_shader *shader);
|
||||
void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *shader);
|
||||
|
||||
void gfx_shader_resolve_relative(struct gfx_shader *shader, const char *ref_path);
|
||||
bool gfx_shader_resolve_parameters(config_file_t *conf, struct gfx_shader *shader);
|
||||
|
||||
enum rarch_shader_type gfx_shader_parse_type(const char *path, enum rarch_shader_type fallback);
|
||||
|
||||
|
@ -751,6 +751,13 @@ static void thread_apply_state_changes(void *data)
|
||||
slock_unlock(thr->frame.lock);
|
||||
}
|
||||
|
||||
// This is read-only state which should not have any kind of race condition.
|
||||
static struct gfx_shader *thread_get_current_shader(void *data)
|
||||
{
|
||||
thread_video_t *thr = (thread_video_t*)data;
|
||||
return thr->poke ? thr->poke->get_current_shader(thr->driver_data) : NULL;
|
||||
}
|
||||
|
||||
static const video_poke_interface_t thread_poke = {
|
||||
thread_set_filtering,
|
||||
#ifdef HAVE_FBO
|
||||
@ -763,6 +770,12 @@ static const video_poke_interface_t thread_poke = {
|
||||
thread_set_texture_frame,
|
||||
thread_set_texture_enable,
|
||||
#endif
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
thread_get_current_shader,
|
||||
};
|
||||
|
||||
static void thread_get_poke_interface(void *data, const video_poke_interface_t **iface)
|
||||
|
Loading…
Reference in New Issue
Block a user