diff --git a/dynamic.c b/dynamic.c index a43dac8965..0b23eaff4b 100644 --- a/dynamic.c +++ b/dynamic.c @@ -653,6 +653,7 @@ static bool environment_cb(unsigned cmd, void *data) break; case RETRO_ENVIRONMENT_SET_HW_RENDER: + case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL: // ABI compat { RARCH_LOG("Environ SET_HW_RENDER.\n"); struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data; @@ -669,6 +670,7 @@ static bool environment_cb(unsigned cmd, void *data) break; case RETRO_HW_CONTEXT_OPENGL: + case RETRO_HW_CONTEXT_OPENGL_CORE: RARCH_ERR("Requesting OpenGL context, but RetroArch is compiled against OpenGLES2. Cannot use HW context.\n"); return false; #elif defined(HAVE_OPENGL) @@ -680,6 +682,11 @@ static bool environment_cb(unsigned cmd, void *data) RARCH_LOG("Requesting OpenGL context.\n"); driver.video = &video_gl; break; + + case RETRO_HW_CONTEXT_OPENGL_CORE: + RARCH_LOG("Requesting core OpenGL context (%u.%u).\n", cb->version_major, cb->version_minor); + driver.video = &video_gl; + break; #endif default: @@ -688,7 +695,11 @@ static bool environment_cb(unsigned cmd, void *data) } cb->get_current_framebuffer = driver_get_current_framebuffer; cb->get_proc_address = driver_get_proc_address; - memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb)); + + if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) // Old ABI. Don't copy garbage. + memcpy(&g_extern.system.hw_render_callback, cb, offsetof(struct retro_hw_render_callback, stencil)); + else + memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb)); break; } diff --git a/gfx/context/androidegl_ctx.c b/gfx/context/androidegl_ctx.c index 1fd6f67efd..254312e9bb 100644 --- a/gfx/context/androidegl_ctx.c +++ b/gfx/context/androidegl_ctx.c @@ -236,8 +236,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return ret; } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; g_api = api; return api == GFX_CTX_OPENGL_ES_API; } diff --git a/gfx/context/apple_gl_ctx.c b/gfx/context/apple_gl_ctx.c index d280bdf639..78f48f3208 100644 --- a/gfx/context/apple_gl_ctx.c +++ b/gfx/context/apple_gl_ctx.c @@ -27,8 +27,10 @@ #include "../../apple/RetroArch/rarch_wrapper.h" -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; #ifdef IOS return api == GFX_CTX_OPENGL_ES_API; #else diff --git a/gfx/context/bbqnx_ctx.c b/gfx/context/bbqnx_ctx.c index 532ba6ec9a..796ea931a1 100644 --- a/gfx/context/bbqnx_ctx.c +++ b/gfx/context/bbqnx_ctx.c @@ -362,8 +362,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return ret; } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; g_api = api; return api == GFX_CTX_OPENGL_ES_API; } diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index d730ac364a..67bda39585 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -553,8 +553,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return eglGetProcAddress(symbol); } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; g_api = api; switch (api) { diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index dcedf1cd39..fef98c4401 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -39,6 +39,13 @@ static unsigned g_screen; static GLXContext g_ctx; static GLXFBConfig g_fbc; +static unsigned g_major; +static unsigned g_minor; +static bool g_core; + +typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, + GLXFBConfig, GLXContext, Bool, const int*); +static glXCreateContextAttribsARBProc glx_create_context_attribs; static XF86VidModeModeInfo g_desktop_mode; static bool g_should_reset_mode; @@ -207,11 +214,26 @@ static bool gfx_ctx_init(void) if (!g_dpy) goto error; - // GLX 1.3+ required. int major, minor; glXQueryVersion(g_dpy, &major, &minor); - if (major < 1 || (major == 1 && minor < 3)) - goto error; + if (g_major * 1000 + g_minor >= 3001) // Core context + { + g_core = true; + // GLX 1.4+ required. + if ((major * 1000 + minor) < 1004) + goto error; + + glx_create_context_attribs = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + if (!glx_create_context_attribs) + goto error; + } + else + { + g_core = false; + // GLX 1.3+ required. + if ((major * 1000 + minor) < 1003) + goto error; + } int nelements; fbcs = glXChooseFBConfig(g_dpy, DefaultScreen(g_dpy), @@ -339,7 +361,20 @@ static bool gfx_ctx_set_video_mode( XEvent event; XIfEvent(g_dpy, &event, glx_wait_notify, NULL); - g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); + if (g_core) + { + const int attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, g_major, + GLX_CONTEXT_MINOR_VERSION_ARB, g_minor, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None, + }; + + g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs); + } + else + g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); + if (!g_ctx) { RARCH_ERR("[GLX]: Failed to create new context.\n"); @@ -460,6 +495,8 @@ static void gfx_ctx_destroy(void) g_inited = false; g_pglSwapInterval = NULL; + g_major = g_minor = 0; + g_core = false; } static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) @@ -486,8 +523,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return glXGetProcAddress((const GLubyte*)symbol); } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + g_major = major; + g_minor = minor; return api == GFX_CTX_OPENGL_API; } diff --git a/gfx/context/ps3_ctx.c b/gfx/context/ps3_ctx.c index e4731d9b9f..63d00d72e3 100644 --- a/gfx/context/ps3_ctx.c +++ b/gfx/context/ps3_ctx.c @@ -300,8 +300,10 @@ static void gfx_ctx_destroy(void) static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) { } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; return api == GFX_CTX_OPENGL_API || GFX_CTX_OPENGL_ES_API; } diff --git a/gfx/context/vc_egl_ctx.c b/gfx/context/vc_egl_ctx.c index 60ebec88b9..b9097751ff 100644 --- a/gfx/context/vc_egl_ctx.c +++ b/gfx/context/vc_egl_ctx.c @@ -243,8 +243,10 @@ static bool gfx_ctx_set_video_mode( return true; } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; g_api = api; switch (api) { diff --git a/gfx/context/wgl_ctx.c b/gfx/context/wgl_ctx.c index 700305407b..a39cb5a377 100644 --- a/gfx/context/wgl_ctx.c +++ b/gfx/context/wgl_ctx.c @@ -484,8 +484,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return (gfx_ctx_proc_t)wglGetProcAddress(symbol); } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; return api == GFX_CTX_OPENGL_API; } diff --git a/gfx/context/xdk_ctx.c b/gfx/context/xdk_ctx.c index fb23249048..3649934b09 100644 --- a/gfx/context/xdk_ctx.c +++ b/gfx/context/xdk_ctx.c @@ -260,8 +260,10 @@ static void gfx_ctx_xdk_destroy(void) static void gfx_ctx_xdk_input_driver(const input_driver_t **input, void **input_data) { } -static bool gfx_ctx_xdk_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_xdk_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; #if defined(_XBOX1) return api == GFX_CTX_DIRECT3D8_API; #elif defined(_XBOX360) diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index 94e99dd789..220f426b4d 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -555,8 +555,10 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return eglGetProcAddress(symbol); } -static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { + (void)major; + (void)minor; g_api = api; switch (api) { diff --git a/gfx/gfx_context.c b/gfx/gfx_context.c index 18e4958213..b97c651cda 100644 --- a/gfx/gfx_context.c +++ b/gfx/gfx_context.c @@ -14,6 +14,7 @@ */ #include "gfx_context.h" +#include "general.h" #include #ifdef HAVE_CONFIG_H @@ -55,7 +56,7 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = { const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident) { - for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(gfx_ctx_drivers); i++) { if (strcmp(gfx_ctx_drivers[i]->ident, ident) == 0) return gfx_ctx_drivers[i]; @@ -64,11 +65,11 @@ const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident) return NULL; } -const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api) +const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api, unsigned major, unsigned minor) { - for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(gfx_ctx_drivers); i++) { - if (gfx_ctx_drivers[i]->bind_api(api)) + if (gfx_ctx_drivers[i]->bind_api(api, major, minor)) { if (gfx_ctx_drivers[i]->init()) return gfx_ctx_drivers[i]; diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h index fa70e76e73..c8614799a5 100644 --- a/gfx/gfx_context.h +++ b/gfx/gfx_context.h @@ -41,7 +41,7 @@ typedef struct gfx_ctx_driver bool (*init)(void); void (*destroy)(void); - bool (*bind_api)(enum gfx_ctx_api); // Which API to bind to. + bool (*bind_api)(enum gfx_ctx_api, unsigned major, unsigned minor); // Which API to bind to. // Sets the swap interval. void (*swap_interval)(unsigned); @@ -111,7 +111,7 @@ extern const gfx_ctx_driver_t gfx_ctx_apple; extern const gfx_ctx_driver_t gfx_ctx_null; const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize. -const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api); // Finds first suitable driver and initializes. +const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api, unsigned major, unsigned minor); // Finds first suitable driver and initializes. #endif diff --git a/gfx/gl.c b/gfx/gl.c index bec4389a92..cb2c1ee7e9 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -138,6 +138,29 @@ static bool load_sync_proc(gl_t *gl) } #endif +#ifndef HAVE_OPENGLES +static PFNGLGENVERTEXARRAYSPROC pglGenVertexArrays; +static PFNGLBINDVERTEXARRAYPROC pglBindVertexArray; +static PFNGLDELETEVERTEXARRAYSPROC pglDeleteVertexArrays; + +static bool load_vao_proc(gl_t *gl) +{ + if (!gl_query_extension("ARB_vertex_array_object")) + return false; + + LOAD_GL_SYM(GenVertexArrays); + LOAD_GL_SYM(BindVertexArray); + LOAD_GL_SYM(DeleteVertexArrays); + + bool present = pglGenVertexArrays && pglBindVertexArray && pglDeleteVertexArrays; + if (!present) + return false; + + pglGenVertexArrays(1, &gl->vao); + return true; +} +#endif + #ifdef HAVE_FBO #if defined(_WIN32) && !defined(RARCH_CONSOLE) static PFNGLGENFRAMEBUFFERSPROC pglGenFramebuffers; @@ -667,20 +690,6 @@ void gl_init_fbo(void *data, unsigned width, unsigned height) #ifndef HAVE_RGL -// GLES and GL inconsistency. -#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT -#endif -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT -#endif -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT -#endif -#ifndef GL_FRAMEBUFFER_UNSUPPORTED -#define GL_FRAMEBUFFER_UNSUPPORTED GL_FRAMEBUFFER_UNSUPPORTED_EXT -#endif - bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) { RARCH_LOG("[GL]: Initializing HW render (%u x %u).\n", width, height); @@ -697,6 +706,12 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) pglGenFramebuffers(TEXTURES, gl->hw_render_fbo); bool depth = g_extern.system.hw_render_callback.depth; + bool stencil = g_extern.system.hw_render_callback.stencil; + +#ifdef HAVE_OPENGLES2 + if (stencil && !gl_query_extension("OES_packed_depth_stencil")) + return false; +#endif if (depth) { @@ -711,29 +726,47 @@ bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height) if (depth) { - pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_depth[i]); - pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, - width, height); - pglBindRenderbuffer(GL_RENDERBUFFER, 0); - pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, gl->hw_render_depth[i]); + GLenum component = GL_DEPTH_COMPONENT16; + GLenum attachment = GL_DEPTH_ATTACHMENT; + if (stencil) + { +#ifdef HAVE_OPENGLES2 + // GLES2 is a bit weird, as always. :P + pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_depth[i]); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, + width, height); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); + + // There's no GL_DEPTH_STENCIL_ATTACHMENT like in desktop GL. + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_depth[i]); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_depth[i]); +#else + // We use ARB FBO extensions, no need to check. + pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_depth[i]); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + width, height); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_depth[i]); +#endif + } + else + { + pglBindRenderbuffer(GL_RENDERBUFFER, gl->hw_render_depth[i]); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + width, height); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl->hw_render_depth[i]); + } } GLenum status = pglCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - RARCH_ERR("[GL]: Failed to create HW render FBO #%u.\n", i); - const char *err = NULL; - switch (status) - { - - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: err = "Incomplete Attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: err = "Incomplete Dimensions"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: err = "Missing Attachment"; break; - case GL_FRAMEBUFFER_UNSUPPORTED: err = "Unsupported"; break; - default: err = "Unknown"; break; - } - RARCH_ERR("[GL]: Error: %s.\n", err); + RARCH_ERR("[GL]: Failed to create HW render FBO #%u, error: 0x%u.\n", i, (unsigned)status); return false; } } @@ -1380,8 +1413,11 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei RARCH_PERFORMANCE_START(frame_run); gl_t *gl = (gl_t*)data; - uint64_t lifecycle_mode_state = g_extern.lifecycle_mode_state; - (void)lifecycle_mode_state; + +#ifndef HAVE_OPENGLES + if (gl->core_context) + pglBindVertexArray(gl->vao); +#endif if (gl->shader) gl->shader->use(1); @@ -1543,6 +1579,11 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei } #endif +#ifndef HAVE_OPENGLES + if (gl->core_context) + pglBindVertexArray(0); +#endif + return true; } @@ -1614,11 +1655,18 @@ static void gl_free(void *data) #endif #endif +#ifndef HAVE_OPENGLES + if (gl->core_context) + { + pglBindVertexArray(0); + pglDeleteVertexArrays(1, &gl->vao); + } +#endif + context_destroy_func(); free(gl->empty_buf); free(gl->conv_buffer); - free(gl); } @@ -1640,6 +1688,17 @@ static bool resolve_extensions(gl_t *gl) return false; #endif +#ifndef HAVE_OPENGLES + gl->core_context = g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGL_CORE; + RARCH_LOG("[GL]: Using Core GL context.\n"); + if (gl->core_context && + !load_vao_proc(gl)) + { + RARCH_ERR("[GL]: Failed to init VAOs.\n"); + return false; + } +#endif + #ifdef HAVE_GL_SYNC gl->have_sync = load_sync_proc(gl); if (gl->have_sync && g_settings.video.hard_sync) @@ -1779,6 +1838,8 @@ static void gl_init_pbo_readback(void *data) static const gfx_ctx_driver_t *gl_get_context(void) { + unsigned major = g_extern.system.hw_render_callback.version_major; + unsigned minor = g_extern.system.hw_render_callback.version_minor; #ifdef HAVE_OPENGLES enum gfx_ctx_api api = GFX_CTX_OPENGL_ES_API; const char *api_name = "OpenGL ES"; @@ -1792,7 +1853,7 @@ static const gfx_ctx_driver_t *gl_get_context(void) const gfx_ctx_driver_t *ctx = gfx_ctx_find_driver(g_settings.video.gl_context); if (ctx) { - if (!ctx->bind_api(api)) + if (!ctx->bind_api(api, major, minor)) { RARCH_ERR("Failed to bind API %s to context %s.\n", api_name, g_settings.video.gl_context); return NULL; @@ -1813,7 +1874,7 @@ static const gfx_ctx_driver_t *gl_get_context(void) return ctx; } else - return gfx_ctx_init_first(api); + return gfx_ctx_init_first(api, major, minor); } static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) @@ -1923,7 +1984,8 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo #ifdef HAVE_OPENGLES2 gl->hw_render_use = g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGLES2; #else - gl->hw_render_use = g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGL; + gl->hw_render_use = g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGL || + g_extern.system.hw_render_callback.context_type == RETRO_HW_CONTEXT_OPENGL_CORE; #endif #endif diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 9eeeb50124..1f004d81c3 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -284,6 +284,11 @@ typedef struct gl GLsync fences[MAX_FENCES]; unsigned fence_count; #endif + +#ifndef HAVE_OPENGLES + bool core_context; + GLuint vao; +#endif } gl_t; // Windows ... <_< diff --git a/libretro.h b/libretro.h index 9f55186db5..937bbea6c6 100755 --- a/libretro.h +++ b/libretro.h @@ -434,7 +434,7 @@ enum retro_mod // Sets an interface which frontend can use to eject and insert disk images. // This is used for games which consist of multiple images and must be manually // swapped out by the user (e.g. PSX). -#define RETRO_ENVIRONMENT_SET_HW_RENDER (14 | RETRO_ENVIRONMENT_EXPERIMENTAL) +#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 // struct retro_hw_render_callback * -- // NOTE: This call is currently very experimental, and should not be considered part of the public API. // The interface could be changed or removed at any time. @@ -509,6 +509,7 @@ enum retro_hw_context_type RETRO_HW_CONTEXT_NONE = 0, RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0 + RETRO_HW_CONTEXT_OPENGL_CORE, // Modern desktop core GL context. Use major/minor fields to set GL version. RETRO_HW_CONTEXT_DUMMY = INT_MAX }; @@ -520,6 +521,10 @@ struct retro_hw_render_callback retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. retro_hw_get_proc_address_t get_proc_address; // Set by frontend. bool depth; // Set if render buffers should have depth component attached. + bool stencil; // Set if stencil buffers should be attached. + // If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored. + unsigned version_major; // Major version number for core GL context. + unsigned version_minor; // Minor version number for core GL context. }; // Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.