mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-18 17:04:34 +00:00
Reintroduce CGP refactor.
Fix several issues that caused crashes.
This commit is contained in:
parent
c3ac3028b5
commit
e649db253c
1
Makefile
1
Makefile
@ -23,6 +23,7 @@ OBJ = frontend/frontend.o \
|
||||
conf/config_file.o \
|
||||
screenshot.o \
|
||||
gfx/scaler/scaler.o \
|
||||
gfx/shader_parse.o \
|
||||
gfx/scaler/pixconv.o \
|
||||
gfx/scaler/scaler_int.o \
|
||||
gfx/scaler/filter.o \
|
||||
|
@ -29,6 +29,7 @@ OBJ = frontend/frontend.o \
|
||||
gfx/scaler/scaler_int.o \
|
||||
gfx/scaler/filter.o \
|
||||
gfx/state_tracker.o \
|
||||
gfx/shader_parse.o \
|
||||
gfx/fonts/fonts.o \
|
||||
gfx/fonts/bitmapfont.o \
|
||||
gfx/image.o \
|
||||
|
@ -696,6 +696,13 @@ void config_set_int(config_file_t *conf, const char *key, int val)
|
||||
config_set_string(conf, key, buf);
|
||||
}
|
||||
|
||||
void config_set_hex(config_file_t *conf, const char *key, unsigned val)
|
||||
{
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%x", val);
|
||||
config_set_string(conf, key, buf);
|
||||
}
|
||||
|
||||
void config_set_uint64(config_file_t *conf, const char *key, uint64_t val)
|
||||
{
|
||||
char buf[128];
|
||||
|
@ -92,6 +92,7 @@ bool config_get_bool(config_file_t *conf, const char *entry, bool *in);
|
||||
void config_set_double(config_file_t *conf, const char *entry, double value);
|
||||
void config_set_float(config_file_t *conf, const char *entry, float value);
|
||||
void config_set_int(config_file_t *conf, const char *entry, int val);
|
||||
void config_set_hex(config_file_t *conf, const char *entry, unsigned val);
|
||||
void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val);
|
||||
void config_set_char(config_file_t *conf, const char *entry, char val);
|
||||
void config_set_string(config_file_t *conf, const char *entry, const char *val);
|
||||
|
4
gfx/gl.c
4
gfx/gl.c
@ -439,7 +439,7 @@ static bool gl_shader_filter_type(void *data, unsigned index, bool *smooth)
|
||||
}
|
||||
|
||||
#ifdef HAVE_FBO
|
||||
static void gl_shader_scale(void *data, unsigned index, struct gl_fbo_scale *scale)
|
||||
static void gl_shader_scale(void *data, unsigned index, struct gfx_fbo_scale *scale)
|
||||
{
|
||||
gl_t *gl = (gl_t*)data;
|
||||
|
||||
@ -674,7 +674,7 @@ void gl_init_fbo(void *data, unsigned width, unsigned height)
|
||||
return;
|
||||
#endif
|
||||
|
||||
struct gl_fbo_scale scale, scale_last;
|
||||
struct gfx_fbo_scale scale, scale_last;
|
||||
gl_shader_scale(gl, 1, &scale);
|
||||
gl_shader_scale(gl, gl_shader_num_func(gl), &scale_last);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "gfx_context.h"
|
||||
#include "scaler/scaler.h"
|
||||
#include "fonts/gl_font.h"
|
||||
#include "shader_parse.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
@ -160,25 +161,6 @@ struct gl_fbo_rect
|
||||
unsigned height;
|
||||
};
|
||||
|
||||
enum gl_scale_type
|
||||
{
|
||||
RARCH_SCALE_ABSOLUTE,
|
||||
RARCH_SCALE_INPUT,
|
||||
RARCH_SCALE_VIEWPORT
|
||||
};
|
||||
|
||||
struct gl_fbo_scale
|
||||
{
|
||||
bool fp_fbo;
|
||||
enum gl_scale_type type_x;
|
||||
enum gl_scale_type type_y;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
unsigned abs_x;
|
||||
unsigned abs_y;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct gl_ortho
|
||||
{
|
||||
GLfloat left;
|
||||
@ -239,7 +221,7 @@ typedef struct gl
|
||||
GLuint fbo[MAX_SHADERS];
|
||||
GLuint fbo_texture[MAX_SHADERS];
|
||||
struct gl_fbo_rect fbo_rect[MAX_SHADERS];
|
||||
struct gl_fbo_scale fbo_scale[MAX_SHADERS];
|
||||
struct gfx_fbo_scale fbo_scale[MAX_SHADERS];
|
||||
int fbo_pass;
|
||||
bool fbo_inited;
|
||||
|
||||
|
555
gfx/shader_cg.c
555
gfx/shader_cg.c
@ -123,35 +123,25 @@ struct cg_program
|
||||
CGparameter frame_dir_v;
|
||||
CGparameter mvp;
|
||||
|
||||
unsigned frame_count_mod;
|
||||
|
||||
struct cg_fbo_params fbo[RARCH_CG_MAX_SHADERS];
|
||||
struct cg_fbo_params orig;
|
||||
struct cg_fbo_params prev[PREV_TEXTURES];
|
||||
};
|
||||
|
||||
#define FILTER_UNSPEC 0
|
||||
#define FILTER_LINEAR 1
|
||||
#define FILTER_NEAREST 2
|
||||
|
||||
static struct cg_program prg[RARCH_CG_MAX_SHADERS];
|
||||
static const char **cg_arguments;
|
||||
static bool cg_active = false;
|
||||
static bool cg_active;
|
||||
static CGprofile cgVProf, cgFProf;
|
||||
static unsigned active_index = 0;
|
||||
static unsigned cg_shader_num = 0;
|
||||
static struct gl_fbo_scale cg_scale[RARCH_CG_MAX_SHADERS];
|
||||
static unsigned fbo_smooth[RARCH_CG_MAX_SHADERS];
|
||||
static unsigned active_index;
|
||||
|
||||
static struct gfx_shader *cg_shader;
|
||||
|
||||
static state_tracker_t *state_tracker;
|
||||
static GLuint lut_textures[MAX_TEXTURES];
|
||||
static unsigned lut_textures_num = 0;
|
||||
static char lut_textures_uniform[MAX_TEXTURES][64];
|
||||
|
||||
static CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + RARCH_CG_MAX_SHADERS];
|
||||
static unsigned cg_attrib_index;
|
||||
|
||||
static state_tracker_t *state_tracker = NULL;
|
||||
|
||||
static void gl_cg_reset_attrib(void)
|
||||
{
|
||||
for (unsigned i = 0; i < cg_attrib_index; i++)
|
||||
@ -222,8 +212,9 @@ void gl_cg_set_params(unsigned width, unsigned height,
|
||||
|
||||
if (prg[active_index].frame_cnt_f || prg[active_index].frame_cnt_v)
|
||||
{
|
||||
if (prg[active_index].frame_count_mod)
|
||||
frame_count %= prg[active_index].frame_count_mod;
|
||||
unsigned modulo = cg_shader->pass[active_index - 1].frame_count_mod;
|
||||
if (modulo)
|
||||
frame_count %= modulo;
|
||||
|
||||
set_param_1f(prg[active_index].frame_cnt_f, (float)frame_count);
|
||||
set_param_1f(prg[active_index].frame_cnt_v, (float)frame_count);
|
||||
@ -275,9 +266,9 @@ void gl_cg_set_params(unsigned width, unsigned height,
|
||||
}
|
||||
|
||||
// Set lookup textures.
|
||||
for (unsigned i = 0; i < lut_textures_num; i++)
|
||||
for (unsigned i = 0; i < cg_shader->luts; i++)
|
||||
{
|
||||
CGparameter param = cgGetNamedParameter(prg[active_index].fprg, lut_textures_uniform[i]);
|
||||
CGparameter param = cgGetNamedParameter(prg[active_index].fprg, cg_shader->lut[i].id);
|
||||
if (param)
|
||||
{
|
||||
cgGLSetTextureParameter(param, lut_textures[i]);
|
||||
@ -357,23 +348,24 @@ static void gl_cg_deinit_progs(void)
|
||||
static void gl_cg_deinit_state(void)
|
||||
{
|
||||
gl_cg_reset_attrib();
|
||||
|
||||
cg_active = false;
|
||||
cg_shader_num = 0;
|
||||
|
||||
gl_cg_deinit_progs();
|
||||
|
||||
memset(cg_scale, 0, sizeof(cg_scale));
|
||||
memset(fbo_smooth, 0, sizeof(fbo_smooth));
|
||||
|
||||
glDeleteTextures(lut_textures_num, lut_textures);
|
||||
lut_textures_num = 0;
|
||||
if (cg_shader && cg_shader->luts)
|
||||
{
|
||||
glDeleteTextures(cg_shader->luts, lut_textures);
|
||||
memset(lut_textures, 0, sizeof(lut_textures));
|
||||
}
|
||||
|
||||
if (state_tracker)
|
||||
{
|
||||
state_tracker_free(state_tracker);
|
||||
state_tracker = NULL;
|
||||
}
|
||||
|
||||
free(cg_shader);
|
||||
cg_shader = NULL;
|
||||
}
|
||||
|
||||
// Final deinit.
|
||||
@ -486,10 +478,16 @@ static bool load_plain(const char *path)
|
||||
if (!load_stock())
|
||||
return false;
|
||||
|
||||
cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg_shader));
|
||||
if (!cg_shader)
|
||||
return false;
|
||||
|
||||
cg_shader->passes = 1;
|
||||
|
||||
if (path)
|
||||
{
|
||||
RARCH_LOG("Loading Cg file: %s\n", path);
|
||||
|
||||
strlcpy(cg_shader->pass[0].source.cg, path, sizeof(cg_shader->pass[0].source.cg));
|
||||
if (!load_program(1, path, true))
|
||||
return false;
|
||||
}
|
||||
@ -499,8 +497,6 @@ static bool load_plain(const char *path)
|
||||
prg[1] = prg[0];
|
||||
}
|
||||
|
||||
cg_shader_num = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -517,10 +513,9 @@ static bool load_menu_shader(void)
|
||||
#define BORDER_FUNC GL_CLAMP_TO_BORDER
|
||||
#endif
|
||||
|
||||
static void load_texture_data(GLuint *obj, const struct texture_image *img, bool smooth)
|
||||
static void load_texture_data(GLuint obj, const struct texture_image *img, bool smooth)
|
||||
{
|
||||
glGenTextures(1, obj);
|
||||
glBindTexture(GL_TEXTURE_2D, *obj);
|
||||
glBindTexture(GL_TEXTURE_2D, obj);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC);
|
||||
@ -537,41 +532,18 @@ static void load_texture_data(GLuint *obj, const struct texture_image *img, bool
|
||||
free(img->pixels);
|
||||
}
|
||||
|
||||
static bool load_textures(const char *cgp_path, config_file_t *conf)
|
||||
static bool load_textures(const char *cgp_path)
|
||||
{
|
||||
bool ret = true;
|
||||
char *textures = NULL;
|
||||
if (!config_get_string(conf, "textures", &textures)) // No textures here ...
|
||||
if (!cg_shader->luts)
|
||||
return true;
|
||||
|
||||
char *save;
|
||||
const char *id = strtok_r(textures, ";", &save);
|
||||
while (id && lut_textures_num < MAX_TEXTURES)
|
||||
glGenTextures(cg_shader->luts, lut_textures);
|
||||
|
||||
for (unsigned i = 0; i < cg_shader->luts; i++)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
if (!config_get_array(conf, id, path, sizeof(path)))
|
||||
{
|
||||
RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id);
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
char id_filter[64];
|
||||
print_buf(id_filter, "%s_linear", id);
|
||||
|
||||
bool smooth = true;
|
||||
if (!config_get_bool(conf, id_filter, &smooth))
|
||||
smooth = true;
|
||||
|
||||
char id_absolute[64];
|
||||
print_buf(id_absolute, "%s_absolute", id);
|
||||
|
||||
bool absolute = false;
|
||||
if (!config_get_bool(conf, id_absolute, &absolute))
|
||||
absolute = false;
|
||||
|
||||
char image_path[PATH_MAX];
|
||||
fill_pathname_resolve_relative(image_path, cgp_path, path, sizeof(image_path));
|
||||
fill_pathname_resolve_relative(image_path, cgp_path,
|
||||
cg_shader->lut[i].path, sizeof(image_path));
|
||||
|
||||
RARCH_LOG("Loading image from: \"%s\".\n", image_path);
|
||||
|
||||
@ -579,130 +551,25 @@ static bool load_textures(const char *cgp_path, config_file_t *conf)
|
||||
if (!texture_image_load(image_path, &img))
|
||||
{
|
||||
RARCH_ERR("Failed to load picture ...\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(lut_textures_uniform[lut_textures_num],
|
||||
id, sizeof(lut_textures_uniform[lut_textures_num]));
|
||||
|
||||
load_texture_data(&lut_textures[lut_textures_num], &img, smooth);
|
||||
lut_textures_num++;
|
||||
|
||||
id = strtok_r(NULL, ";", &save);
|
||||
load_texture_data(lut_textures[i], &img,
|
||||
cg_shader->lut[i].filter != RARCH_FILTER_NEAREST);
|
||||
}
|
||||
|
||||
end:
|
||||
free(textures);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool load_imports(const char *cgp_path, config_file_t *conf)
|
||||
static bool load_imports(const char *cgp_path)
|
||||
{
|
||||
bool ret = true;
|
||||
char *imports = NULL;
|
||||
|
||||
if (!config_get_string(conf, "imports", &imports))
|
||||
return true;
|
||||
|
||||
struct state_tracker_uniform_info info[MAX_VARIABLES];
|
||||
unsigned info_cnt = 0;
|
||||
struct state_tracker_info tracker_info = {0};
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
char script_path[PATH_MAX];
|
||||
char *script = NULL;
|
||||
char *script_class = NULL;
|
||||
#endif
|
||||
|
||||
char *save;
|
||||
const char *id = strtok_r(imports, ";", &save);
|
||||
while (id && info_cnt < MAX_VARIABLES)
|
||||
for (unsigned i = 0; i < cg_shader->variables; i++)
|
||||
{
|
||||
char semantic_buf[64];
|
||||
char wram_buf[64];
|
||||
char input_slot_buf[64];
|
||||
char mask_buf[64];
|
||||
char equal_buf[64];
|
||||
|
||||
print_buf(semantic_buf, "%s_semantic", id);
|
||||
print_buf(wram_buf, "%s_wram", id);
|
||||
print_buf(input_slot_buf, "%s_input_slot", id);
|
||||
print_buf(mask_buf, "%s_mask", id);
|
||||
print_buf(equal_buf, "%s_equal", id);
|
||||
|
||||
char *semantic = NULL;
|
||||
|
||||
config_get_string(conf, semantic_buf, &semantic);
|
||||
|
||||
if (!semantic)
|
||||
{
|
||||
RARCH_ERR("No semantic for import variable.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
enum state_tracker_type tracker_type;
|
||||
enum state_ram_type ram_type = RARCH_STATE_NONE;
|
||||
|
||||
if (strcmp(semantic, "capture") == 0)
|
||||
tracker_type = RARCH_STATE_CAPTURE;
|
||||
else if (strcmp(semantic, "transition") == 0)
|
||||
tracker_type = RARCH_STATE_TRANSITION;
|
||||
else if (strcmp(semantic, "transition_count") == 0)
|
||||
tracker_type = RARCH_STATE_TRANSITION_COUNT;
|
||||
else if (strcmp(semantic, "capture_previous") == 0)
|
||||
tracker_type = RARCH_STATE_CAPTURE_PREV;
|
||||
else if (strcmp(semantic, "transition_previous") == 0)
|
||||
tracker_type = RARCH_STATE_TRANSITION_PREV;
|
||||
#ifdef HAVE_PYTHON
|
||||
else if (strcmp(semantic, "python") == 0)
|
||||
tracker_type = RARCH_STATE_PYTHON;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid semantic.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
unsigned addr = 0;
|
||||
#ifdef HAVE_PYTHON
|
||||
if (tracker_type != RARCH_STATE_PYTHON)
|
||||
#endif
|
||||
{
|
||||
unsigned input_slot = 0;
|
||||
if (config_get_hex(conf, input_slot_buf, &input_slot))
|
||||
{
|
||||
switch (input_slot)
|
||||
{
|
||||
case 1:
|
||||
ram_type = RARCH_STATE_INPUT_SLOT1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ram_type = RARCH_STATE_INPUT_SLOT2;
|
||||
break;
|
||||
|
||||
default:
|
||||
RARCH_ERR("Invalid input slot for import.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (config_get_hex(conf, wram_buf, &addr))
|
||||
ram_type = RARCH_STATE_WRAM;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("No address assigned to semantic.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned memtype;
|
||||
switch (ram_type)
|
||||
switch (cg_shader->variable[i].ram_type)
|
||||
{
|
||||
case RARCH_STATE_WRAM:
|
||||
memtype = RETRO_MEMORY_SYSTEM_RAM;
|
||||
@ -712,336 +579,118 @@ static bool load_imports(const char *cgp_path, config_file_t *conf)
|
||||
memtype = -1u;
|
||||
}
|
||||
|
||||
if ((memtype != -1u) && (addr >= pretro_get_memory_size(memtype)))
|
||||
if ((memtype != -1u) && (cg_shader->variable[i].addr >= pretro_get_memory_size(memtype)))
|
||||
{
|
||||
RARCH_ERR("Address out of bounds.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned bitmask = 0;
|
||||
if (!config_get_hex(conf, mask_buf, &bitmask))
|
||||
bitmask = 0;
|
||||
unsigned bitequal = 0;
|
||||
if (!config_get_hex(conf, equal_buf, &bitequal))
|
||||
bitequal = 0;
|
||||
|
||||
strlcpy(info[info_cnt].id, id, sizeof(info[info_cnt].id));
|
||||
info[info_cnt].addr = addr;
|
||||
info[info_cnt].type = tracker_type;
|
||||
info[info_cnt].ram_type = ram_type;
|
||||
info[info_cnt].mask = bitmask;
|
||||
info[info_cnt].equal = bitequal;
|
||||
|
||||
info_cnt++;
|
||||
free(semantic);
|
||||
|
||||
id = strtok_r(NULL, ";", &save);
|
||||
}
|
||||
|
||||
tracker_info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM);
|
||||
tracker_info.info = info;
|
||||
tracker_info.info_elem = info_cnt;
|
||||
tracker_info.info = cg_shader->variable;
|
||||
tracker_info.info_elem = cg_shader->variables;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
if (config_get_string(conf, "import_script", &script))
|
||||
if (*cg_shader->script_path)
|
||||
{
|
||||
fill_pathname_resolve_relative(script_path, cgp_path, script, sizeof(script_path));
|
||||
char script_path[PATH_MAX];
|
||||
fill_pathname_resolve_relative(script_path, cgp_path,
|
||||
cg_shader->script_path, sizeof(script_path));
|
||||
tracker_info.script = script_path;
|
||||
tracker_info.script_is_file = true;
|
||||
}
|
||||
if (config_get_string(conf, "import_script_class", &script_class))
|
||||
tracker_info.script_class = script_class;
|
||||
|
||||
tracker_info.script_is_file = true;
|
||||
tracker_info.script_class = *cg_shader->script_class ? cg_shader->script_class : NULL;
|
||||
#endif
|
||||
|
||||
state_tracker = state_tracker_init(&tracker_info);
|
||||
if (!state_tracker)
|
||||
RARCH_WARN("Failed to initialize state tracker.\n");
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
if (script)
|
||||
free(script);
|
||||
if (script_class)
|
||||
free(script_class);
|
||||
#endif
|
||||
|
||||
end:
|
||||
free(imports);
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool load_shader(const char *cgp_path, unsigned i, config_file_t *conf)
|
||||
static bool load_shader(const char *cgp_path, unsigned i)
|
||||
{
|
||||
char *shader_path = NULL;
|
||||
char attr_buf[64];
|
||||
char path_buf[PATH_MAX];
|
||||
|
||||
print_buf(attr_buf, "shader%u", i);
|
||||
if (config_get_string(conf, attr_buf, &shader_path))
|
||||
{
|
||||
fill_pathname_resolve_relative(path_buf, cgp_path, shader_path, sizeof(path_buf));
|
||||
free(shader_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Didn't find shader path in config ...\n");
|
||||
return false;
|
||||
}
|
||||
fill_pathname_resolve_relative(path_buf, cgp_path,
|
||||
cg_shader->pass[i].source.cg, sizeof(path_buf));
|
||||
|
||||
RARCH_LOG("Loading Cg shader: \"%s\".\n", path_buf);
|
||||
|
||||
if (!load_program(i + 1, path_buf, true))
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_RMENU
|
||||
// In RMenu, need to display shaders in menu.
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
strlcpy(g_settings.video.cg_shader_path,
|
||||
path_buf, sizeof(g_settings.video.cg_shader_path));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool load_shader_params(unsigned i, config_file_t *conf)
|
||||
{
|
||||
char scale_type[64] = {0};
|
||||
char scale_type_x[64] = {0};
|
||||
char scale_type_y[64] = {0};
|
||||
|
||||
prg[i + 1].frame_count_mod = 0;
|
||||
char frame_count_mod[64] = {0};
|
||||
char frame_count_mod_buf[64];
|
||||
print_buf(frame_count_mod_buf, "frame_count_mod%u", i);
|
||||
if (config_get_array(conf, frame_count_mod_buf, frame_count_mod, sizeof(frame_count_mod)))
|
||||
prg[i + 1].frame_count_mod = strtoul(frame_count_mod, NULL, 0);
|
||||
|
||||
char scale_name_buf[64];
|
||||
print_buf(scale_name_buf, "scale_type%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type, sizeof(scale_type));
|
||||
|
||||
print_buf(scale_name_buf, "scale_type_x%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type_x, sizeof(scale_type_x));
|
||||
|
||||
print_buf(scale_name_buf, "scale_type_y%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type_y, sizeof(scale_type_y));
|
||||
|
||||
if (!*scale_type && !*scale_type_x && !*scale_type_y)
|
||||
return true;
|
||||
|
||||
if (*scale_type)
|
||||
{
|
||||
strlcpy(scale_type_x, scale_type, sizeof(scale_type_x));
|
||||
strlcpy(scale_type_y, scale_type, sizeof(scale_type_y));
|
||||
}
|
||||
|
||||
char attr_name_buf[64];
|
||||
float fattr = 0.0f;
|
||||
int iattr = 0;
|
||||
struct gl_fbo_scale *scale = &cg_scale[i + 1]; // Shader 0 is passthrough shader. Start at 1.
|
||||
|
||||
scale->valid = true;
|
||||
scale->type_x = RARCH_SCALE_INPUT;
|
||||
scale->type_y = RARCH_SCALE_INPUT;
|
||||
scale->scale_x = 1.0;
|
||||
scale->scale_y = 1.0;
|
||||
|
||||
char fp_fbo_buf[64];
|
||||
print_buf(fp_fbo_buf, "float_framebuffer%u", i);
|
||||
scale->fp_fbo = false;
|
||||
config_get_bool(conf, fp_fbo_buf, &scale->fp_fbo);
|
||||
|
||||
const struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
|
||||
scale->abs_x = geom->base_width;
|
||||
scale->abs_y = geom->base_height;
|
||||
|
||||
if (*scale_type_x)
|
||||
{
|
||||
if (strcmp(scale_type_x, "source") == 0)
|
||||
scale->type_x = RARCH_SCALE_INPUT;
|
||||
else if (strcmp(scale_type_x, "viewport") == 0)
|
||||
scale->type_x = RARCH_SCALE_VIEWPORT;
|
||||
else if (strcmp(scale_type_x, "absolute") == 0)
|
||||
scale->type_x = RARCH_SCALE_ABSOLUTE;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid attribute.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (*scale_type_y)
|
||||
{
|
||||
if (strcmp(scale_type_y, "source") == 0)
|
||||
scale->type_y = RARCH_SCALE_INPUT;
|
||||
else if (strcmp(scale_type_y, "viewport") == 0)
|
||||
scale->type_y = RARCH_SCALE_VIEWPORT;
|
||||
else if (strcmp(scale_type_y, "absolute") == 0)
|
||||
scale->type_y = RARCH_SCALE_ABSOLUTE;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid attribute.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale->type_x == RARCH_SCALE_ABSOLUTE)
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_x = iattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_x%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_x = iattr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_x = fattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_x%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_x = fattr;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale->type_y == RARCH_SCALE_ABSOLUTE)
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_y = iattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_y%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_y = iattr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_y = fattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_y%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_y = fattr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool load_preset(const char *path)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (!load_stock())
|
||||
return false;
|
||||
|
||||
int shaders = 0;
|
||||
|
||||
RARCH_LOG("Loading Cg meta-shader: %s\n", path);
|
||||
config_file_t *conf = config_file_new(path);
|
||||
if (!conf)
|
||||
{
|
||||
RARCH_ERR("Failed to load preset.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config_get_int(conf, "shaders", &shaders))
|
||||
if (!cg_shader)
|
||||
cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg_shader));
|
||||
if (!cg_shader)
|
||||
return false;
|
||||
|
||||
if (!gfx_shader_read_conf_cgp(conf, cg_shader))
|
||||
{
|
||||
RARCH_ERR("Cannot find \"shaders\" param.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
RARCH_ERR("Failed to parse CGP file.\n");
|
||||
config_file_free(conf);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shaders < 1)
|
||||
{
|
||||
RARCH_ERR("Need to define at least 1 shader.\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
config_file_free(conf);
|
||||
|
||||
cg_shader_num = shaders;
|
||||
if (shaders > RARCH_CG_MAX_SHADERS - 3)
|
||||
#if 0 // Debugging
|
||||
config_file_t *save_test = config_file_new(NULL);
|
||||
gfx_shader_write_conf_cgp(conf, cg_shader);
|
||||
config_file_write(save_test, "/tmp/load.cgp");
|
||||
config_file_free(save_test);
|
||||
#endif
|
||||
|
||||
if (cg_shader->passes > RARCH_CG_MAX_SHADERS - 3)
|
||||
{
|
||||
RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", RARCH_CG_MAX_SHADERS - 3);
|
||||
cg_shader_num = shaders = RARCH_CG_MAX_SHADERS - 3;
|
||||
cg_shader->passes = RARCH_CG_MAX_SHADERS - 3;
|
||||
}
|
||||
// If we aren't using last pass non-FBO shader,
|
||||
// this shader will be assumed to be "fixed-function".
|
||||
// Just use prg[0] for that pass, which will be
|
||||
// pass-through.
|
||||
prg[shaders + 1] = prg[0];
|
||||
prg[cg_shader->passes + 1] = prg[0];
|
||||
|
||||
// Check filter params.
|
||||
for (int i = 0; i < shaders; i++)
|
||||
for (unsigned i = 0; i < cg_shader->passes; i++)
|
||||
{
|
||||
bool smooth = false;
|
||||
char filter_name_buf[64];
|
||||
print_buf(filter_name_buf, "filter_linear%u", i);
|
||||
if (config_get_bool(conf, filter_name_buf, &smooth))
|
||||
fbo_smooth[i + 1] = smooth ? FILTER_LINEAR : FILTER_NEAREST;
|
||||
|
||||
#ifdef HAVE_RMENU
|
||||
// In RMenu, need to set smoothing for first and second passes.
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
g_settings.video.smooth = fbo_smooth[1] == FILTER_LINEAR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int i = 0; i < shaders; i++)
|
||||
{
|
||||
if (!load_shader_params(i, conf))
|
||||
{
|
||||
RARCH_ERR("Failed to load shader params ...\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!load_shader(path, i, conf))
|
||||
if (!load_shader(path, i))
|
||||
{
|
||||
RARCH_ERR("Failed to load shaders ...\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!load_textures(path, conf))
|
||||
if (!load_textures(path))
|
||||
{
|
||||
RARCH_ERR("Failed to load lookup textures ...\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!load_imports(path, conf))
|
||||
if (!load_imports(path))
|
||||
{
|
||||
RARCH_ERR("Failed to load imports ...\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
|
||||
end:
|
||||
if (conf)
|
||||
config_file_free(conf);
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_program_base_attrib(unsigned i)
|
||||
@ -1202,7 +851,7 @@ bool gl_cg_init(const char *path)
|
||||
|
||||
prg[0].mvp = cgGetNamedParameter(prg[0].vprg, "modelViewProj");
|
||||
|
||||
for (unsigned i = 1; i <= cg_shader_num; i++)
|
||||
for (unsigned i = 1; i <= cg_shader->passes; i++)
|
||||
set_program_attributes(i);
|
||||
|
||||
if (menu_cg_program)
|
||||
@ -1230,37 +879,35 @@ void gl_cg_use(unsigned index)
|
||||
unsigned gl_cg_num(void)
|
||||
{
|
||||
if (cg_active)
|
||||
return cg_shader_num;
|
||||
return cg_shader->passes;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool gl_cg_filter_type(unsigned index, bool *smooth)
|
||||
{
|
||||
if (cg_active)
|
||||
if (cg_active && index)
|
||||
{
|
||||
if (fbo_smooth[index] == FILTER_UNSPEC)
|
||||
if (cg_shader->pass[index - 1].filter == RARCH_FILTER_UNSPEC)
|
||||
return false;
|
||||
*smooth = (fbo_smooth[index] == FILTER_LINEAR);
|
||||
*smooth = cg_shader->pass[index - 1].filter == RARCH_FILTER_LINEAR;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void gl_cg_shader_scale(unsigned index, struct gl_fbo_scale *scale)
|
||||
void gl_cg_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
|
||||
{
|
||||
if (cg_active)
|
||||
*scale = cg_scale[index];
|
||||
if (cg_active && index)
|
||||
*scale = cg_shader->pass[index - 1].fbo;
|
||||
else
|
||||
scale->valid = false;
|
||||
}
|
||||
|
||||
void gl_cg_set_menu_shader(const char *path)
|
||||
{
|
||||
if (menu_cg_program)
|
||||
free(menu_cg_program);
|
||||
|
||||
free(menu_cg_program);
|
||||
menu_cg_program = strdup(path);
|
||||
}
|
||||
|
||||
@ -1321,22 +968,6 @@ void gl_cg_invalidate_context(void)
|
||||
cgCtx = NULL;
|
||||
}
|
||||
|
||||
unsigned gl_cg_get_lut_info(struct gl_cg_lut_info *info, unsigned elems)
|
||||
{
|
||||
if (!cg_active)
|
||||
return 0;
|
||||
|
||||
elems = elems > lut_textures_num ? lut_textures_num : elems;
|
||||
|
||||
for (unsigned i = 0; i < elems; i++)
|
||||
{
|
||||
strlcpy(info[i].id, lut_textures_uniform[i], sizeof(info[i].id));
|
||||
info[i].tex = lut_textures[i];
|
||||
}
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
const gl_shader_backend_t gl_cg_backend = {
|
||||
gl_cg_init,
|
||||
gl_cg_deinit,
|
||||
|
@ -38,7 +38,7 @@ void gl_cg_use(unsigned index);
|
||||
unsigned gl_cg_num(void);
|
||||
|
||||
bool gl_cg_filter_type(unsigned index, bool *smooth);
|
||||
void gl_cg_shader_scale(unsigned index, struct gl_fbo_scale *scale);
|
||||
void gl_cg_shader_scale(unsigned index, struct gfx_fbo_scale *scale);
|
||||
|
||||
bool gl_cg_set_mvp(const math_matrix *mat);
|
||||
bool gl_cg_set_coords(const struct gl_coords *coords);
|
||||
@ -54,15 +54,6 @@ void gl_cg_set_compiler_args(const char **argv);
|
||||
bool gl_cg_load_shader(unsigned index, const char *path);
|
||||
|
||||
void gl_cg_invalidate_context(void); // Call when resetting GL context on PS3.
|
||||
|
||||
struct gl_cg_lut_info
|
||||
{
|
||||
char id[64];
|
||||
GLuint tex;
|
||||
};
|
||||
|
||||
unsigned gl_cg_get_lut_info(struct gl_cg_lut_info *info, unsigned elems);
|
||||
|
||||
extern const gl_shader_backend_t gl_cg_backend;
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../boolean.h"
|
||||
#include "gl_common.h"
|
||||
#include "gfx_context.h"
|
||||
#include "shader_parse.h"
|
||||
#include "math/matrix.h"
|
||||
|
||||
struct gl_shader_backend
|
||||
@ -36,7 +37,7 @@ struct gl_shader_backend
|
||||
void (*use)(unsigned index);
|
||||
unsigned (*num_shaders)(void);
|
||||
bool (*filter_type)(unsigned index, bool *smooth);
|
||||
void (*shader_scale)(unsigned index, struct gl_fbo_scale *scale);
|
||||
void (*shader_scale)(unsigned index, struct gfx_fbo_scale *scale);
|
||||
bool (*set_coords)(const struct gl_coords *coords);
|
||||
bool (*set_mvp)(const math_matrix *mat);
|
||||
|
||||
|
@ -143,7 +143,7 @@ static bool glsl_enable;
|
||||
static bool glsl_modern;
|
||||
static GLuint gl_program[RARCH_GLSL_MAX_SHADERS];
|
||||
static enum filter_type gl_filter_type[RARCH_GLSL_MAX_SHADERS];
|
||||
static struct gl_fbo_scale gl_scale[RARCH_GLSL_MAX_SHADERS];
|
||||
static struct gfx_fbo_scale gl_scale[RARCH_GLSL_MAX_SHADERS];
|
||||
static unsigned gl_num_programs;
|
||||
static unsigned active_index;
|
||||
|
||||
@ -174,8 +174,8 @@ struct shader_program
|
||||
float scale_y;
|
||||
unsigned abs_x;
|
||||
unsigned abs_y;
|
||||
enum gl_scale_type type_x;
|
||||
enum gl_scale_type type_y;
|
||||
enum gfx_scale_type type_x;
|
||||
enum gfx_scale_type type_y;
|
||||
unsigned frame_count_mod;
|
||||
|
||||
bool valid_scale;
|
||||
@ -1591,7 +1591,7 @@ bool gl_glsl_filter_type(unsigned index, bool *smooth)
|
||||
}
|
||||
}
|
||||
|
||||
void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale)
|
||||
void gl_glsl_shader_scale(unsigned index, struct gfx_fbo_scale *scale)
|
||||
{
|
||||
if (glsl_enable)
|
||||
*scale = gl_scale[index];
|
||||
|
@ -39,7 +39,7 @@ void gl_glsl_use(unsigned index);
|
||||
unsigned gl_glsl_num(void);
|
||||
|
||||
bool gl_glsl_filter_type(unsigned index, bool *smooth);
|
||||
void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale);
|
||||
void gl_glsl_shader_scale(unsigned index, struct gfx_fbo_scale *scale);
|
||||
|
||||
bool gl_glsl_set_coords(const struct gl_coords *coords);
|
||||
bool gl_glsl_set_mvp(const math_matrix *mat);
|
||||
|
513
gfx/shader_parse.c
Normal file
513
gfx/shader_parse.c
Normal file
@ -0,0 +1,513 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "shader_parse.h"
|
||||
#include "../compat/posix_string.h"
|
||||
#include "../msvc/msvc_compat.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define print_buf(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
|
||||
|
||||
static bool shader_parse_pass(config_file_t *conf, struct gfx_shader_pass *pass, unsigned i)
|
||||
{
|
||||
// Source
|
||||
char shader_name[64];
|
||||
print_buf(shader_name, "shader%u", i);
|
||||
if (!config_get_path(conf, shader_name, pass->source.cg, sizeof(pass->source.cg)))
|
||||
{
|
||||
RARCH_ERR("Couldn't parse shader source (%s).\n", shader_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Smooth
|
||||
char filter_name_buf[64];
|
||||
print_buf(filter_name_buf, "filter_linear%u", i);
|
||||
|
||||
bool smooth = false;
|
||||
if (config_get_bool(conf, filter_name_buf, &smooth))
|
||||
pass->filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
else
|
||||
pass->filter = RARCH_FILTER_UNSPEC;
|
||||
|
||||
// Frame count mod
|
||||
char frame_count_mod[64] = {0};
|
||||
char frame_count_mod_buf[64];
|
||||
print_buf(frame_count_mod_buf, "frame_count_mod%u", i);
|
||||
if (config_get_array(conf, frame_count_mod_buf, frame_count_mod, sizeof(frame_count_mod)))
|
||||
pass->frame_count_mod = strtoul(frame_count_mod, NULL, 0);
|
||||
|
||||
// Scale
|
||||
struct gfx_fbo_scale *scale = &pass->fbo;
|
||||
char scale_type[64] = {0};
|
||||
char scale_type_x[64] = {0};
|
||||
char scale_type_y[64] = {0};
|
||||
char scale_name_buf[64];
|
||||
print_buf(scale_name_buf, "scale_type%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type, sizeof(scale_type));
|
||||
|
||||
print_buf(scale_name_buf, "scale_type_x%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type_x, sizeof(scale_type_x));
|
||||
|
||||
print_buf(scale_name_buf, "scale_type_y%u", i);
|
||||
config_get_array(conf, scale_name_buf, scale_type_y, sizeof(scale_type_y));
|
||||
|
||||
if (!*scale_type && !*scale_type_x && !*scale_type_y)
|
||||
return true;
|
||||
|
||||
if (*scale_type)
|
||||
{
|
||||
strlcpy(scale_type_x, scale_type, sizeof(scale_type_x));
|
||||
strlcpy(scale_type_y, scale_type, sizeof(scale_type_y));
|
||||
}
|
||||
|
||||
char attr_name_buf[64];
|
||||
float fattr = 0.0f;
|
||||
int iattr = 0;
|
||||
|
||||
scale->valid = true;
|
||||
scale->type_x = RARCH_SCALE_INPUT;
|
||||
scale->type_y = RARCH_SCALE_INPUT;
|
||||
scale->scale_x = 1.0;
|
||||
scale->scale_y = 1.0;
|
||||
|
||||
char fp_fbo_buf[64];
|
||||
print_buf(fp_fbo_buf, "float_framebuffer%u", i);
|
||||
config_get_bool(conf, fp_fbo_buf, &scale->fp_fbo);
|
||||
|
||||
if (*scale_type_x)
|
||||
{
|
||||
if (strcmp(scale_type_x, "source") == 0)
|
||||
scale->type_x = RARCH_SCALE_INPUT;
|
||||
else if (strcmp(scale_type_x, "viewport") == 0)
|
||||
scale->type_x = RARCH_SCALE_VIEWPORT;
|
||||
else if (strcmp(scale_type_x, "absolute") == 0)
|
||||
scale->type_x = RARCH_SCALE_ABSOLUTE;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid attribute.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (*scale_type_y)
|
||||
{
|
||||
if (strcmp(scale_type_y, "source") == 0)
|
||||
scale->type_y = RARCH_SCALE_INPUT;
|
||||
else if (strcmp(scale_type_y, "viewport") == 0)
|
||||
scale->type_y = RARCH_SCALE_VIEWPORT;
|
||||
else if (strcmp(scale_type_y, "absolute") == 0)
|
||||
scale->type_y = RARCH_SCALE_ABSOLUTE;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid attribute.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale->type_x == RARCH_SCALE_ABSOLUTE)
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_x = iattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_x%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_x = iattr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_x = fattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_x%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_x = fattr;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale->type_y == RARCH_SCALE_ABSOLUTE)
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_y = iattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_y%u", i);
|
||||
if (config_get_int(conf, attr_name_buf, &iattr))
|
||||
scale->abs_y = iattr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_y = fattr;
|
||||
else
|
||||
{
|
||||
print_buf(attr_name_buf, "scale_y%u", i);
|
||||
if (config_get_float(conf, attr_name_buf, &fattr))
|
||||
scale->scale_y = fattr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool shader_parse_textures(config_file_t *conf, struct gfx_shader *shader)
|
||||
{
|
||||
char textures[1024];
|
||||
if (!config_get_array(conf, "textures", textures, sizeof(textures)))
|
||||
return true;
|
||||
|
||||
char *save;
|
||||
for (const char *id = strtok_r(textures, ";", &save);
|
||||
id && shader->luts < GFX_MAX_TEXTURES;
|
||||
shader->luts++, id = strtok_r(NULL, ";", &save))
|
||||
{
|
||||
if (!config_get_array(conf, id, shader->lut[shader->luts].path, sizeof(shader->lut[shader->luts].path)))
|
||||
{
|
||||
RARCH_ERR("Cannot find path to texture \"%s\" ...\n", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(shader->lut[shader->luts].id, id, sizeof(shader->lut[shader->luts].id));
|
||||
|
||||
char id_filter[64];
|
||||
print_buf(id_filter, "%s_linear", id);
|
||||
|
||||
bool smooth = false;
|
||||
if (config_get_bool(conf, id_filter, &smooth))
|
||||
shader->lut[shader->luts].filter = smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
||||
else
|
||||
shader->lut[shader->luts].filter = RARCH_FILTER_UNSPEC;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool shader_parse_imports(config_file_t *conf, struct gfx_shader *shader)
|
||||
{
|
||||
char imports[1024];
|
||||
if (!config_get_array(conf, "imports", imports, sizeof(imports)))
|
||||
return true;
|
||||
|
||||
char *save;
|
||||
const char *id = strtok_r(imports, ";", &save);
|
||||
for (const char *id = strtok_r(imports, ";", &save);
|
||||
id && shader->variables < GFX_MAX_VARIABLES;
|
||||
shader->variables++, id = strtok_r(NULL, ";", &save))
|
||||
{
|
||||
struct state_tracker_uniform_info *var = &shader->variable[shader->variables];
|
||||
|
||||
strlcpy(var->id, id, sizeof(var->id));
|
||||
|
||||
char semantic_buf[64];
|
||||
char wram_buf[64];
|
||||
char input_slot_buf[64];
|
||||
char mask_buf[64];
|
||||
char equal_buf[64];
|
||||
|
||||
print_buf(semantic_buf, "%s_semantic", id);
|
||||
print_buf(wram_buf, "%s_wram", id);
|
||||
print_buf(input_slot_buf, "%s_input_slot", id);
|
||||
print_buf(mask_buf, "%s_mask", id);
|
||||
print_buf(equal_buf, "%s_equal", id);
|
||||
|
||||
char semantic[64];
|
||||
if (!config_get_array(conf, semantic_buf, semantic, sizeof(semantic)))
|
||||
{
|
||||
RARCH_ERR("No semantic for import variable.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
enum state_ram_type ram_type = RARCH_STATE_NONE;
|
||||
|
||||
if (strcmp(semantic, "capture") == 0)
|
||||
var->type = RARCH_STATE_CAPTURE;
|
||||
else if (strcmp(semantic, "transition") == 0)
|
||||
var->type = RARCH_STATE_TRANSITION;
|
||||
else if (strcmp(semantic, "transition_count") == 0)
|
||||
var->type = RARCH_STATE_TRANSITION_COUNT;
|
||||
else if (strcmp(semantic, "capture_previous") == 0)
|
||||
var->type = RARCH_STATE_CAPTURE_PREV;
|
||||
else if (strcmp(semantic, "transition_previous") == 0)
|
||||
var->type = RARCH_STATE_TRANSITION_PREV;
|
||||
else if (strcmp(semantic, "python") == 0)
|
||||
var->type = RARCH_STATE_PYTHON;
|
||||
else
|
||||
{
|
||||
RARCH_ERR("Invalid semantic.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned addr = 0, mask = 0, equal = 0;
|
||||
if (var->type != RARCH_STATE_PYTHON)
|
||||
{
|
||||
unsigned input_slot = 0;
|
||||
if (config_get_uint(conf, input_slot_buf, &input_slot))
|
||||
{
|
||||
switch (input_slot)
|
||||
{
|
||||
case 1:
|
||||
var->ram_type = RARCH_STATE_INPUT_SLOT1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
var->ram_type = RARCH_STATE_INPUT_SLOT2;
|
||||
break;
|
||||
|
||||
default:
|
||||
RARCH_ERR("Invalid input slot for import.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (config_get_hex(conf, wram_buf, &addr))
|
||||
{
|
||||
var->ram_type = RARCH_STATE_WRAM;
|
||||
var->addr = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR("No address assigned to semantic.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config_get_hex(conf, mask_buf, &mask))
|
||||
var->mask = mask;
|
||||
if (config_get_hex(conf, equal_buf, &equal))
|
||||
var->equal = equal;
|
||||
}
|
||||
|
||||
config_get_path(conf, "import_script", shader->script_path, sizeof(shader->script_path));
|
||||
config_get_array(conf, "import_script_class", shader->script_class, sizeof(shader->script_class));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gfx_shader_read_conf_cgp(config_file_t *conf, struct gfx_shader *shader)
|
||||
{
|
||||
memset(shader, 0, sizeof(*shader));
|
||||
|
||||
unsigned shaders = 0;
|
||||
if (!config_get_uint(conf, "shaders", &shaders))
|
||||
{
|
||||
RARCH_ERR("Cannot find \"shaders\" param.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shaders)
|
||||
{
|
||||
RARCH_ERR("Need to define at least 1 shader.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
shader->passes = min(shaders, GFX_MAX_SHADERS);
|
||||
for (unsigned i = 0; i < shader->passes; i++)
|
||||
{
|
||||
if (!shader_parse_pass(conf, &shader->pass[i], i))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shader_parse_textures(conf, shader))
|
||||
return false;
|
||||
|
||||
if (!shader_parse_imports(conf, shader))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *scale_type_to_str(enum gfx_scale_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RARCH_SCALE_INPUT:
|
||||
return "source";
|
||||
case RARCH_SCALE_VIEWPORT:
|
||||
return "viewport";
|
||||
case RARCH_SCALE_ABSOLUTE:
|
||||
return "absolute";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_write_scale_dim(config_file_t *conf, const char *dim,
|
||||
enum gfx_scale_type type, float scale, unsigned abs, unsigned i)
|
||||
{
|
||||
char key[64];
|
||||
print_buf(key, "scale_type_%s%u", dim, i);
|
||||
config_set_string(conf, key, scale_type_to_str(type));
|
||||
|
||||
print_buf(key, "scale_%s%u", dim, i);
|
||||
if (type == RARCH_SCALE_ABSOLUTE)
|
||||
config_set_int(conf, key, abs);
|
||||
else
|
||||
config_set_float(conf, key, scale);
|
||||
}
|
||||
|
||||
static void shader_write_fbo(config_file_t *conf, const struct gfx_fbo_scale *fbo, unsigned i)
|
||||
{
|
||||
char key[64];
|
||||
print_buf(key, "float_framebuffer%u", i);
|
||||
config_set_bool(conf, key, fbo->fp_fbo);
|
||||
|
||||
if (!fbo->valid)
|
||||
return;
|
||||
|
||||
shader_write_scale_dim(conf, "x", fbo->type_x, fbo->scale_x, fbo->abs_x, i);
|
||||
shader_write_scale_dim(conf, "y", fbo->type_y, fbo->scale_y, fbo->abs_y, i);
|
||||
}
|
||||
|
||||
static const char *import_semantic_to_string(enum state_tracker_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RARCH_STATE_CAPTURE:
|
||||
return "capture";
|
||||
case RARCH_STATE_TRANSITION:
|
||||
return "transition";
|
||||
case RARCH_STATE_TRANSITION_COUNT:
|
||||
return "transition_count";
|
||||
case RARCH_STATE_CAPTURE_PREV:
|
||||
return "capture_previous";
|
||||
case RARCH_STATE_TRANSITION_PREV:
|
||||
return "transition_previous";
|
||||
case RARCH_STATE_PYTHON:
|
||||
return "python";
|
||||
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_write_variable(config_file_t *conf, const struct state_tracker_uniform_info *info)
|
||||
{
|
||||
const char *id = info->id;
|
||||
|
||||
char semantic_buf[64];
|
||||
char wram_buf[64];
|
||||
char input_slot_buf[64];
|
||||
char mask_buf[64];
|
||||
char equal_buf[64];
|
||||
|
||||
print_buf(semantic_buf, "%s_semantic", id);
|
||||
print_buf(wram_buf, "%s_wram", id);
|
||||
print_buf(input_slot_buf, "%s_input_slot", id);
|
||||
print_buf(mask_buf, "%s_mask", id);
|
||||
print_buf(equal_buf, "%s_equal", id);
|
||||
|
||||
config_set_string(conf, semantic_buf, import_semantic_to_string(info->type));
|
||||
config_set_hex(conf, mask_buf, info->mask);
|
||||
config_set_hex(conf, equal_buf, info->equal);
|
||||
|
||||
switch (info->ram_type)
|
||||
{
|
||||
case RARCH_STATE_INPUT_SLOT1:
|
||||
config_set_int(conf, input_slot_buf, 1);
|
||||
break;
|
||||
|
||||
case RARCH_STATE_INPUT_SLOT2:
|
||||
config_set_int(conf, input_slot_buf, 2);
|
||||
break;
|
||||
|
||||
case RARCH_STATE_WRAM:
|
||||
config_set_hex(conf, wram_buf, info->addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_shader_write_conf_cgp(config_file_t *conf, const struct gfx_shader *shader)
|
||||
{
|
||||
config_set_int(conf, "shaders", shader->passes);
|
||||
for (unsigned i = 0; i < shader->passes; i++)
|
||||
{
|
||||
const struct gfx_shader_pass *pass = &shader->pass[i];
|
||||
|
||||
char key[64];
|
||||
print_buf(key, "shader%u", i);
|
||||
config_set_string(conf, key, pass->source.cg);
|
||||
|
||||
if (pass->filter != RARCH_FILTER_UNSPEC)
|
||||
{
|
||||
print_buf(key, "filter_linear%u", i);
|
||||
config_set_bool(conf, key, pass->filter == RARCH_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
if (pass->frame_count_mod)
|
||||
{
|
||||
print_buf(key, "frame_count_mod%u", i);
|
||||
config_set_int(conf, key, pass->frame_count_mod);
|
||||
}
|
||||
|
||||
shader_write_fbo(conf, &pass->fbo, i);
|
||||
}
|
||||
|
||||
if (shader->luts)
|
||||
{
|
||||
char textures[4096] = {0};
|
||||
strlcpy(textures, shader->lut[0].id, sizeof(textures));
|
||||
for (unsigned i = 1; i < shader->luts; i++)
|
||||
{
|
||||
// O(n^2), but number of textures is very limited.
|
||||
strlcat(textures, ";", sizeof(textures));
|
||||
strlcat(textures, shader->lut[i].id, sizeof(textures));
|
||||
}
|
||||
|
||||
config_set_string(conf, "textures", textures);
|
||||
|
||||
for (unsigned i = 0; i < shader->luts; i++)
|
||||
{
|
||||
char key[64];
|
||||
|
||||
if (shader->lut[i].filter != RARCH_FILTER_UNSPEC)
|
||||
{
|
||||
print_buf(key, "%s_linear", shader->lut[i].id);
|
||||
config_set_bool(conf, key, shader->lut[i].filter != RARCH_FILTER_LINEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*shader->script_path)
|
||||
config_set_string(conf, "import_script", shader->script_path);
|
||||
if (*shader->script_class)
|
||||
config_set_string(conf, "import_script_class", shader->script_class);
|
||||
|
||||
if (shader->variables)
|
||||
{
|
||||
char variables[4096] = {0};
|
||||
strlcpy(variables, shader->variable[0].id, sizeof(variables));
|
||||
for (unsigned i = 1; i < shader->variables; i++)
|
||||
{
|
||||
strlcat(variables, ";", sizeof(variables));
|
||||
strlcat(variables, shader->variable[i].id, sizeof(variables));
|
||||
}
|
||||
|
||||
config_set_string(conf, "imports", variables);
|
||||
|
||||
for (unsigned i = 0; i < shader->variables; i++)
|
||||
shader_write_variable(conf, &shader->variable[i]);
|
||||
}
|
||||
}
|
||||
|
98
gfx/shader_parse.h
Normal file
98
gfx/shader_parse.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SHADER_PARSE_H
|
||||
#define SHADER_PARSE_H
|
||||
|
||||
#include "boolean.h"
|
||||
#include "../conf/config_file.h"
|
||||
#include "state_tracker.h"
|
||||
#include "../general.h"
|
||||
|
||||
#define GFX_MAX_SHADERS 16
|
||||
#define GFX_MAX_TEXTURES 8
|
||||
#define GFX_MAX_VARIABLES 64
|
||||
|
||||
enum gfx_scale_type
|
||||
{
|
||||
RARCH_SCALE_INPUT = 0,
|
||||
RARCH_SCALE_ABSOLUTE,
|
||||
RARCH_SCALE_VIEWPORT
|
||||
};
|
||||
|
||||
enum gfx_filter_type
|
||||
{
|
||||
RARCH_FILTER_UNSPEC = 0,
|
||||
RARCH_FILTER_LINEAR,
|
||||
RARCH_FILTER_NEAREST,
|
||||
};
|
||||
|
||||
struct gfx_fbo_scale
|
||||
{
|
||||
bool valid;
|
||||
enum gfx_scale_type type_x;
|
||||
enum gfx_scale_type type_y;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
unsigned abs_x;
|
||||
unsigned abs_y;
|
||||
bool fp_fbo;
|
||||
};
|
||||
|
||||
struct gfx_shader_pass
|
||||
{
|
||||
union
|
||||
{
|
||||
char cg[PATH_MAX];
|
||||
struct
|
||||
{
|
||||
char vertex[PATH_MAX];
|
||||
char fragment[PATH_MAX];
|
||||
} glsl;
|
||||
} source;
|
||||
|
||||
struct gfx_fbo_scale fbo;
|
||||
enum gfx_filter_type filter;
|
||||
unsigned frame_count_mod;
|
||||
};
|
||||
|
||||
struct gfx_shader_lut
|
||||
{
|
||||
char id[64];
|
||||
char path[PATH_MAX];
|
||||
enum gfx_filter_type filter;
|
||||
};
|
||||
|
||||
// This is pretty big, shouldn't be put on the stack.
|
||||
// Avoid lots of allocation for convenience.
|
||||
struct gfx_shader
|
||||
{
|
||||
unsigned passes;
|
||||
struct gfx_shader_pass pass[GFX_MAX_SHADERS];
|
||||
|
||||
unsigned luts;
|
||||
struct gfx_shader_lut lut[GFX_MAX_TEXTURES];
|
||||
|
||||
unsigned variables;
|
||||
struct state_tracker_uniform_info variable[GFX_MAX_VARIABLES];
|
||||
char script_path[PATH_MAX];
|
||||
char script_class[512];
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
@ -29,14 +29,12 @@ extern "C" {
|
||||
|
||||
enum state_tracker_type
|
||||
{
|
||||
#ifdef HAVE_PYTHON
|
||||
RARCH_STATE_PYTHON,
|
||||
#endif
|
||||
RARCH_STATE_CAPTURE,
|
||||
RARCH_STATE_CAPTURE = 0,
|
||||
RARCH_STATE_CAPTURE_PREV,
|
||||
RARCH_STATE_TRANSITION,
|
||||
RARCH_STATE_TRANSITION_COUNT,
|
||||
RARCH_STATE_TRANSITION_PREV
|
||||
RARCH_STATE_TRANSITION_PREV,
|
||||
RARCH_STATE_PYTHON
|
||||
};
|
||||
|
||||
enum state_ram_type
|
||||
|
@ -109,6 +109,10 @@ VIDEO CONTEXT
|
||||
VIDEO SHADERS
|
||||
============================================================ */
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_HLSL)
|
||||
#include "../gfx/shader_parse.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CG
|
||||
#include "../gfx/shader_cg.c"
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user