static void gl_glsl_deinit(void *data) { glsl_shader_data_t *glsl = (glsl_shader_data_t*)data; if (!glsl) return; gl_glsl_destroy_resources(glsl); free(glsl); }
static void gl_glsl_deinit(void) { driver_t *driver = driver_get_ptr(); glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver->video_shader_data; if (!glsl) return; gl_glsl_destroy_resources(glsl); if (driver->video_shader_data) free(driver->video_shader_data); driver->video_shader_data = NULL; }
static void *gl_glsl_init(void *data, const char *path) { unsigned i; struct shader_program_info shader_prog_info; bool shader_support = false; #ifdef GLSL_DEBUG char *error_string = NULL; #endif config_file_t *conf = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; glsl_shader_data_t *glsl = (glsl_shader_data_t*) calloc(1, sizeof(glsl_shader_data_t)); if (!glsl) return NULL; (void)shader_support; #ifndef HAVE_OPENGLES RARCH_LOG("[GLSL]: Checking GLSL shader support ...\n"); shader_support = glCreateProgram && glUseProgram && glCreateShader && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); goto error; } #endif glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader)); if (!glsl->shader) goto error; if (!string_is_empty(path)) { bool ret = false; const char *path_ext = path_get_extension(path); if (string_is_equal_fast(path_ext, "glslp", 5)) { conf = config_file_new(path); if (conf) { ret = video_shader_read_conf_cgp(conf, glsl->shader); glsl->shader->modern = true; } } else if (string_is_equal_fast(path_ext, "glsl", 4)) { strlcpy(glsl->shader->pass[0].source.path, path, sizeof(glsl->shader->pass[0].source.path)); glsl->shader->passes = 1; glsl->shader->modern = true; ret = true; } if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); goto error; } } 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; } if (!string_is_empty(path)) video_shader_resolve_relative(glsl->shader, path); video_shader_resolve_parameters(conf, glsl->shader); if (conf) { config_file_free(conf); conf = NULL; } stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES if (!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) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif /* 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++) { if (*glsl->shader->pass[i].alias) { char define[128]; define[0] = '\0'; snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl->shader->pass[i].alias); strlcat(glsl->alias_define, define, sizeof(glsl->alias_define)); } } shader_prog_info.vertex = stock_vertex; shader_prog_info.fragment = stock_fragment; shader_prog_info.is_file = false; if (!gl_glsl_compile_program(glsl, 0, &glsl->prg[0], &shader_prog_info)) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!gl_glsl_compile_programs(glsl, &glsl->prg[1])) goto error; if (!gl_load_luts(glsl->shader, glsl->lut_textures)) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); goto error; } for (i = 0; i <= glsl->shader->passes; i++) gl_glsl_find_uniforms(glsl, i, glsl->prg[i].id, &glsl->uniforms[i]); #ifdef GLSL_DEBUG if (!gl_check_error(&error_string)) { RARCH_ERR("%s\n", error_string); free(error_string); RARCH_WARN("Detected GL error in GLSL.\n"); } #endif if (glsl->shader->variables) { retro_ctx_memory_info_t mem_info; struct state_tracker_info info; mem_info.id = RETRO_MEMORY_SYSTEM_RAM; core_get_memory(&mem_info); info.wram = (uint8_t*)mem_info.data; info.info = glsl->shader->variable; info.info_elem = glsl->shader->variables; info.script = NULL; info.script_class = NULL; #ifdef HAVE_PYTHON info.script = glsl->shader->script; if (*glsl->shader->script_class) info.script_class= glsl->shader->script_class; #endif info.script_is_file = NULL; glsl->state_tracker = state_tracker_init(&info); if (!glsl->state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl->prg[glsl->shader->passes + 1] = glsl->prg[0]; glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0]; if (glsl->shader->modern) { shader_prog_info.vertex = glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend; shader_prog_info.fragment = glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend; shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_STOCK_BLEND, &glsl->prg[VIDEO_SHADER_STOCK_BLEND], &shader_prog_info ); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_STOCK_BLEND].id, &glsl->uniforms[VIDEO_SHADER_STOCK_BLEND]); } else { glsl->prg[VIDEO_SHADER_STOCK_BLEND] = glsl->prg[0]; glsl->uniforms[VIDEO_SHADER_STOCK_BLEND] = glsl->uniforms[0]; } #ifdef HAVE_SHADERPIPELINE #ifdef HAVE_OPENGLES if (gl_query_extension("GL_OES_standard_derivatives")) { shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; shader_prog_info.fragment = stock_fragment_xmb; } else { shader_prog_info.vertex = stock_vertex_xmb_ribbon_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; } #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy; shader_prog_info.fragment = stock_fragment_xmb; #endif shader_prog_info.is_file = false; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU, &glsl->prg[VIDEO_SHADER_MENU], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id, &glsl->uniforms[VIDEO_SHADER_MENU]); shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_ribbon_simple_legacy; shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_2, &glsl->prg[VIDEO_SHADER_MENU_2], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_2].id, &glsl->uniforms[VIDEO_SHADER_MENU_2]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_simple_snow; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_3, &glsl->prg[VIDEO_SHADER_MENU_3], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_3].id, &glsl->uniforms[VIDEO_SHADER_MENU_3]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_snow; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_4, &glsl->prg[VIDEO_SHADER_MENU_4], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_4].id, &glsl->uniforms[VIDEO_SHADER_MENU_4]); #if defined(HAVE_OPENGLES) shader_prog_info.vertex = stock_vertex_xmb_snow_modern; #else shader_prog_info.vertex = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy; #endif shader_prog_info.fragment = stock_fragment_xmb_bokeh; gl_glsl_compile_program( glsl, VIDEO_SHADER_MENU_5, &glsl->prg[VIDEO_SHADER_MENU_5], &shader_prog_info); gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_5].id, &glsl->uniforms[VIDEO_SHADER_MENU_5]); #endif 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); } return glsl; error: gl_glsl_destroy_resources(glsl); if (conf) config_file_free(conf); if (glsl) free(glsl); return NULL; }
static bool gl_glsl_init(void *data, const char *path) { unsigned i; config_file_t *conf = NULL; glsl_shader_data_t *glsl = NULL; const char *stock_vertex = NULL; const char *stock_fragment = NULL; driver_t *driver = driver_get_ptr(); (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 && glDeleteShader && glShaderSource && glCompileShader && glAttachShader && glDetachShader && glLinkProgram && glGetUniformLocation && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv && glUniformMatrix4fv && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv && glGetProgramInfoLog && glDeleteProgram && glGetAttachedShaders && glGetAttribLocation && glEnableVertexAttribArray && glDisableVertexAttribArray && glVertexAttribPointer && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); free(glsl); return false; } #endif glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader)); if (!glsl->shader) { free(glsl); return false; } if (path) { bool ret; const char *path_ext = path_get_extension(path); if (!strcmp(path_ext, "glsl")) { strlcpy(glsl->shader->pass[0].source.path, path, sizeof(glsl->shader->pass[0].source.path)); glsl->shader->passes = 1; glsl->shader->modern = true; ret = true; } else if (!strcmp(path_ext, "glslp")) { conf = config_file_new(path); if (conf) { ret = video_shader_read_conf_cgp(conf, glsl->shader); glsl->shader->modern = true; } else ret = false; } else ret = false; if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); free(glsl->shader); free(glsl); return false; } } 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; } video_shader_resolve_relative(glsl->shader, path); video_shader_resolve_parameters(conf, glsl->shader); if (conf) { config_file_free(conf); conf = NULL; } stock_vertex = (glsl->shader->modern) ? stock_vertex_modern : stock_vertex_legacy; stock_fragment = (glsl->shader->modern) ? stock_fragment_modern : stock_fragment_legacy; if (glsl_core) { stock_vertex = stock_vertex_core; stock_fragment = stock_fragment_core; } #ifdef HAVE_OPENGLES2 if (!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) { RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n"); goto error; } #endif /* 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->glsl_alias_define = '\0'; for (i = 0; i < glsl->shader->passes; i++) { if (*glsl->shader->pass[i].alias) { char define[128] = {0}; snprintf(define, sizeof(define), "#define %s_ALIAS\n", glsl->shader->pass[i].alias); strlcat(glsl->glsl_alias_define, define, sizeof(glsl->glsl_alias_define)); } } 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(glsl, &glsl->gl_program[1])) goto error; if (!gl_load_luts(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(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) { 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; #ifdef HAVE_PYTHON info.script = glsl->shader->script; info.script_class = *glsl->shader->script_class ? glsl->shader->script_class : NULL; #endif glsl->gl_state_tracker = state_tracker_init(&info); if (!glsl->gl_state_tracker) RARCH_WARN("Failed to init state tracker.\n"); } glsl->gl_program[glsl->shader->passes + 1] = glsl->gl_program[0]; glsl->gl_uniforms[glsl->shader->passes + 1] = glsl->gl_uniforms[0]; if (glsl->shader->modern) { glsl->gl_program[GL_SHADER_STOCK_BLEND] = compile_program( glsl, glsl_core ? stock_vertex_core_blend : stock_vertex_modern_blend, glsl_core ? stock_fragment_core_blend : stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(glsl, 0, glsl->gl_program[GL_SHADER_STOCK_BLEND], &glsl->gl_uniforms[GL_SHADER_STOCK_BLEND]); } else { 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(glsl); for (i = 0; i < GFX_MAX_SHADERS; i++) { 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_destroy_resources(glsl); if (glsl) free(glsl); return false; }