static bool load_preset(const char *path) { unsigned i; if (!load_stock()) return false; 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"); return false; } if (!cg_shader) cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg_shader)); if (!cg_shader) return false; if (!gfx_shader_read_conf_cgp(conf, cg_shader)) { RARCH_ERR("Failed to parse CGP file.\n"); config_file_free(conf); return false; } config_file_free(conf); gfx_shader_resolve_relative(cg_shader, path); if (cg_shader->passes > GFX_MAX_SHADERS - 3) { RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", GFX_MAX_SHADERS - 3); cg_shader->passes = GFX_MAX_SHADERS - 3; } for (i = 0; i < cg_shader->passes; i++) { if (!load_shader(i)) { RARCH_ERR("Failed to load shaders ...\n"); return false; } } if (!load_textures()) { RARCH_ERR("Failed to load lookup textures ...\n"); return false; } if (!load_imports()) { RARCH_ERR("Failed to load imports ...\n"); return false; } return true; }
void shader_manager_init(rgui_handle_t *rgui) { config_file_t *conf = NULL; char cgp_path[PATH_MAX]; const char *ext = path_get_extension(g_settings.video.shader_path); if (strcmp(ext, "glslp") == 0 || strcmp(ext, "cgp") == 0) { conf = config_file_new(g_settings.video.shader_path); if (conf) { if (gfx_shader_read_conf_cgp(conf, &rgui->shader)) gfx_shader_resolve_relative(&rgui->shader, g_settings.video.shader_path); config_file_free(conf); } } else if (strcmp(ext, "glsl") == 0 || strcmp(ext, "cg") == 0) { strlcpy(rgui->shader.pass[0].source.cg, g_settings.video.shader_path, sizeof(rgui->shader.pass[0].source.cg)); rgui->shader.passes = 1; } else { const char *shader_dir = *g_settings.video.shader_dir ? g_settings.video.shader_dir : g_settings.system_directory; fill_pathname_join(cgp_path, shader_dir, "rgui.glslp", sizeof(cgp_path)); conf = config_file_new(cgp_path); if (!conf) { fill_pathname_join(cgp_path, shader_dir, "rgui.cgp", sizeof(cgp_path)); conf = config_file_new(cgp_path); } if (conf) { if (gfx_shader_read_conf_cgp(conf, &rgui->shader)) gfx_shader_resolve_relative(&rgui->shader, cgp_path); config_file_free(conf); } } }
bool d3d_init_multipass(void *data) { d3d_video_t *d3d = (d3d_video_t*)data; config_file_t *conf = config_file_new(d3d->cg_shader.c_str()); if (!conf) { RARCH_ERR("Failed to load preset.\n"); return false; } memset(&d3d->shader, 0, sizeof(d3d->shader)); if (!gfx_shader_read_conf_cgp(conf, &d3d->shader)) { config_file_free(conf); RARCH_ERR("Failed to parse CGP file.\n"); return false; } config_file_free(conf); gfx_shader_resolve_relative(&d3d->shader, d3d->cg_shader.c_str()); RARCH_LOG("[D3D9 Meta-Cg] Found %d shaders.\n", d3d->shader.passes); for (unsigned i = 0; i < d3d->shader.passes; i++) { if (!d3d->shader.pass[i].fbo.valid) { d3d->shader.pass[i].fbo.scale_x = d3d->shader.pass[i].fbo.scale_y = 1.0f; d3d->shader.pass[i].fbo.type_x = d3d->shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT; } } bool use_extra_pass = d3d->shader.passes < GFX_MAX_SHADERS && d3d->shader.pass[d3d->shader.passes - 1].fbo.valid; if (use_extra_pass) { d3d->shader.passes++; gfx_shader_pass &dummy_pass = d3d->shader.pass[d3d->shader.passes - 1]; dummy_pass.fbo.scale_x = dummy_pass.fbo.scale_y = 1.0f; dummy_pass.fbo.type_x = dummy_pass.fbo.type_y = RARCH_SCALE_VIEWPORT; dummy_pass.filter = RARCH_FILTER_UNSPEC; } else { gfx_shader_pass &pass = d3d->shader.pass[d3d->shader.passes - 1]; pass.fbo.scale_x = pass.fbo.scale_y = 1.0f; pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT; } return true; }
static bool load_preset(void *data, const char *path) { if (!load_stock(data)) return false; 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"); return false; } if (!cg_shader) cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg_shader)); if (!cg_shader) return false; if (!gfx_shader_read_conf_cgp(conf, cg_shader)) { RARCH_ERR("Failed to parse CGP file.\n"); config_file_free(conf); return false; } config_file_free(conf); if (cg_shader->passes > RARCH_HLSL_MAX_SHADERS - 3) { RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", RARCH_HLSL_MAX_SHADERS - 3); cg_shader->passes = RARCH_HLSL_MAX_SHADERS - 3; } for (unsigned i = 0; i < cg_shader->passes; i++) { if (!load_shader(data, path, i)) { RARCH_ERR("Failed to load shaders ...\n"); return false; } } /* TODO - textures / imports */ return true; }
void menu_shader_manager_set_preset(struct gfx_shader *shader, unsigned type, const char *cgp_path) { RARCH_LOG("Setting Menu shader: %s.\n", cgp_path ? cgp_path : "N/A (stock)"); g_settings.video.shader_enable = false; if (driver.video->set_shader && driver.video->set_shader(driver.video_data, (enum rarch_shader_type)type, cgp_path)) { /* Makes sure that we use Menu CGP shader on driver reinit. * Only do this when the cgp actually works to avoid potential errors. */ strlcpy(g_settings.video.shader_path, cgp_path ? cgp_path : "", sizeof(g_settings.video.shader_path)); g_settings.video.shader_enable = true; if (cgp_path && shader) { /* Load stored CGP into menu on success. * Used when a preset is directly loaded. * No point in updating when the CGP was * created from the menu itself. */ config_file_t *conf = config_file_new(cgp_path); if (conf) { if (gfx_shader_read_conf_cgp(conf, shader)) { gfx_shader_resolve_relative(shader, cgp_path); gfx_shader_resolve_parameters(conf, shader); } config_file_free(conf); } driver.menu->need_refresh = true; } } }
void menu_shader_manager_init(void *data) { char cgp_path[PATH_MAX]; struct gfx_shader *shader; config_file_t *conf = NULL; const char *config_path = NULL; menu_handle_t *menu = (menu_handle_t*)data; if (!menu) return; shader = (struct gfx_shader*)menu->shader; if (*g_extern.core_specific_config_path && g_settings.core_specific_config) config_path = g_extern.core_specific_config_path; else if (*g_extern.config_path) config_path = g_extern.config_path; /* In a multi-config setting, we can't have * conflicts on menu.cgp/menu.glslp. */ if (config_path) { fill_pathname_base(menu->default_glslp, config_path, sizeof(menu->default_glslp)); path_remove_extension(menu->default_glslp); strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp)); fill_pathname_base(menu->default_cgp, config_path, sizeof(menu->default_cgp)); path_remove_extension(menu->default_cgp); strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp)); } else { strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp)); strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp)); } const char *ext = path_get_extension(g_settings.video.shader_path); if (strcmp(ext, "glslp") == 0 || strcmp(ext, "cgp") == 0) { conf = config_file_new(g_settings.video.shader_path); if (conf) { if (gfx_shader_read_conf_cgp(conf, shader)) { gfx_shader_resolve_relative(shader, g_settings.video.shader_path); gfx_shader_resolve_parameters(conf, shader); } config_file_free(conf); } } else if (strcmp(ext, "glsl") == 0 || strcmp(ext, "cg") == 0) { strlcpy(shader->pass[0].source.path, g_settings.video.shader_path, sizeof(shader->pass[0].source.path)); shader->passes = 1; } else { const char *shader_dir = *g_settings.video.shader_dir ? g_settings.video.shader_dir : g_settings.system_directory; fill_pathname_join(cgp_path, shader_dir, "menu.glslp", sizeof(cgp_path)); conf = config_file_new(cgp_path); if (!conf) { fill_pathname_join(cgp_path, shader_dir, "menu.cgp", sizeof(cgp_path)); conf = config_file_new(cgp_path); } if (conf) { if (gfx_shader_read_conf_cgp(conf, shader)) { gfx_shader_resolve_relative(shader, cgp_path); gfx_shader_resolve_parameters(conf, shader); } config_file_free(conf); } } }
static bool gl_glsl_init(void *data, const char *path) { unsigned i; (void)data; #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"); return false; } #endif glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); if (!glsl_shader) return false; if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { strlcpy(glsl_shader->pass[0].source.cg, path, sizeof(glsl_shader->pass[0].source.cg)); glsl_shader->passes = 1; glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) { config_file_t *conf = config_file_new(path); if (conf) { ret = gfx_shader_read_conf_cgp(conf, glsl_shader); glsl_shader->modern = true; config_file_free(conf); } else ret = false; } else ret = gfx_shader_read_xml(path, glsl_shader); if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl_shader->passes = 1; glsl_shader->pass[0].source.xml.vertex = strdup(glsl_core ? stock_vertex_core : stock_vertex_modern); glsl_shader->pass[0].source.xml.fragment = strdup(glsl_core ? stock_fragment_core : stock_fragment_modern); glsl_shader->modern = true; } gfx_shader_resolve_relative(glsl_shader, path); const char *stock_vertex = glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; const char *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 if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); goto error; } if (!compile_programs(&gl_program[1])) goto error; if (!gl_load_luts(glsl_shader, 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]); #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 gl_state_tracker = state_tracker_init(&info); if (!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]; if (glsl_shader->modern) { gl_program[GL_SHADER_STOCK_BLEND] = compile_program(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(0, gl_program[GL_SHADER_STOCK_BLEND], &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]; } gl_glsl_reset_attrib(); for (i = 0; i < GFX_MAX_SHADERS; i++) { glGenBuffers(1, &glsl_vbo[i].vbo_primary); glGenBuffers(1, &glsl_vbo[i].vbo_secondary); } return true; error: gl_glsl_deinit(); return false; }
static bool load_preset(cg_shader_data_t *cg, const char *path) { unsigned i; if (!load_stock(cg)) return false; 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"); return false; } cg->cg_shader = (struct gfx_shader*)calloc(1, sizeof(*cg->cg_shader)); if (!cg->cg_shader) return false; if (!gfx_shader_read_conf_cgp(conf, cg->cg_shader)) { RARCH_ERR("Failed to parse CGP file.\n"); config_file_free(conf); return false; } gfx_shader_resolve_relative(cg->cg_shader, path); gfx_shader_resolve_parameters(conf, cg->cg_shader); config_file_free(conf); if (cg->cg_shader->passes > GFX_MAX_SHADERS - 3) { RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n", GFX_MAX_SHADERS - 3); cg->cg_shader->passes = GFX_MAX_SHADERS - 3; } for (i = 0; i < cg->cg_shader->passes; i++) if (*cg->cg_shader->pass[i].alias) snprintf(cg->cg_alias_define[i], sizeof(cg->cg_alias_define[i]), "-D%s_ALIAS", cg->cg_shader->pass[i].alias); for (i = 0; i < cg->cg_shader->passes; i++) { if (!load_shader(cg, i)) { RARCH_ERR("Failed to load shaders ...\n"); return false; } } if (!gl_load_luts(cg->cg_shader, cg->lut_textures)) { RARCH_ERR("Failed to load lookup textures ...\n"); return false; } if (!gl_cg_load_imports(cg)) { RARCH_ERR("Failed to load imports ...\n"); return false; } return true; }
static bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) && !defined(__APPLE__) // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); LOAD_GL_SYM(CreateShader); LOAD_GL_SYM(DeleteShader); LOAD_GL_SYM(ShaderSource); LOAD_GL_SYM(CompileShader); LOAD_GL_SYM(AttachShader); LOAD_GL_SYM(DetachShader); LOAD_GL_SYM(LinkProgram); LOAD_GL_SYM(GetUniformLocation); LOAD_GL_SYM(Uniform1i); LOAD_GL_SYM(Uniform1f); LOAD_GL_SYM(Uniform2fv); LOAD_GL_SYM(Uniform4fv); LOAD_GL_SYM(UniformMatrix4fv); LOAD_GL_SYM(GetShaderiv); LOAD_GL_SYM(GetShaderInfoLog); LOAD_GL_SYM(GetProgramiv); LOAD_GL_SYM(GetProgramInfoLog); LOAD_GL_SYM(DeleteProgram); LOAD_GL_SYM(GetAttachedShaders); LOAD_GL_SYM(GetAttribLocation); LOAD_GL_SYM(EnableVertexAttribArray); LOAD_GL_SYM(DisableVertexAttribArray); LOAD_GL_SYM(VertexAttribPointer); RARCH_LOG("Checking GLSL shader support ...\n"); bool shader_support = pglCreateProgram && pglUseProgram && pglCreateShader && pglDeleteShader && pglShaderSource && pglCompileShader && pglAttachShader && pglDetachShader && pglLinkProgram && pglGetUniformLocation && pglUniform1i && pglUniform1f && pglUniform2fv && pglUniform4fv && pglUniformMatrix4fv && pglGetShaderiv && pglGetShaderInfoLog && pglGetProgramiv && pglGetProgramInfoLog && pglDeleteProgram && pglGetAttachedShaders && pglGetAttribLocation && pglEnableVertexAttribArray && pglDisableVertexAttribArray && pglVertexAttribPointer; if (!shader_support) { RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n"); return false; } #endif glsl_shader = (struct gfx_shader*)calloc(1, sizeof(*glsl_shader)); if (!glsl_shader) return false; if (path) { bool ret; if (strcmp(path_get_extension(path), "glsl") == 0) { strlcpy(glsl_shader->pass[0].source.cg, path, sizeof(glsl_shader->pass[0].source.cg)); glsl_shader->passes = 1; glsl_shader->modern = true; ret = true; } else if (strcmp(path_get_extension(path), "glslp") == 0) { config_file_t *conf = config_file_new(path); if (conf) { ret = gfx_shader_read_conf_cgp(conf, glsl_shader); glsl_shader->modern = true; config_file_free(conf); } else ret = false; } else ret = gfx_shader_read_xml(path, glsl_shader); if (!ret) { RARCH_ERR("[GL]: Failed to parse GLSL shader.\n"); return false; } } else { RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n"); glsl_shader->passes = 1; glsl_shader->pass[0].source.xml.vertex = strdup(stock_vertex_modern); glsl_shader->pass[0].source.xml.fragment = strdup(stock_fragment_modern); glsl_shader->modern = true; } gfx_shader_resolve_relative(glsl_shader, path); #ifdef HAVE_OPENGLES2 if (!glsl_shader->modern) { RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n"); return false; } #endif const char *stock_vertex = glsl_shader->modern ? stock_vertex_modern : stock_vertex_legacy; const char *stock_fragment = glsl_shader->modern ? stock_fragment_modern : stock_fragment_legacy; if (!(gl_program[0] = compile_program(stock_vertex, stock_fragment, 0))) { RARCH_ERR("GLSL stock programs failed to compile.\n"); gl_glsl_free_shader(); return false; } if (!compile_programs(&gl_program[1])) { gl_glsl_free_shader(); return false; } if (!load_luts()) { RARCH_ERR("[GL]: Failed to load LUTs.\n"); gl_glsl_free_shader(); return false; } for (unsigned i = 0; i <= glsl_shader->passes; i++) find_uniforms(gl_program[i], &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 gl_state_tracker = state_tracker_init(&info); if (!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]; if (glsl_shader->modern) { gl_program[GL_SHADER_STOCK_BLEND] = compile_program(stock_vertex_modern_blend, stock_fragment_modern_blend, GL_SHADER_STOCK_BLEND); find_uniforms(gl_program[GL_SHADER_STOCK_BLEND], &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]; } gl_glsl_reset_attrib(); return true; }