From e649db253ccbdaabc232ce8c9894ccc9092c7feb Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 6 Apr 2013 11:30:56 +0200 Subject: [PATCH] Reintroduce CGP refactor. Fix several issues that caused crashes. --- Makefile | 1 + Makefile.win | 1 + conf/config_file.c | 7 + conf/config_file.h | 1 + gfx/gl.c | 4 +- gfx/gl_common.h | 22 +- gfx/shader_cg.c | 555 ++++++++------------------------------------ gfx/shader_cg.h | 11 +- gfx/shader_common.h | 3 +- gfx/shader_glsl.c | 8 +- gfx/shader_glsl.h | 2 +- gfx/shader_parse.c | 513 ++++++++++++++++++++++++++++++++++++++++ gfx/shader_parse.h | 98 ++++++++ gfx/state_tracker.h | 8 +- griffin/griffin.c | 4 + 15 files changed, 733 insertions(+), 505 deletions(-) create mode 100644 gfx/shader_parse.c create mode 100644 gfx/shader_parse.h diff --git a/Makefile b/Makefile index 9304305df5c..93411aa6908 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 8ac9a1b3b75..71a73bf00c2 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 840016fd44a..8fcbd92cebf 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 3b462ad384a..8ae75541810 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 b124c416868..fe1e08d79f4 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 92b5afa37cd..1ef857c6d64 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 a338431d600..7fd6501b28e 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) - { - 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; + glGenTextures(cg_shader->luts, lut_textures); + for (unsigned i = 0; i < cg_shader->luts; i++) + { 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)) - { - RARCH_ERR("Cannot find \"shaders\" param.\n"); - ret = false; - goto end; - } + if (!cg_shader) + cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg_shader)); + if (!cg_shader) + return false; - if (shaders < 1) + if (!gfx_shader_read_conf_cgp(conf, cg_shader)) { - RARCH_ERR("Need to define at least 1 shader.\n"); - ret = false; - goto end; + RARCH_ERR("Failed to parse CGP file.\n"); + config_file_free(conf); + return false; } - cg_shader_num = shaders; - if (shaders > RARCH_CG_MAX_SHADERS - 3) + config_file_free(conf); + +#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]; - - // Check filter params. - for (int i = 0; i < shaders; 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 - } + prg[cg_shader->passes + 1] = prg[0]; - for (int i = 0; i < shaders; i++) + for (unsigned i = 0; i < cg_shader->passes; 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 a4fd59282cc..853d5fe6c11 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 582f84ac2f6..571957a4c05 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 e0aeacd5648..588fefee739 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 3ab47447a62..ec2e26cd4b0 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 00000000000..a1a7c94b02a --- /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 00000000000..a3bbdca8a9d --- /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 f3b1c9acb80..fe3029e6560 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 5a49b09487a..f8f4b7f89fd 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