Add HW context support to X/EGL and KMS/EGL.

This commit is contained in:
Themaister 2014-04-19 16:06:12 +02:00
parent f658112756
commit 105872a42c
9 changed files with 86 additions and 15 deletions

View File

@ -47,6 +47,8 @@
#include <sys/poll.h> #include <sys/poll.h>
#include <fcntl.h> #include <fcntl.h>
static bool g_use_hw_ctx;
static EGLContext g_egl_hw_ctx;
static EGLContext g_egl_ctx; static EGLContext g_egl_ctx;
static EGLSurface g_egl_surf; static EGLSurface g_egl_surf;
static EGLDisplay g_egl_dpy; static EGLDisplay g_egl_dpy;
@ -593,9 +595,19 @@ static bool gfx_ctx_set_video_mode(void *data,
goto error; goto error;
g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, (g_api == GFX_CTX_OPENGL_ES_API) ? gles_context_attribs : NULL); g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, (g_api == GFX_CTX_OPENGL_ES_API) ? gles_context_attribs : NULL);
if (!g_egl_ctx) if (g_egl_ctx == EGL_NO_CONTEXT)
goto error; goto error;
if (g_use_hw_ctx)
{
g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_config, g_egl_ctx,
(g_api == GFX_CTX_OPENGL_ES_API) ? gles_context_attribs : NULL);
RARCH_LOG("[KMS/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);
if (g_egl_hw_ctx == EGL_NO_CONTEXT)
goto error;
}
g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, (EGLNativeWindowType)g_gbm_surface, NULL); g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, (EGLNativeWindowType)g_gbm_surface, NULL);
if (!g_egl_surf) if (!g_egl_surf)
goto error; goto error;
@ -636,6 +648,9 @@ void gfx_ctx_destroy(void *data)
eglDestroyContext(g_egl_dpy, g_egl_ctx); eglDestroyContext(g_egl_dpy, g_egl_ctx);
} }
if (g_egl_hw_ctx)
eglDestroyContext(g_egl_dpy, g_egl_hw_ctx);
if (g_egl_surf) if (g_egl_surf)
eglDestroySurface(g_egl_dpy, g_egl_surf); eglDestroySurface(g_egl_dpy, g_egl_surf);
eglTerminate(g_egl_dpy); eglTerminate(g_egl_dpy);
@ -717,6 +732,14 @@ static bool gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major, u
} }
} }
static void gfx_ctx_bind_hw_render(void *data, bool enable)
{
(void)data;
g_use_hw_ctx = enable;
if (g_egl_dpy)
eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, enable ? g_egl_hw_ctx : g_egl_ctx);
}
const gfx_ctx_driver_t gfx_ctx_drm_egl = { const gfx_ctx_driver_t gfx_ctx_drm_egl = {
gfx_ctx_init, gfx_ctx_init,
gfx_ctx_destroy, gfx_ctx_destroy,
@ -736,5 +759,6 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = {
NULL, NULL,
NULL, NULL,
"kms-egl", "kms-egl",
gfx_ctx_bind_hw_render,
}; };

View File

@ -40,6 +40,7 @@ static unsigned g_screen;
static XIM g_xim; static XIM g_xim;
static XIC g_xic; static XIC g_xic;
static bool g_use_hw_ctx;
static GLXContext g_ctx, g_hw_ctx; static GLXContext g_ctx, g_hw_ctx;
static GLXFBConfig g_fbc; static GLXFBConfig g_fbc;
static unsigned g_major; static unsigned g_major;
@ -413,15 +414,26 @@ static bool gfx_ctx_set_video_mode(void *data,
*aptr = None; *aptr = None;
g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs); g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs);
g_hw_ctx = glx_create_context_attribs(g_dpy, g_fbc, g_ctx, True, attribs); if (g_use_hw_ctx)
{
RARCH_LOG("[GLX]: Creating shared HW context.\n");
g_hw_ctx = glx_create_context_attribs(g_dpy, g_fbc, g_ctx, True, attribs);
if (!g_hw_ctx)
RARCH_ERR("[GLX]: Failed to create new shared context.\n");
}
} }
else else
{ {
g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True); g_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, 0, True);
g_hw_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, g_ctx, True); if (g_use_hw_ctx)
{
g_hw_ctx = glXCreateNewContext(g_dpy, g_fbc, GLX_RGBA_TYPE, g_ctx, True);
if (!g_hw_ctx)
RARCH_ERR("[GLX]: Failed to create new shared context.\n");
}
} }
if (!g_ctx || !g_hw_ctx) if (!g_ctx)
{ {
RARCH_ERR("[GLX]: Failed to create new context.\n"); RARCH_ERR("[GLX]: Failed to create new context.\n");
goto error; goto error;
@ -504,7 +516,8 @@ static void gfx_ctx_destroy(void *data)
glXMakeContextCurrent(g_dpy, None, None, NULL); glXMakeContextCurrent(g_dpy, None, None, NULL);
if (!driver.video_cache_context) if (!driver.video_cache_context)
{ {
glXDestroyContext(g_dpy, g_hw_ctx); if (g_hw_ctx)
glXDestroyContext(g_dpy, g_hw_ctx);
glXDestroyContext(g_dpy, g_ctx); glXDestroyContext(g_dpy, g_ctx);
g_ctx = NULL; g_ctx = NULL;
g_hw_ctx = NULL; g_hw_ctx = NULL;
@ -605,8 +618,13 @@ static void gfx_ctx_show_mouse(void *data, bool state)
static void gfx_ctx_bind_hw_render(void *data, bool enable) static void gfx_ctx_bind_hw_render(void *data, bool enable)
{ {
(void)data; (void)data;
RARCH_LOG("[GLX]: Binding context (%s): %p\n", enable ? "RetroArch" : "HW render", enable ? (void*)g_hw_ctx : (void*)g_ctx); g_use_hw_ctx = enable;
glXMakeContextCurrent(g_dpy, g_glx_win, g_glx_win, enable ? g_hw_ctx : g_ctx);
if (g_dpy)
{
//RARCH_LOG("[GLX]: Binding context (%s): %p\n", enable ? "RetroArch" : "HW render", enable ? (void*)g_hw_ctx : (void*)g_ctx);
glXMakeContextCurrent(g_dpy, g_glx_win, g_glx_win, enable ? g_hw_ctx : g_ctx);
}
} }
const gfx_ctx_driver_t gfx_ctx_glx = { const gfx_ctx_driver_t gfx_ctx_glx = {

View File

@ -41,6 +41,8 @@ static unsigned g_screen;
static XIM g_xim; static XIM g_xim;
static XIC g_xic; static XIC g_xic;
static bool g_use_hw_ctx;
static EGLContext g_egl_hw_ctx;
static EGLContext g_egl_ctx; static EGLContext g_egl_ctx;
static EGLSurface g_egl_surf; static EGLSurface g_egl_surf;
static EGLDisplay g_egl_dpy; static EGLDisplay g_egl_dpy;
@ -422,10 +424,19 @@ static bool gfx_ctx_set_video_mode(void *data,
(g_api == GFX_CTX_OPENGL_ES_API) ? egl_ctx_gles_attribs : NULL); (g_api == GFX_CTX_OPENGL_ES_API) ? egl_ctx_gles_attribs : NULL);
RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx); RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx);
if (g_egl_ctx == EGL_NO_CONTEXT)
if (!g_egl_ctx)
goto error; goto error;
if (g_use_hw_ctx)
{
g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_config, g_egl_ctx,
(g_api == GFX_CTX_OPENGL_ES_API) ? egl_ctx_gles_attribs : NULL);
RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);
if (g_egl_hw_ctx == EGL_NO_CONTEXT)
goto error;
}
g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, (EGLNativeWindowType)g_win, NULL); g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, (EGLNativeWindowType)g_win, NULL);
if (!g_egl_surf) if (!g_egl_surf)
goto error; goto error;
@ -513,6 +524,9 @@ static void gfx_ctx_destroy(void *data)
eglDestroyContext(g_egl_dpy, g_egl_ctx); eglDestroyContext(g_egl_dpy, g_egl_ctx);
} }
if (g_egl_hw_ctx)
eglDestroyContext(g_egl_dpy, g_egl_hw_ctx);
if (g_egl_surf) if (g_egl_surf)
eglDestroySurface(g_egl_dpy, g_egl_surf); eglDestroySurface(g_egl_dpy, g_egl_surf);
eglTerminate(g_egl_dpy); eglTerminate(g_egl_dpy);
@ -622,6 +636,14 @@ static void gfx_ctx_show_mouse(void *data, bool state)
x11_show_mouse(g_dpy, g_win, state); x11_show_mouse(g_dpy, g_win, state);
} }
static void gfx_ctx_bind_hw_render(void *data, bool enable)
{
(void)data;
g_use_hw_ctx = enable;
if (g_egl_dpy)
eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, enable ? g_egl_hw_ctx : g_egl_ctx);
}
const gfx_ctx_driver_t gfx_ctx_x_egl = { const gfx_ctx_driver_t gfx_ctx_x_egl = {
gfx_ctx_init, gfx_ctx_init,
gfx_ctx_destroy, gfx_ctx_destroy,
@ -641,5 +663,6 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = {
NULL, NULL,
gfx_ctx_show_mouse, gfx_ctx_show_mouse,
"x-egl", "x-egl",
gfx_ctx_bind_hw_render,
}; };

View File

@ -1405,7 +1405,7 @@ static const gfx_ctx_driver_t *d3d_get_context(void)
major = 9; major = 9;
#endif #endif
minor = 0; minor = 0;
return gfx_ctx_init_first(driver.video_data, api, major, minor); return gfx_ctx_init_first(driver.video_data, api, major, minor, false);
} }
static void *d3d_init(const video_info_t *info, const input_driver_t **input, static void *d3d_init(const video_info_t *info, const input_driver_t **input,

View File

@ -71,13 +71,15 @@ const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident)
return NULL; return NULL;
} }
const gfx_ctx_driver_t *gfx_ctx_init_first(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor) const gfx_ctx_driver_t *gfx_ctx_init_first(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor, bool hw_render_ctx)
{ {
unsigned i; unsigned i;
for (i = 0; gfx_ctx_drivers[i]; i++) for (i = 0; gfx_ctx_drivers[i]; i++)
{ {
if (gfx_ctx_drivers[i]->bind_api(data, api, major, minor)) if (gfx_ctx_drivers[i]->bind_api(data, api, major, minor))
{ {
if (gfx_ctx_drivers[i]->bind_hw_render)
gfx_ctx_drivers[i]->bind_hw_render(data, hw_render_ctx);
if (gfx_ctx_drivers[i]->init(data)) if (gfx_ctx_drivers[i]->init(data))
return gfx_ctx_drivers[i]; return gfx_ctx_drivers[i];
} }

View File

@ -123,7 +123,7 @@ extern const gfx_ctx_driver_t gfx_ctx_emscripten;
extern const gfx_ctx_driver_t gfx_ctx_null; 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_find_driver(const char *ident); // Finds driver with ident. Does not initialize.
const gfx_ctx_driver_t *gfx_ctx_init_first(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor); // Finds first suitable driver and initializes. const gfx_ctx_driver_t *gfx_ctx_init_first(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor, bool hw_render_ctx); // Finds first suitable driver and initializes.
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1927,6 +1927,10 @@ static const gfx_ctx_driver_t *gl_get_context(gl_t *gl)
return NULL; return NULL;
} }
// Enables or disables offscreen HW context.
if (ctx->bind_hw_render)
ctx->bind_hw_render(gl, cb->context_type != RETRO_HW_CONTEXT_NONE);
if (!ctx->init(gl)) if (!ctx->init(gl))
{ {
RARCH_ERR("Failed to init GL context: %s.\n", ctx->ident); RARCH_ERR("Failed to init GL context: %s.\n", ctx->ident);
@ -1942,7 +1946,7 @@ static const gfx_ctx_driver_t *gl_get_context(gl_t *gl)
return ctx; return ctx;
} }
else else
return gfx_ctx_init_first(gl, api, major, minor); return gfx_ctx_init_first(gl, api, major, minor, cb->context_type != RETRO_HW_CONTEXT_NONE);
} }
#ifdef GL_DEBUG #ifdef GL_DEBUG

View File

@ -87,7 +87,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
if (!vg) if (!vg)
return NULL; return NULL;
vg->driver = gfx_ctx_init_first(vg, GFX_CTX_OPENVG_API, 0, 0); vg->driver = gfx_ctx_init_first(vg, GFX_CTX_OPENVG_API, 0, 0, false);
if (!vg->driver) if (!vg->driver)
{ {

View File

@ -299,7 +299,7 @@ static const gfx_ctx_driver_t *d3d_get_context(void *data)
major = 9; major = 9;
#endif #endif
minor = 0; minor = 0;
return gfx_ctx_init_first(d3d, api, major, minor); return gfx_ctx_init_first(d3d, api, major, minor, false);
} }
static bool d3d_init_base(void *data, const video_info_t *info) static bool d3d_init_base(void *data, const video_info_t *info)