diff --git a/gfx/shader/shader_glsl.c b/gfx/shader/shader_glsl.c index b5d834cf32..869a83c93b 100644 --- a/gfx/shader/shader_glsl.c +++ b/gfx/shader/shader_glsl.c @@ -42,23 +42,6 @@ #define PREV_TEXTURES (MAX_TEXTURES - 1) -static struct gfx_shader *glsl_shader; -static bool glsl_core; -static unsigned glsl_major; -static unsigned glsl_minor; - -static bool glsl_enable; -static GLuint gl_program[GFX_MAX_SHADERS]; -static unsigned glsl_active_index; - -static GLuint gl_teximage[GFX_MAX_TEXTURES]; - -static state_tracker_t *gl_state_tracker; - -static GLint gl_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS]; -static unsigned gl_attrib_index; - -static char glsl_alias_define[1024]; /* Cache the VBO. */ struct cache_vbo @@ -71,7 +54,6 @@ struct cache_vbo GLfloat *buffer_secondary; size_t size_secondary; }; -static struct cache_vbo glsl_vbo[GFX_MAX_SHADERS]; struct glsl_attrib { @@ -113,7 +95,6 @@ struct shader_uniforms struct shader_uniforms_frame prev[PREV_TEXTURES]; }; -static struct shader_uniforms gl_uniforms[GFX_MAX_SHADERS]; static const char *glsl_prefixes[] = { "", @@ -223,12 +204,30 @@ static const char *stock_fragment_core_blend = " FragColor = color * texture(Texture, tex_coord);\n" "}"; -static GLint get_uniform(GLuint prog, const char *base) +typedef struct glsl_shader_data +{ + struct gfx_shader *glsl_shader; + struct shader_uniforms gl_uniforms[GFX_MAX_SHADERS]; + struct cache_vbo glsl_vbo[GFX_MAX_SHADERS]; + bool glsl_core; + char glsl_alias_define[1024]; + unsigned glsl_major; + unsigned glsl_minor; + unsigned glsl_active_index; + unsigned gl_attrib_index; + GLuint gl_program[GFX_MAX_SHADERS]; + GLuint gl_teximage[GFX_MAX_TEXTURES]; + GLint gl_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS]; + state_tracker_t *gl_state_tracker; +} glsl_shader_data_t; + +static GLint get_uniform(glsl_shader_data_t *glsl, + GLuint prog, const char *base) { unsigned i; char buf[64]; - snprintf(buf, sizeof(buf), "%s%s", glsl_shader->prefix, base); + snprintf(buf, sizeof(buf), "%s%s", glsl->glsl_shader->prefix, base); GLint loc = glGetUniformLocation(prog, buf); if (loc >= 0) return loc; @@ -244,11 +243,12 @@ static GLint get_uniform(GLuint prog, const char *base) return -1; } -static GLint get_attrib(GLuint prog, const char *base) +static GLint get_attrib(glsl_shader_data_t *glsl, + GLuint prog, const char *base) { unsigned i; char buf[64]; - snprintf(buf, sizeof(buf), "%s%s", glsl_shader->prefix, base); + snprintf(buf, sizeof(buf), "%s%s", glsl->glsl_shader->prefix, base); GLint loc = glGetUniformLocation(prog, buf); if (loc >= 0) return loc; @@ -308,27 +308,36 @@ static void print_linker_log(GLuint obj) free(info_log); } -static bool compile_shader(GLuint shader, +static bool compile_shader(glsl_shader_data_t *glsl, + GLuint shader, const char *define, const char *program) { char version[32] = {0}; - if (glsl_core && !strstr(program, "#version")) + if (glsl->glsl_core && !strstr(program, "#version")) { unsigned version_no = 0; - unsigned gl_ver = glsl_major * 100 + glsl_minor * 10; + unsigned gl_ver = glsl->glsl_major * 100 + glsl->glsl_minor * 10; switch (gl_ver) { - case 300: version_no = 130; break; - case 310: version_no = 140; break; - case 320: version_no = 150; break; - default: version_no = gl_ver; break; + case 300: + version_no = 130; + break; + case 310: + version_no = 140; + break; + case 320: + version_no = 150; + break; + default: + version_no = gl_ver; + break; } snprintf(version, sizeof(version), "#version %u\n", version_no); RARCH_LOG("[GL]: Using GLSL version %u.\n", version_no); } - const char *source[] = { version, define, glsl_alias_define, program }; + const char *source[] = { version, define, glsl->glsl_alias_define, program }; glShaderSource(shader, ARRAY_SIZE(source), source, NULL); glCompileShader(shader); @@ -355,7 +364,8 @@ static bool link_program(GLuint prog) return false; } -static GLuint compile_program(const char *vertex, +static GLuint compile_program(glsl_shader_data_t *glsl, + const char *vertex, const char *fragment, unsigned i) { GLuint prog = glCreateProgram(); @@ -370,6 +380,7 @@ static GLuint compile_program(const char *vertex, RARCH_LOG("Found GLSL vertex shader.\n"); vert = glCreateShader(GL_VERTEX_SHADER); if (!compile_shader( + glsl, vert, "#define VERTEX\n#define PARAMETER_UNIFORM\n", vertex)) { RARCH_ERR("Failed to compile vertex shader #%u\n", i); @@ -383,7 +394,7 @@ static GLuint compile_program(const char *vertex, { RARCH_LOG("Found GLSL fragment shader.\n"); frag = glCreateShader(GL_FRAGMENT_SHADER); - if (!compile_shader(frag, + if (!compile_shader(glsl, frag, "#define FRAGMENT\n#define PARAMETER_UNIFORM\n", fragment)) { RARCH_ERR("Failed to compile fragment shader #%u\n", i); @@ -411,7 +422,7 @@ static GLuint compile_program(const char *vertex, glDeleteShader(frag); glUseProgram(prog); - GLint location = get_uniform(prog, "Texture"); + GLint location = get_uniform(glsl, prog, "Texture"); glUniform1i(location, 0); glUseProgram(0); } @@ -429,12 +440,13 @@ static bool load_source_path(struct gfx_shader_pass *pass, return pass->source.string.fragment && pass->source.string.vertex; } -static bool compile_programs(GLuint *gl_prog) +static bool compile_programs(glsl_shader_data_t *glsl, GLuint *gl_prog) { unsigned i; - for (i = 0; i < glsl_shader->passes; i++) + for (i = 0; i < glsl->glsl_shader->passes; i++) { - struct gfx_shader_pass *pass = &glsl_shader->pass[i]; + struct gfx_shader_pass *pass = (struct gfx_shader_pass*) + &glsl->glsl_shader->pass[i]; /* If we load from GLSLP (CGP), * load the file here, and pretend @@ -450,7 +462,7 @@ static bool compile_programs(GLuint *gl_prog) const char *vertex = pass->source.string.vertex; const char *fragment = pass->source.string.fragment; - gl_prog[i] = compile_program(vertex, fragment, i); + gl_prog[i] = compile_program(glsl, vertex, fragment, i); if (!gl_prog[i]) { @@ -462,15 +474,15 @@ static bool compile_programs(GLuint *gl_prog) return true; } -static void gl_glsl_reset_attrib(void) +static void gl_glsl_reset_attrib(glsl_shader_data_t *glsl) { unsigned i; /* Add sanity check that we did not overflow. */ - rarch_assert(gl_attrib_index <= ARRAY_SIZE(gl_attribs)); + rarch_assert(glsl->gl_attrib_index <= ARRAY_SIZE(glsl->gl_attribs)); - for (i = 0; i < gl_attrib_index; i++) - glDisableVertexAttribArray(gl_attribs[i]); - gl_attrib_index = 0; + for (i = 0; i < glsl->gl_attrib_index; i++) + glDisableVertexAttribArray(glsl->gl_attribs[i]); + glsl->gl_attrib_index = 0; } static void gl_glsl_set_vbo(GLfloat **buffer, size_t *buffer_elems, @@ -494,7 +506,8 @@ static void gl_glsl_set_vbo(GLfloat **buffer, size_t *buffer_elems, } } -static void gl_glsl_set_attribs(GLuint vbo, +static void gl_glsl_set_attribs(glsl_shader_data_t *glsl, + GLuint vbo, GLfloat **buffer, size_t *buffer_elems, const GLfloat *data, size_t elems, const struct glsl_attrib *attrs, size_t num_attrs) @@ -508,12 +521,12 @@ static void gl_glsl_set_attribs(GLuint vbo, { GLint loc = attrs[i].loc; - if (gl_attrib_index < ARRAY_SIZE(gl_attribs)) + if (glsl->gl_attrib_index < ARRAY_SIZE(glsl->gl_attribs)) { glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, attrs[i].size, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)(uintptr_t)attrs[i].offset); - gl_attribs[gl_attrib_index++] = loc; + glsl->gl_attribs[glsl->gl_attrib_index++] = loc; } else RARCH_WARN("Attrib array buffer was overflown!\n"); @@ -530,7 +543,8 @@ static void clear_uniforms_frame(struct shader_uniforms_frame *frame) frame->tex_coord = -1; } -static void find_uniforms_frame(GLuint prog, +static void find_uniforms_frame(glsl_shader_data_t *glsl, + GLuint prog, struct shader_uniforms_frame *frame, const char *base) { char texture[64]; @@ -544,132 +558,157 @@ static void find_uniforms_frame(GLuint prog, snprintf(tex_coord, sizeof(tex_coord), "%s%s", base, "TexCoord"); if (frame->texture < 0) - frame->texture = get_uniform(prog, texture); + frame->texture = get_uniform(glsl, prog, texture); if (frame->texture_size < 0) - frame->texture_size = get_uniform(prog, texture_size); + frame->texture_size = get_uniform(glsl, prog, texture_size); if (frame->input_size < 0) - frame->input_size = get_uniform(prog, input_size); + frame->input_size = get_uniform(glsl, prog, input_size); if (frame->tex_coord < 0) - frame->tex_coord = get_attrib(prog, tex_coord); + frame->tex_coord = get_attrib(glsl, prog, tex_coord); } -static void find_uniforms(unsigned pass, GLuint prog, +static void find_uniforms(glsl_shader_data_t *glsl, + unsigned pass, GLuint prog, struct shader_uniforms *uni) { unsigned i; glUseProgram(prog); - uni->mvp = get_uniform(prog, "MVPMatrix"); - uni->tex_coord = get_attrib(prog, "TexCoord"); - uni->vertex_coord = get_attrib(prog, "VertexCoord"); - uni->color = get_attrib(prog, "Color"); - uni->lut_tex_coord = get_attrib(prog, "LUTTexCoord"); + uni->mvp = get_uniform(glsl, prog, "MVPMatrix"); + uni->tex_coord = get_attrib(glsl, prog, "TexCoord"); + uni->vertex_coord = get_attrib(glsl, prog, "VertexCoord"); + uni->color = get_attrib(glsl, prog, "Color"); + uni->lut_tex_coord = get_attrib(glsl, prog, "LUTTexCoord"); - uni->input_size = get_uniform(prog, "InputSize"); - uni->output_size = get_uniform(prog, "OutputSize"); - uni->texture_size = get_uniform(prog, "TextureSize"); + uni->input_size = get_uniform(glsl, prog, "InputSize"); + uni->output_size = get_uniform(glsl, prog, "OutputSize"); + uni->texture_size = get_uniform(glsl, prog, "TextureSize"); - uni->frame_count = get_uniform(prog, "FrameCount"); - uni->frame_direction = get_uniform(prog, "FrameDirection"); + uni->frame_count = get_uniform(glsl, prog, "FrameCount"); + uni->frame_direction = get_uniform(glsl, prog, "FrameDirection"); - for (i = 0; i < glsl_shader->luts; i++) - uni->lut_texture[i] = glGetUniformLocation(prog, glsl_shader->lut[i].id); + for (i = 0; i < glsl->glsl_shader->luts; i++) + uni->lut_texture[i] = glGetUniformLocation(prog, glsl->glsl_shader->lut[i].id); char frame_base[64]; clear_uniforms_frame(&uni->orig); - find_uniforms_frame(prog, &uni->orig, "Orig"); + find_uniforms_frame(glsl, prog, &uni->orig, "Orig"); if (pass > 1) { snprintf(frame_base, sizeof(frame_base), "PassPrev%u", pass); - find_uniforms_frame(prog, &uni->orig, frame_base); + find_uniforms_frame(glsl, prog, &uni->orig, frame_base); } for (i = 0; i + 1 < pass; i++) { snprintf(frame_base, sizeof(frame_base), "Pass%u", i + 1); clear_uniforms_frame(&uni->pass[i]); - find_uniforms_frame(prog, &uni->pass[i], frame_base); + find_uniforms_frame(glsl, prog, &uni->pass[i], frame_base); snprintf(frame_base, sizeof(frame_base), "PassPrev%u", pass - (i + 1)); - find_uniforms_frame(prog, &uni->pass[i], frame_base); + find_uniforms_frame(glsl, prog, &uni->pass[i], frame_base); - if (*glsl_shader->pass[i].alias) - find_uniforms_frame(prog, &uni->pass[i], glsl_shader->pass[i].alias); + if (*glsl->glsl_shader->pass[i].alias) + find_uniforms_frame(glsl, prog, &uni->pass[i], glsl->glsl_shader->pass[i].alias); } clear_uniforms_frame(&uni->prev[0]); - find_uniforms_frame(prog, &uni->prev[0], "Prev"); + find_uniforms_frame(glsl, prog, &uni->prev[0], "Prev"); for (i = 1; i < PREV_TEXTURES; i++) { snprintf(frame_base, sizeof(frame_base), "Prev%u", i); clear_uniforms_frame(&uni->prev[i]); - find_uniforms_frame(prog, &uni->prev[i], frame_base); + find_uniforms_frame(glsl, prog, &uni->prev[i], frame_base); } glUseProgram(0); } -static void gl_glsl_free_shader(void) +static void gl_glsl_deinit_shader(glsl_shader_data_t *glsl) { unsigned i; - if (!glsl_shader) + if (!glsl || !glsl->glsl_shader) return; - for (i = 0; i < glsl_shader->passes; i++) + for (i = 0; i < glsl->glsl_shader->passes; i++) { - free(glsl_shader->pass[i].source.string.vertex); - free(glsl_shader->pass[i].source.string.fragment); + free(glsl->glsl_shader->pass[i].source.string.vertex); + free(glsl->glsl_shader->pass[i].source.string.fragment); } - free(glsl_shader->script); - free(glsl_shader); - glsl_shader = NULL; + free(glsl->glsl_shader->script); + free(glsl->glsl_shader); + glsl->glsl_shader = NULL; +} + +static void gl_glsl_destroy_resources(glsl_shader_data_t *glsl) +{ + unsigned i; + if (!glsl) + return; + + glUseProgram(0); + for (i = 0; i < GFX_MAX_SHADERS; i++) + { + if (glsl->gl_program[i] == 0 || (i && glsl->gl_program[i] == glsl->gl_program[0])) + continue; + + glDeleteProgram(glsl->gl_program[i]); + } + + if (glsl->glsl_shader && glsl->glsl_shader->luts) + glDeleteTextures(glsl->glsl_shader->luts, glsl->gl_teximage); + + memset(glsl->gl_program, 0, sizeof(glsl->gl_program)); + memset(glsl->gl_uniforms, 0, sizeof(glsl->gl_uniforms)); + glsl->glsl_active_index = 0; + + gl_glsl_deinit_shader(glsl); + + if (glsl->gl_state_tracker) + state_tracker_free(glsl->gl_state_tracker); + glsl->gl_state_tracker = NULL; + + gl_glsl_reset_attrib(glsl); + + for (i = 0; i < GFX_MAX_SHADERS; i++) + { + if (glsl->glsl_vbo[i].vbo_primary) + glDeleteBuffers(1, &glsl->glsl_vbo[i].vbo_primary); + if (glsl->glsl_vbo[i].vbo_secondary) + glDeleteBuffers(1, &glsl->glsl_vbo[i].vbo_secondary); + + free(glsl->glsl_vbo[i].buffer_primary); + free(glsl->glsl_vbo[i].buffer_secondary); + } + memset(&glsl->glsl_vbo, 0, sizeof(glsl->glsl_vbo)); } static void gl_glsl_deinit(void) { - unsigned i; - glUseProgram(0); - for (i = 0; i < GFX_MAX_SHADERS; i++) - { - if (gl_program[i] == 0 || (i && gl_program[i] == gl_program[0])) - continue; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; - glDeleteProgram(gl_program[i]); - } + if (!glsl) + return; - if (glsl_shader && glsl_shader->luts) - glDeleteTextures(glsl_shader->luts, gl_teximage); + gl_glsl_destroy_resources(glsl); - memset(gl_program, 0, sizeof(gl_program)); - memset(gl_uniforms, 0, sizeof(gl_uniforms)); - glsl_enable = false; - glsl_active_index = 0; - - gl_glsl_free_shader(); - - if (gl_state_tracker) - state_tracker_free(gl_state_tracker); - gl_state_tracker = NULL; - - gl_glsl_reset_attrib(); - - for (i = 0; i < GFX_MAX_SHADERS; i++) - { - if (glsl_vbo[i].vbo_primary) - glDeleteBuffers(1, &glsl_vbo[i].vbo_primary); - if (glsl_vbo[i].vbo_secondary) - glDeleteBuffers(1, &glsl_vbo[i].vbo_secondary); - - free(glsl_vbo[i].buffer_primary); - free(glsl_vbo[i].buffer_secondary); - } - memset(&glsl_vbo, 0, sizeof(glsl_vbo)); + if (driver.video_shader_data) + free(driver.video_shader_data); + driver.video_shader_data = NULL; } static bool gl_glsl_init(void *data, const char *path) { unsigned i; + config_file_t *conf = NULL; + glsl_shader_data_t *glsl = NULL; (void)data; + + glsl = (glsl_shader_data_t*)calloc(1, sizeof(glsl_shader_data_t)); + + if (!glsl) + return false; + #ifndef HAVE_OPENGLES2 RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = glCreateProgram && glUseProgram && glCreateShader @@ -688,25 +727,24 @@ static bool gl_glsl_init(void *data, const char *path) if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); + free(glsl); return false; } #endif - glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); - if (!glsl_shader) + glsl->glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl->glsl_shader)); + if (!glsl->glsl_shader) return false; - config_file_t *conf = NULL; - if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { - strlcpy(glsl_shader->pass[0].source.path, path, - sizeof(glsl_shader->pass[0].source.path)); - glsl_shader->passes = 1; - glsl_shader->modern = true; + strlcpy(glsl->glsl_shader->pass[0].source.path, path, + sizeof(glsl->glsl_shader->pass[0].source.path)); + glsl->glsl_shader->passes = 1; + glsl->glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) @@ -714,8 +752,8 @@ static bool gl_glsl_init(void *data, const char *path) conf = config_file_new(path); if (conf) { - ret = gfx_shader_read_conf_cgp(conf, glsl_shader); - glsl_shader->modern = true; + ret = gfx_shader_read_conf_cgp(conf, glsl->glsl_shader); + glsl->glsl_shader->modern = true; } else ret = false; @@ -732,16 +770,16 @@ static bool gl_glsl_init(void *data, const char *path) else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); - glsl_shader->passes = 1; - glsl_shader->pass[0].source.string.vertex = - strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); - glsl_shader->pass[0].source.string.fragment = - strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); - glsl_shader->modern = true; + glsl->glsl_shader->passes = 1; + glsl->glsl_shader->pass[0].source.string.vertex = + strdup(glsl->glsl_core ? stock_vertex_core : stock_vertex_modern); + glsl->glsl_shader->pass[0].source.string.fragment = + strdup(glsl->glsl_core ? stock_fragment_core : stock_fragment_modern); + glsl->glsl_shader->modern = true; } - gfx_shader_resolve_relative(glsl_shader, path); - gfx_shader_resolve_parameters(conf, glsl_shader); + gfx_shader_resolve_relative(glsl->glsl_shader, path); + gfx_shader_resolve_parameters(conf, glsl->glsl_shader); if (conf) { @@ -749,25 +787,25 @@ static bool gl_glsl_init(void *data, const char *path) conf = NULL; } - const char *stock_vertex = glsl_shader->modern ? + const char *stock_vertex = glsl->glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; - const char *stock_fragment = glsl_shader->modern ? + const char *stock_fragment = glsl->glsl_shader->modern ? stock_fragment_modern : stock_fragment_legacy; - if (glsl_core) + if (glsl->glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES2 - if (!glsl_shader->modern) + if (!glsl->glsl_shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); goto error; } #else - if (glsl_core && !glsl_shader->modern) + if (glsl->glsl_core && !glsl->glsl_shader->modern) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; @@ -776,91 +814,98 @@ static bool gl_glsl_init(void *data, const char *path) /* Find all aliases we use in our GLSLP and add #defines for them so * that a shader can choose a fallback if we are not using a preset. */ - *glsl_alias_define = '\0'; - for (i = 0; i < glsl_shader->passes; i++) + *glsl->glsl_alias_define = '\0'; + for (i = 0; i < glsl->glsl_shader->passes; i++) { - if (*glsl_shader->pass[i].alias) + if (*glsl->glsl_shader->pass[i].alias) { char define[128]; snprintf(define, sizeof(define), "#define %s_ALIAS\n", - glsl_shader->pass[i].alias); - strlcat(glsl_alias_define, define, sizeof(glsl_alias_define)); + glsl->glsl_shader->pass[i].alias); + strlcat(glsl->glsl_alias_define, define, sizeof(glsl->glsl_alias_define)); } } - if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) + if (!(glsl->gl_program[0] = compile_program(glsl, stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } - if (!compile_programs(&gl_program[1])) + if (!compile_programs(glsl, &glsl->gl_program[1])) goto error; - if (!gl_load_luts(glsl_shader, gl_teximage)) + if (!gl_load_luts(glsl->glsl_shader, glsl->gl_teximage)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } - for (i = 0; i <= glsl_shader->passes; i++) - find_uniforms(i, gl_program[i], &gl_uniforms[i]); + for (i = 0; i <= glsl->glsl_shader->passes; i++) + find_uniforms(glsl, i, glsl->gl_program[i], &glsl->gl_uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error()) RARCH_WARN("Detected GL error in GLSL.\n"); #endif - if (glsl_shader->variables) + if (glsl->glsl_shader->variables) { struct state_tracker_info info = {0}; info.wram = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM); - info.info = glsl_shader->variable; - info.info_elem = glsl_shader->variables; + info.info = glsl->glsl_shader->variable; + info.info_elem = glsl->glsl_shader->variables; #ifdef HAVE_PYTHON - info.script = glsl_shader->script; - info.script_class = *glsl_shader->script_class ? - glsl_shader->script_class : NULL; + info.script = glsl->glsl_shader->script; + info.script_class = *glsl->glsl_shader->script_class ? + glsl->glsl_shader->script_class : NULL; #endif - gl_state_tracker = state_tracker_init(&info); - if (!gl_state_tracker) + glsl->gl_state_tracker = state_tracker_init(&info); + if (!glsl->gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } - glsl_enable = true; - gl_program[glsl_shader->passes + 1] = gl_program[0]; - gl_uniforms[glsl_shader->passes + 1] = gl_uniforms[0]; + glsl->gl_program[glsl->glsl_shader->passes + 1] = glsl->gl_program[0]; + glsl->gl_uniforms[glsl->glsl_shader->passes + 1] = glsl->gl_uniforms[0]; - if (glsl_shader->modern) + if (glsl->glsl_shader->modern) { - gl_program[GL_SHADER_STOCK_BLEND] = compile_program(glsl_core ? + glsl->gl_program[GL_SHADER_STOCK_BLEND] = compile_program( + glsl, + glsl->glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend, - glsl_core ? + glsl->glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); - find_uniforms(0, gl_program[GL_SHADER_STOCK_BLEND], - &gl_uniforms[GL_SHADER_STOCK_BLEND]); + find_uniforms(glsl, 0, glsl->gl_program[GL_SHADER_STOCK_BLEND], + &glsl->gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { - gl_program[GL_SHADER_STOCK_BLEND] = gl_program[0]; - gl_uniforms[GL_SHADER_STOCK_BLEND] = gl_uniforms[0]; + glsl->gl_program [GL_SHADER_STOCK_BLEND] = glsl->gl_program[0]; + glsl->gl_uniforms[GL_SHADER_STOCK_BLEND] = glsl->gl_uniforms[0]; } - gl_glsl_reset_attrib(); + gl_glsl_reset_attrib(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) { - glGenBuffers(1, &glsl_vbo[i].vbo_primary); - glGenBuffers(1, &glsl_vbo[i].vbo_secondary); + glGenBuffers(1, &glsl->glsl_vbo[i].vbo_primary); + glGenBuffers(1, &glsl->glsl_vbo[i].vbo_secondary); } + driver.video_shader_data = glsl; + return true; error: - gl_glsl_deinit(); + gl_glsl_destroy_resources(glsl); + + if (glsl) + free(glsl); + return false; } @@ -875,17 +920,22 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, GLfloat buffer[512]; struct glsl_attrib attribs[32]; unsigned i; + const struct shader_uniforms *uni = NULL; size_t size = 0, attribs_size = 0; const struct gl_tex_info *info = (const struct gl_tex_info*)_info; const struct gl_tex_info *prev_info = (const struct gl_tex_info*)_prev_info; const struct gl_tex_info *fbo_info = (const struct gl_tex_info*)_fbo_info; struct glsl_attrib *attr = (struct glsl_attrib*)attribs; - const struct shader_uniforms *uni = (const struct shader_uniforms*) - &gl_uniforms[glsl_active_index]; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + + if (!glsl) + return; + + uni = (const struct shader_uniforms*)&glsl->gl_uniforms[glsl->glsl_active_index]; (void)data; - if (!glsl_enable || (gl_program[glsl_active_index] == 0)) + if (!glsl || (glsl->gl_program[glsl->glsl_active_index] == 0)) return; float input_size[2] = {(float)width, (float)height}; @@ -901,9 +951,9 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, if (uni->texture_size >= 0) glUniform2fv(uni->texture_size, 1, texture_size); - if (uni->frame_count >= 0 && glsl_active_index) + if (uni->frame_count >= 0 && glsl->glsl_active_index) { - unsigned modulo = glsl_shader->pass[glsl_active_index - 1].frame_count_mod; + unsigned modulo = glsl->glsl_shader->pass[glsl->glsl_active_index - 1].frame_count_mod; if (modulo) frame_count %= modulo; glUniform1i(uni->frame_count, frame_count); @@ -914,20 +964,20 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, unsigned texunit = 1; - for (i = 0; i < glsl_shader->luts; i++) + for (i = 0; i < glsl->glsl_shader->luts; i++) { if (uni->lut_texture[i] >= 0) { /* Have to rebind as HW render could override this. */ glActiveTexture(GL_TEXTURE0 + texunit); - glBindTexture(GL_TEXTURE_2D, gl_teximage[i]); + glBindTexture(GL_TEXTURE_2D, glsl->gl_teximage[i]); glUniform1i(uni->lut_texture[i], texunit); texunit++; } } /* Set original texture. */ - if (glsl_active_index) + if (glsl->glsl_active_index) { if (uni->orig.texture >= 0) { @@ -1021,35 +1071,37 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, if (size) { - gl_glsl_set_attribs(glsl_vbo[glsl_active_index].vbo_secondary, - &glsl_vbo[glsl_active_index].buffer_secondary, - &glsl_vbo[glsl_active_index].size_secondary, + gl_glsl_set_attribs(glsl, glsl->glsl_vbo[glsl->glsl_active_index].vbo_secondary, + &glsl->glsl_vbo[glsl->glsl_active_index].buffer_secondary, + &glsl->glsl_vbo[glsl->glsl_active_index].size_secondary, buffer, size, attribs, attribs_size); } glActiveTexture(GL_TEXTURE0); /* #pragma parameters. */ - for (i = 0; i < glsl_shader->num_parameters; i++) + for (i = 0; i < glsl->glsl_shader->num_parameters; i++) { - int location = glGetUniformLocation(gl_program[glsl_active_index], - glsl_shader->parameters[i].id); - glUniform1f(location, glsl_shader->parameters[i].current); + int location = glGetUniformLocation( + glsl->gl_program[glsl->glsl_active_index], + glsl->glsl_shader->parameters[i].id); + glUniform1f(location, glsl->glsl_shader->parameters[i].current); } /* Set state parameters. */ - if (gl_state_tracker) + if (glsl->gl_state_tracker) { static struct state_tracker_uniform state_info[GFX_MAX_VARIABLES]; static unsigned cnt = 0; - if (glsl_active_index == 1) - cnt = state_get_uniform(gl_state_tracker, state_info, + if (glsl->glsl_active_index == 1) + cnt = state_get_uniform(glsl->gl_state_tracker, state_info, GFX_MAX_VARIABLES, frame_count); for (i = 0; i < cnt; i++) { - int location = glGetUniformLocation(gl_program[glsl_active_index], + int location = glGetUniformLocation( + glsl->gl_program[glsl->glsl_active_index], state_info[i].id); glUniform1f(location, state_info[i].value); } @@ -1058,11 +1110,14 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, static bool gl_glsl_set_mvp(void *data, const math_matrix_4x4 *mat) { + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + (void)data; - if (!glsl_enable || !glsl_shader->modern) + + if (!glsl || !glsl->glsl_shader->modern) goto fallback; - int loc = gl_uniforms[glsl_active_index].mvp; + int loc = glsl->gl_uniforms[glsl->glsl_active_index].mvp; if (loc >= 0) glUniformMatrix4fv(loc, 1, GL_FALSE, mat->data); @@ -1077,8 +1132,9 @@ fallback: static bool gl_glsl_set_coords(const void *data) { const struct gl_coords *coords = (const struct gl_coords*)data; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; - if (!glsl_enable || !glsl_shader->modern || !coords) + if (!glsl || !glsl->glsl_shader->modern || !coords) goto fallback; /* Avoid hitting malloc on every single regular quad draw. */ @@ -1097,7 +1153,8 @@ static bool gl_glsl_set_coords(const void *data) size_t attribs_size = 0; struct glsl_attrib *attr = attribs; - const struct shader_uniforms *uni = &gl_uniforms[glsl_active_index]; + const struct shader_uniforms *uni = &glsl->gl_uniforms[glsl->glsl_active_index]; + if (uni->tex_coord >= 0) { attr->loc = uni->tex_coord; @@ -1152,9 +1209,10 @@ static bool gl_glsl_set_coords(const void *data) if (size) { - gl_glsl_set_attribs(glsl_vbo[glsl_active_index].vbo_primary, - &glsl_vbo[glsl_active_index].buffer_primary, - &glsl_vbo[glsl_active_index].size_primary, + gl_glsl_set_attribs(glsl, + glsl->glsl_vbo[glsl->glsl_active_index].vbo_primary, + &glsl->glsl_vbo[glsl->glsl_active_index].buffer_primary, + &glsl->glsl_vbo[glsl->glsl_active_index].size_primary, buffer, size, attribs, attribs_size); } @@ -1171,30 +1229,35 @@ fallback: static void gl_glsl_use(void *data, unsigned idx) { - (void)data; - if (glsl_enable) - { - gl_glsl_reset_attrib(); + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; - glsl_active_index = idx; - glUseProgram(gl_program[idx]); - } + (void)data; + + if (!glsl) + return; + + gl_glsl_reset_attrib(glsl); + + glsl->glsl_active_index = idx; + glUseProgram(glsl->gl_program[idx]); } static unsigned gl_glsl_num(void) { - if (glsl_shader) - return glsl_shader->passes; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl && glsl->glsl_shader) + return glsl->glsl_shader->passes; return 0; } static bool gl_glsl_filter_type(unsigned idx, bool *smooth) { - if (glsl_enable && idx - && (glsl_shader->pass[idx - 1].filter != RARCH_FILTER_UNSPEC) + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl && idx + && (glsl->glsl_shader->pass[idx - 1].filter != RARCH_FILTER_UNSPEC) ) { - *smooth = (glsl_shader->pass[idx - 1].filter == RARCH_FILTER_LINEAR); + *smooth = (glsl->glsl_shader->pass[idx - 1].filter == RARCH_FILTER_LINEAR); return true; } return false; @@ -1202,15 +1265,17 @@ static bool gl_glsl_filter_type(unsigned idx, bool *smooth) static enum gfx_wrap_type gl_glsl_wrap_type(unsigned idx) { - if (glsl_enable && idx) - return glsl_shader->pass[idx - 1].wrap; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl && idx) + return glsl->glsl_shader->pass[idx - 1].wrap; return RARCH_WRAP_BORDER; } static void gl_glsl_shader_scale(unsigned idx, struct gfx_fbo_scale *scale) { - if (glsl_enable && idx) - *scale = glsl_shader->pass[idx - 1].fbo; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl && idx) + *scale = glsl->glsl_shader->pass[idx - 1].fbo; else scale->valid = false; } @@ -1218,13 +1283,15 @@ static void gl_glsl_shader_scale(unsigned idx, struct gfx_fbo_scale *scale) static unsigned gl_glsl_get_prev_textures(void) { unsigned i, j; - if (!glsl_enable) + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + + if (!glsl) return 0; unsigned max_prev = 0; - for (i = 1; i <= glsl_shader->passes; i++) + for (i = 1; i <= glsl->glsl_shader->passes; i++) for (j = 0; j < PREV_TEXTURES; j++) - if (gl_uniforms[i].prev[j].texture >= 0) + if (glsl->gl_uniforms[i].prev[j].texture >= 0) max_prev = max(j + 1, max_prev); return max_prev; @@ -1232,14 +1299,18 @@ static unsigned gl_glsl_get_prev_textures(void) static bool gl_glsl_mipmap_input(unsigned idx) { - if (glsl_enable && idx) - return glsl_shader->pass[idx - 1].mipmap; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl && idx) + return glsl->glsl_shader->pass[idx - 1].mipmap; return false; } static struct gfx_shader *gl_glsl_get_current_shader(void) { - return glsl_enable ? glsl_shader : NULL; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + if (glsl) + return glsl->glsl_shader; + return NULL; } void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*)) @@ -1250,9 +1321,14 @@ void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*)) void gl_glsl_set_context_type(bool core_profile, unsigned major, unsigned minor) { - glsl_core = core_profile; - glsl_major = major; - glsl_minor = minor; + glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver.video_shader_data; + + if (!glsl) + return; + + glsl->glsl_core = core_profile; + glsl->glsl_major = major; + glsl->glsl_minor = minor; } const shader_backend_t gl_glsl_backend = {