bool retro_load_game(const struct retro_game_info *info) { retro_variable var; if (!info) return false; strcpy(retro_path_info, info->path); if (strstr(info->path, ".obj") || strstr(info->path, ".mtl")) engine_program_cb = &engine_program_modelviewer; else engine_program_cb = &engine_program_instancingviewer; update_variables(); var.key = "3dengine-sensor-enable"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enabled")) { if (sensor_initialized) return true; log_cb(RETRO_LOG_INFO, "Sensor interface found, enabling...\n"); if (sensor_cb.set_sensor_state) { sensor_cb.set_sensor_state(0, RETRO_SENSOR_ACCELEROMETER_ENABLE, FPS); sensor_enable = true; } sensor_initialized = true; } if (!strcmp(var.value, "disabled")) { if (sensor_initialized) return true; log_cb(RETRO_LOG_INFO, "Sensor interface found, disabling...\n"); if (sensor_cb.set_sensor_state) { sensor_cb.set_sensor_state(0, RETRO_SENSOR_ACCELEROMETER_DISABLE, FPS); sensor_enable = false; } } } var.key = "3dengine-location-enable"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enabled")) { location_enable = true; location_cb.initialized = location_initialized; location_cb.deinitialized = location_deinitialized; environ_cb(RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE, &location_cb); } } memset(&camera_cb, 0, sizeof(camera_cb)); enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { if (log_cb) log_cb(RETRO_LOG_ERROR, "XRGB8888 is not supported.\n"); return false; } var.key = "3dengine-camera-enable"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enabled")) { camera_enable = true; var.key = "3dengine-camera-type"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "texture")) { camera_cb.caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE); camera_cb.frame_opengl_texture = camera_gl_callback; } else { camera_cb.caps = (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER); camera_cb.frame_raw_framebuffer = camera_raw_fb_callback; } } camera_cb.initialized = camera_initialized; if (camera_enable && !environ_cb(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &camera_cb)) { if (log_cb) log_cb(RETRO_LOG_ERROR, "camera is not supported.\n"); return false; } } } #ifdef HAVE_OPENGLES hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; #else hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; #endif hw_render.context_reset = context_reset; hw_render.depth = true; if (!camera_enable) hw_render.bottom_left_origin = true; if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) return false; #ifdef HAVE_OPENGLES if (camera_enable && camera_cb.caps & (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER) && !gl_query_extension("BGRA8888")) { if (log_cb) log_cb(RETRO_LOG_ERROR, "no BGRA8888 support for raw framebuffer, exiting...\n"); return false; } support_unpack_row_length = gl_query_extension("GL_EXT_unpack_subimage"); #else support_unpack_row_length = true; #endif if (log_cb) log_cb(RETRO_LOG_INFO, "Loaded game!\n"); if (engine_program_cb && engine_program_cb->load_game) engine_program_cb->load_game(info); return true; }
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; }
bool gl_check_capability(enum gl_capability_enum enum_idx) { unsigned major = 0; unsigned minor = 0; const char *vendor = (const char*)glGetString(GL_VENDOR); const char *renderer = (const char*)glGetString(GL_RENDERER); const char *version = (const char*)glGetString(GL_VERSION); #ifdef HAVE_OPENGLES if (version && sscanf(version, "OpenGL ES %u.%u", &major, &minor) != 2) #else if (version && sscanf(version, "%u.%u", &major, &minor) != 2) #endif major = minor = 0; (void)vendor; switch (enum_idx) { case GL_CAPS_GLES3_SUPPORTED: #if defined(HAVE_OPENGLES) if (major >= 3) return true; #endif break; case GL_CAPS_EGLIMAGE: #if defined(HAVE_EGL) && defined(HAVE_OPENGLES) if (glEGLImageTargetTexture2DOES != NULL) return true; #endif break; case GL_CAPS_SYNC: #ifdef HAVE_OPENGLES if (major >= 3) return true; #else if (gl_query_extension("ARB_sync") && glFenceSync && glDeleteSync && glClientWaitSync) return true; #endif break; case GL_CAPS_MIPMAP: { static bool extension_queried = false; static bool extension = false; if (!extension_queried) { extension = gl_query_extension("ARB_framebuffer_object"); extension_queried = true; } if (extension) return true; } break; case GL_CAPS_VAO: #ifndef HAVE_OPENGLES if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_vertex_array_object")) return false; if (glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays) return true; #endif break; case GL_CAPS_FBO: #if defined(HAVE_PSGL) || defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1) || defined(HAVE_OPENGLES_3_2) return true; #elif defined(HAVE_FBO) if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_framebuffer_object") && !gl_query_extension("EXT_framebuffer_object")) return false; if (glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glCheckFramebufferStatus && glDeleteFramebuffers && glGenRenderbuffers && glBindRenderbuffer && glFramebufferRenderbuffer && glRenderbufferStorage && glDeleteRenderbuffers) return true; break; #else break; #endif case GL_CAPS_ARGB8: #ifdef HAVE_OPENGLES if (gl_query_extension("OES_rgb8_rgba8") || gl_query_extension("ARM_argb8")) return true; #else /* TODO/FIXME - implement this for non-GLES? */ #endif break; case GL_CAPS_DEBUG: if (gl_query_extension("KHR_debug")) return true; #ifndef HAVE_OPENGLES if (gl_query_extension("ARB_debug_output")) return true; #endif break; case GL_CAPS_PACKED_DEPTH_STENCIL: { struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); if (major >= 3) return true; if (hwr->stencil && !gl_query_extension("OES_packed_depth_stencil") && !gl_query_extension("EXT_packed_depth_stencil")) return false; } return true; case GL_CAPS_ES2_COMPAT: #ifndef HAVE_OPENGLES /* ATI card detected, skipping check for GL_RGB565 support... */ if (vendor && renderer && (strstr(vendor, "ATI") || strstr(renderer, "ATI"))) return false; if (gl_query_extension("ARB_ES2_compatibility")) return true; #endif break; case GL_CAPS_UNPACK_ROW_LENGTH: #ifdef HAVE_OPENGLES if (major >= 3) return true; /* Extension GL_EXT_unpack_subimage, can copy textures faster * than using UNPACK_ROW_LENGTH */ if (gl_query_extension("GL_EXT_unpack_subimage")) return true; #endif break; case GL_CAPS_FULL_NPOT_SUPPORT: if (major >= 3) return true; #ifdef HAVE_OPENGLES if (gl_query_extension("ARB_texture_non_power_of_two") || gl_query_extension("OES_texture_npot")) return true; #else { GLint max_texture_size = 0; GLint max_native_instr = 0; /* try to detect actual npot support. might fail for older cards. */ bool arb_npot = gl_query_extension("ARB_texture_non_power_of_two"); bool arb_frag_program = gl_query_extension("ARB_fragment_program"); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); #ifdef GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB if (arb_frag_program && glGetProgramivARB) glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &max_native_instr); #endif if (arb_npot && arb_frag_program && (max_texture_size >= 8192) && (max_native_instr >= 4096)) return true; } #endif break; case GL_CAPS_SRGB_FBO_ES3: #ifdef HAVE_OPENGLES if (major >= 3) return true; #else break; #endif case GL_CAPS_SRGB_FBO: #if defined(HAVE_OPENGLES) if (major >= 3 || gl_query_extension("EXT_sRGB")) return true; #elif defined(HAVE_FBO) if (gl_query_core_context_in_use() || (gl_query_extension("EXT_texture_sRGB") && gl_query_extension("ARB_framebuffer_sRGB"))) return true; #endif break; case GL_CAPS_FP_FBO: /* GLES - No extensions for float FBO currently. */ #ifndef HAVE_OPENGLES #ifdef HAVE_FBO /* Float FBO is core in 3.2. */ if (gl_query_core_context_in_use() || gl_query_extension("ARB_texture_float")) return true; #endif #endif break; case GL_CAPS_BGRA8888: #ifdef HAVE_OPENGLES /* There are both APPLE and EXT variants. */ /* Videocore hardware supports BGRA8888 extension, but * should be purposefully avoided. */ if (gl_query_extension("BGRA8888") && !strstr(renderer, "VideoCore")) return true; #else /* TODO/FIXME - implement this for non-GLES? */ #endif break; case GL_CAPS_NONE: default: break; } return false; }