diff --git a/Makefile b/Makefile
index 9304305df5..93411aa690 100644
--- a/Makefile
+++ b/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 \
diff --git a/Makefile.win b/Makefile.win
index 8ac9a1b3b7..71a73bf00c 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -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 \
diff --git a/conf/config_file.c b/conf/config_file.c
index 840016fd44..8fcbd92ceb 100644
--- a/conf/config_file.c
+++ b/conf/config_file.c
@@ -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];
diff --git a/conf/config_file.h b/conf/config_file.h
index 3b462ad384..8ae7554181 100644
--- a/conf/config_file.h
+++ b/conf/config_file.h
@@ -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);
diff --git a/gfx/gl.c b/gfx/gl.c
index b124c41686..fe1e08d79f 100644
--- a/gfx/gl.c
+++ b/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);
diff --git a/gfx/gl_common.h b/gfx/gl_common.h
index 92b5afa37c..1ef857c6d6 100644
--- a/gfx/gl_common.h
+++ b/gfx/gl_common.h
@@ -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;
diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c
index a338431d60..7fd6501b28 100644
--- a/gfx/shader_cg.c
+++ b/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,
diff --git a/gfx/shader_cg.h b/gfx/shader_cg.h
index a4fd59282c..853d5fe6c1 100644
--- a/gfx/shader_cg.h
+++ b/gfx/shader_cg.h
@@ -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
diff --git a/gfx/shader_common.h b/gfx/shader_common.h
index 582f84ac2f..571957a4c0 100644
--- a/gfx/shader_common.h
+++ b/gfx/shader_common.h
@@ -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);
diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c
index e0aeacd564..588fefee73 100644
--- a/gfx/shader_glsl.c
+++ b/gfx/shader_glsl.c
@@ -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];
diff --git a/gfx/shader_glsl.h b/gfx/shader_glsl.h
index 3ab47447a6..ec2e26cd4b 100644
--- a/gfx/shader_glsl.h
+++ b/gfx/shader_glsl.h
@@ -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);
diff --git a/gfx/shader_parse.c b/gfx/shader_parse.c
new file mode 100644
index 0000000000..a1a7c94b02
--- /dev/null
+++ b/gfx/shader_parse.c
@@ -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 .
+ */
+
+#include "shader_parse.h"
+#include "../compat/posix_string.h"
+#include "../msvc/msvc_compat.h"
+#include
+#include
+
+#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]);
+ }
+}
+
diff --git a/gfx/shader_parse.h b/gfx/shader_parse.h
new file mode 100644
index 0000000000..a3bbdca8a9
--- /dev/null
+++ b/gfx/shader_parse.h
@@ -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 .
+ */
+
+#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
+
diff --git a/gfx/state_tracker.h b/gfx/state_tracker.h
index f3b1c9acb8..fe3029e656 100644
--- a/gfx/state_tracker.h
+++ b/gfx/state_tracker.h
@@ -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
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 5a49b09487..f8f4b7f89f 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -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