diff --git a/gfx/gl.c b/gfx/gl.c index aeec6b9056..67ee84d7df 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -193,7 +193,7 @@ static bool gl_shader_init(void) return true; } -static inline void gl_shader_use(unsigned index) +static void gl_shader_use(unsigned index) { #ifdef HAVE_CG gl_cg_use(index); @@ -204,7 +204,7 @@ static inline void gl_shader_use(unsigned index) #endif } -static inline void gl_shader_deinit(void) +static void gl_shader_deinit(void) { #ifdef HAVE_CG gl_cg_deinit(); @@ -215,7 +215,7 @@ static inline void gl_shader_deinit(void) #endif } -static inline void gl_shader_set_proj_matrix(void) +static void gl_shader_set_proj_matrix(void) { #ifdef HAVE_CG gl_cg_set_proj_matrix(); @@ -226,7 +226,7 @@ static inline void gl_shader_set_proj_matrix(void) #endif } -static inline void gl_shader_set_params(unsigned width, unsigned height, +static void gl_shader_set_params(unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, unsigned out_width, unsigned out_height) { @@ -239,7 +239,7 @@ static inline void gl_shader_set_params(unsigned width, unsigned height, #endif } -static inline unsigned gl_shader_num(void) +static unsigned gl_shader_num(void) { unsigned num = 0; #ifdef HAVE_CG @@ -257,7 +257,7 @@ static inline unsigned gl_shader_num(void) return num; } -static inline bool gl_shader_filter_type(unsigned index, bool *smooth) +static bool gl_shader_filter_type(unsigned index, bool *smooth) { bool valid = false; #ifdef HAVE_CG @@ -273,20 +273,18 @@ static inline bool gl_shader_filter_type(unsigned index, bool *smooth) return valid; } -static inline bool gl_shader_rect(unsigned index, struct gl_fbo_rect *rect) +static void gl_shader_scale(unsigned index, struct gl_fbo_scale *scale) { - bool valid = false; + scale->valid = false; #ifdef HAVE_CG - if (!valid) - valid = gl_cg_shader_rect(index, rect); + if (!scale->valid) + gl_cg_shader_scale(index, scale); #endif #ifdef HAVE_XML - if (!valid) - valid = gl_glsl_shader_rect(index, rect); + if (!scale->valid) + gl_glsl_shader_scale(index, scale); #endif - - return valid; } /////////////////// diff --git a/gfx/gl_common.h b/gfx/gl_common.h index c0dcce57c6..722416fcc9 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -71,8 +71,13 @@ struct gl_fbo_rect unsigned height; unsigned tex_width; unsigned tex_height; +}; - GLfloat texcoord[8]; +struct gl_fbo_scale +{ + float scale_x; + float scale_y; + bool valid; }; #endif diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index a00053012a..c2d0858fdf 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -209,10 +209,9 @@ bool gl_cg_filter_type(unsigned index, bool *smooth) return false; } -bool gl_cg_shader_rect(unsigned index, struct gl_fbo_rect *rect) +void gl_cg_shader_scale(unsigned index, struct gl_fbo_scale *scale) { (void)index; - (void)rect; // We don't really care since .cg doesn't have those kinds of semantics by itself ... - return false; + scale->valid = false; } diff --git a/gfx/shader_cg.h b/gfx/shader_cg.h index 8dd24d6e04..3e62d6d791 100644 --- a/gfx/shader_cg.h +++ b/gfx/shader_cg.h @@ -37,6 +37,6 @@ void gl_cg_use(unsigned index); unsigned gl_cg_num(void); bool gl_cg_filter_type(unsigned index, bool *smooth); -bool gl_cg_shader_rect(unsigned index, struct gl_fbo_rect *rect); +void gl_cg_shader_scale(unsigned index, struct gl_fbo_scale *scale); #endif diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 8fd666bdd9..8f0ffabdda 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -87,6 +87,7 @@ enum filter_type static bool glsl_enable = false; static GLuint gl_program[MAX_PROGRAMS] = {0}; static enum filter_type gl_filter_type[MAX_PROGRAMS] = {SSNES_GL_NOFORCE}; +static struct gl_fbo_scale gl_scale[MAX_PROGRAMS]; static unsigned gl_num_programs = 0; static unsigned active_index = 0; @@ -95,8 +96,71 @@ struct shader_program char *vertex; char *fragment; enum filter_type filter; + + float scale_x; + float scale_y; + bool valid_scale; }; +static void get_xml_attrs(struct shader_program *prog, xmlNodePtr ptr) +{ + prog->scale_x = 1.0; + prog->scale_y = 1.0; + prog->valid_scale = false; + + // Check if shader forces a certain texture filtering. + xmlChar *attr = xmlGetProp(ptr, (const xmlChar*)"filter"); + if (attr) + { + if (strcmp((const char*)attr, "nearest") == 0) + { + prog->filter = SSNES_GL_NEAREST; + SSNES_LOG("XML: Shader forces GL_NEAREST.\n"); + } + else if (strcmp((const char*)attr, "linear") == 0) + { + prog->filter = SSNES_GL_LINEAR; + SSNES_LOG("XML: Shader forces GL_LINEAR.\n"); + } + else + SSNES_WARN("XML: Invalid property for filter.\n"); + + xmlFree(attr); + } + else + prog->filter = SSNES_GL_NOFORCE; + + xmlChar *attr_scale = xmlGetProp(ptr, (const xmlChar*)"scale"); + xmlChar *attr_scale_x = xmlGetProp(ptr, (const xmlChar*)"scale_x"); + xmlChar *attr_scale_y = xmlGetProp(ptr, (const xmlChar*)"scale_y"); + if (attr_scale) + { + float scale = strtod((const char*)attr_scale, NULL); + prog->scale_x = scale; + prog->scale_y = scale; + prog->valid_scale = true; + } + else if (attr_scale_x) + { + float scale = strtod((const char*)attr_scale, NULL); + prog->scale_x = scale; + prog->valid_scale = true; + } + else if (attr_scale_y) + { + float scale = strtod((const char*)attr_scale, NULL); + prog->scale_y = scale; + prog->valid_scale = true; + } + + if (attr_scale) + xmlFree(attr_scale); + if (attr_scale_x) + xmlFree(attr_scale_x); + if (attr_scale_y) + xmlFree(attr_scale_y); +} + static unsigned get_xml_shaders(const char *path, struct shader_program *prog, size_t size) { LIBXML_TEST_VERSION; @@ -129,8 +193,15 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s if (cur->type == XML_ELEMENT_NODE && strcmp((const char*)cur->name, "shader") == 0) { xmlChar *attr; - if ((attr = xmlGetProp(cur, (const xmlChar*)"language")) && strcmp((const char*)attr, "GLSL") == 0) + attr = xmlGetProp(cur, (const xmlChar*)"language"); + if (attr && strcmp((const char*)attr, "GLSL") == 0) + { + xmlFree(attr); break; + } + + if (attr) + xmlFree(attr); } } @@ -155,35 +226,16 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s if (prog[num].vertex) { SSNES_ERR("Cannot have more than one vertex shader in a program.\n"); + xmlFree(content); goto error; } - prog[num].vertex = strdup((const char*)content); + prog[num].vertex = (char*)content; } else if (strcmp((const char*)cur->name, "fragment") == 0) { - prog[num].fragment = strdup((const char*)content); - - // Check if shader forces a certain texture filtering. - xmlChar *attr = xmlGetProp(cur, (const xmlChar*)"filter"); - if (attr) - { - if (strcmp((const char*)attr, "nearest") == 0) - { - prog[num].filter = SSNES_GL_NEAREST; - SSNES_LOG("XML: Shader forces GL_NEAREST.\n"); - } - else if (strcmp((const char*)attr, "linear") == 0) - { - prog[num].filter = SSNES_GL_LINEAR; - SSNES_LOG("XML: Shader forces GL_LINEAR.\n"); - } - else - SSNES_WARN("XML: Invalid property for filter.\n"); - } - else - prog[num].filter = SSNES_GL_NOFORCE; - + prog[num].fragment = (char*)content; + get_xml_attrs(&prog[num], cur); num++; } } @@ -328,7 +380,12 @@ bool gl_glsl_init(const char *path) } for (unsigned i = 0; i < num_progs; i++) + { gl_filter_type[i + 1] = progs[i].filter; + gl_scale[i + 1].scale_x = progs[i].scale_x; + gl_scale[i + 1].scale_y = progs[i].scale_y; + gl_scale[i + 1].valid = progs[i].valid_scale; + } compile_programs(&gl_program[1], progs, num_progs); @@ -421,9 +478,10 @@ bool gl_glsl_filter_type(unsigned index, bool *smooth) } } -bool gl_glsl_shader_rect(unsigned index, struct gl_fbo_rect *rect) +void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale) { - (void)index; - (void)rect; - return false; + if (glsl_enable) + *scale = gl_scale[index]; + else + scale->valid = false; } diff --git a/gfx/shader_glsl.h b/gfx/shader_glsl.h index 78301f8b76..d80a0c9660 100644 --- a/gfx/shader_glsl.h +++ b/gfx/shader_glsl.h @@ -36,6 +36,6 @@ void gl_glsl_use(unsigned index); unsigned gl_glsl_num(void); bool gl_glsl_filter_type(unsigned index, bool *smooth); -bool gl_glsl_shader_rect(unsigned index, struct gl_fbo_rect *rect); +void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale); #endif