diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index e8b92099c8..18c9103157 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -47,6 +47,8 @@ #include #include +static bool g_use_hw_ctx; +static EGLContext g_egl_hw_ctx; static EGLContext g_egl_ctx; static EGLSurface g_egl_surf; static EGLDisplay g_egl_dpy; @@ -593,9 +595,19 @@ static bool gfx_ctx_set_video_mode(void *data, 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); - if (!g_egl_ctx) + if (g_egl_ctx == EGL_NO_CONTEXT) 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); if (!g_egl_surf) goto error; @@ -636,6 +648,9 @@ void gfx_ctx_destroy(void *data) eglDestroyContext(g_egl_dpy, g_egl_ctx); } + if (g_egl_hw_ctx) + eglDestroyContext(g_egl_dpy, g_egl_hw_ctx); + if (g_egl_surf) eglDestroySurface(g_egl_dpy, g_egl_surf); 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 = { gfx_ctx_init, gfx_ctx_destroy, @@ -736,5 +759,6 @@ const gfx_ctx_driver_t gfx_ctx_drm_egl = { NULL, NULL, "kms-egl", + gfx_ctx_bind_hw_render, }; diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index cd2885d750..c52298173a 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -40,6 +40,7 @@ static unsigned g_screen; static XIM g_xim; static XIC g_xic; +static bool g_use_hw_ctx; static GLXContext g_ctx, g_hw_ctx; static GLXFBConfig g_fbc; static unsigned g_major; @@ -413,15 +414,26 @@ static bool gfx_ctx_set_video_mode(void *data, *aptr = None; 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 { 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"); goto error; @@ -504,7 +516,8 @@ static void gfx_ctx_destroy(void *data) glXMakeContextCurrent(g_dpy, None, None, NULL); 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); g_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) { (void)data; - 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); + g_use_hw_ctx = enable; + + 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 = { diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index 1877754d53..ae1628f76d 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -41,6 +41,8 @@ static unsigned g_screen; static XIM g_xim; static XIC g_xic; +static bool g_use_hw_ctx; +static EGLContext g_egl_hw_ctx; static EGLContext g_egl_ctx; static EGLSurface g_egl_surf; 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); RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx); - - if (!g_egl_ctx) + if (g_egl_ctx == EGL_NO_CONTEXT) 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); if (!g_egl_surf) goto error; @@ -513,6 +524,9 @@ static void gfx_ctx_destroy(void *data) eglDestroyContext(g_egl_dpy, g_egl_ctx); } + if (g_egl_hw_ctx) + eglDestroyContext(g_egl_dpy, g_egl_hw_ctx); + if (g_egl_surf) eglDestroySurface(g_egl_dpy, g_egl_surf); 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); } +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 = { gfx_ctx_init, gfx_ctx_destroy, @@ -641,5 +663,6 @@ const gfx_ctx_driver_t gfx_ctx_x_egl = { NULL, gfx_ctx_show_mouse, "x-egl", + gfx_ctx_bind_hw_render, }; diff --git a/gfx/d3d9/d3d.cpp b/gfx/d3d9/d3d.cpp index 405ac249cf..9e0c7afbab 100644 --- a/gfx/d3d9/d3d.cpp +++ b/gfx/d3d9/d3d.cpp @@ -1405,7 +1405,7 @@ static const gfx_ctx_driver_t *d3d_get_context(void) major = 9; #endif 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, diff --git a/gfx/gfx_context.c b/gfx/gfx_context.c index 065914a911..04576bf578 100644 --- a/gfx/gfx_context.c +++ b/gfx/gfx_context.c @@ -71,13 +71,15 @@ const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident) 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; 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_hw_render) + gfx_ctx_drivers[i]->bind_hw_render(data, hw_render_ctx); if (gfx_ctx_drivers[i]->init(data)) return gfx_ctx_drivers[i]; } diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h index 90f173776c..80cc01d94f 100644 --- a/gfx/gfx_context.h +++ b/gfx/gfx_context.h @@ -123,7 +123,7 @@ extern const gfx_ctx_driver_t gfx_ctx_emscripten; 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(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 } diff --git a/gfx/gl.c b/gfx/gl.c index 6172155e7c..df3ced4538 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -1927,6 +1927,10 @@ static const gfx_ctx_driver_t *gl_get_context(gl_t *gl) 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)) { 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; } 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 diff --git a/gfx/vg.c b/gfx/vg.c index 706a0000e2..0ee6018d98 100644 --- a/gfx/vg.c +++ b/gfx/vg.c @@ -87,7 +87,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo if (!vg) 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) { diff --git a/xdk/xdk_d3d.cpp b/xdk/xdk_d3d.cpp index 6f0d24bbc7..f35ee7eb17 100644 --- a/xdk/xdk_d3d.cpp +++ b/xdk/xdk_d3d.cpp @@ -299,7 +299,7 @@ static const gfx_ctx_driver_t *d3d_get_context(void *data) major = 9; #endif 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)