mirror of
https://github.com/libretro/RetroArch
synced 2025-02-20 15:40:44 +00:00
Initial work on core GL context support.
This commit is contained in:
parent
bd4f7133a4
commit
b9fce188ea
13
dynamic.c
13
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "gfx_context.h"
|
||||
#include "general.h"
|
||||
#include <string.h>
|
||||
|
||||
#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];
|
||||
|
@ -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
|
||||
|
||||
|
138
gfx/gl.c
138
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
|
||||
|
||||
|
@ -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 ... <_<
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user