diff --git a/Makefile b/Makefile index 0df3f12180..40b9356e4e 100644 --- a/Makefile +++ b/Makefile @@ -232,7 +232,7 @@ ifeq ($(HAVE_OPENGL), 1) ifeq ($(HAVE_GLES), 1) LIBS += -lGLESv2 - DEFINES += -DHAVE_OPENGLES -DHAVE_OPENGLES2 + DEFINES += -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_OPENGLES3 OBJ += gfx/glsym/glsym_es2.o else DEFINES += -DHAVE_GL_SYNC diff --git a/dynamic.c b/dynamic.c index 4ab9ca70b6..ee1eb01e6d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -698,7 +698,11 @@ bool rarch_environment_cb(unsigned cmd, void *data) #if defined(HAVE_OPENGLES2) case RETRO_HW_CONTEXT_OPENGLES2: - RARCH_LOG("Requesting OpenGLES2 context.\n"); +#if defined(HAVE_OPENGLES3) + case RETRO_HW_CONTEXT_OPENGLES3: +#endif + RARCH_LOG("Requesting OpenGLES%u context.\n", + cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); break; case RETRO_HW_CONTEXT_OPENGL: @@ -707,7 +711,9 @@ bool rarch_environment_cb(unsigned cmd, void *data) return false; #elif defined(HAVE_OPENGL) case RETRO_HW_CONTEXT_OPENGLES2: - RARCH_ERR("Requesting OpenGLES2 context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n"); + case RETRO_HW_CONTEXT_OPENGLES3: + RARCH_ERR("Requesting OpenGLES%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n", + cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); return false; case RETRO_HW_CONTEXT_OPENGL: diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index 79e42026a7..2c2c0673a5 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -55,6 +55,8 @@ static volatile sig_atomic_t g_quit; static bool g_inited; static unsigned g_interval; static enum gfx_ctx_api g_api; +static unsigned g_major; +static unsigned g_minor; static struct gbm_device *g_gbm_dev; static struct gbm_surface *g_gbm_surface; @@ -393,15 +395,23 @@ static bool gfx_ctx_set_video_mode( EGL_NONE, }; +#ifdef EGL_OPENGL_ES3_BIT_KHR + static const EGLint egl_attribs_gles3[] = { + EGL_ATTRIBS_BASE, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, + EGL_NONE, + }; +#endif + static const EGLint egl_attribs_vg[] = { EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; - // GLES 2.0. Don't use for any other API. - static const EGLint gles_context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, + // GLES 2.0+. Don't use for any other API. + const EGLint gles_context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, g_major ? g_major : 2, EGL_NONE }; @@ -412,6 +422,11 @@ static bool gfx_ctx_set_video_mode( attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: +#ifdef EGL_OPENGL_ES3_BIT_KHR + if (g_major >= 3) + attrib_ptr = egl_attribs_gles3; + else +#endif attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: @@ -568,14 +583,18 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { - (void)major; - (void)minor; + g_major = major; + g_minor = minor; g_api = api; switch (api) { case GFX_CTX_OPENGL_API: return eglBindAPI(EGL_OPENGL_API); case GFX_CTX_OPENGL_ES_API: +#ifndef EGL_OPENGL_ES3_BIT_KHR + if (major >= 3) + return false; +#endif return eglBindAPI(EGL_OPENGL_ES_API); case GFX_CTX_OPENVG_API: return eglBindAPI(EGL_OPENVG_API); diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index b1a414c6a4..b2679a3192 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -53,6 +53,8 @@ static volatile sig_atomic_t g_quit; static bool g_inited; static unsigned g_interval; static enum gfx_ctx_api g_api; +static unsigned g_major; +static unsigned g_minor; static void sighandler(int sig) { @@ -248,6 +250,14 @@ static bool gfx_ctx_init(void) EGL_NONE, }; +#ifdef EGL_OPENGL_ES3_BIT_KHR + static const EGLint egl_attribs_gles3[] = { + EGL_ATTRIBS_BASE, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, + EGL_NONE, + }; +#endif + static const EGLint egl_attribs_vg[] = { EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, @@ -261,7 +271,12 @@ static bool gfx_ctx_init(void) attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: - attrib_ptr = egl_attribs_gles; +#ifdef EGL_OPENGL_ES3_BIT_KHR + if (g_major >= 3) + attrib_ptr = egl_attribs_gles3; + else +#endif + attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: attrib_ptr = egl_attribs_vg; @@ -390,9 +405,9 @@ static bool gfx_ctx_set_video_mode( CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa); XSetWindowBackground(g_dpy, g_win, 0); - // GLES 2.0. Don't use for any other API. - static const EGLint egl_ctx_gles_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, + // GLES 2.0+. Don't use for any other API. + const EGLint egl_ctx_gles_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, g_major ? g_major : 2, EGL_NONE, }; @@ -570,14 +585,18 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor) { - (void)major; - (void)minor; + g_major = major; + g_minor = minor; g_api = api; switch (api) { case GFX_CTX_OPENGL_API: return eglBindAPI(EGL_OPENGL_API); case GFX_CTX_OPENGL_ES_API: +#ifndef EGL_OPENGL_ES3_BIT_KHR + if (major >= 3) + return false; +#endif return eglBindAPI(EGL_OPENGL_ES_API); case GFX_CTX_OPENVG_API: return eglBindAPI(EGL_OPENVG_API); diff --git a/gfx/gl.c b/gfx/gl.c index 77dd4c44f0..91dec027b3 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -1834,11 +1834,20 @@ 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; + const struct retro_hw_render_callback *cb = &g_extern.system.hw_render_callback; + unsigned major = cb->version_major; + unsigned minor = cb->version_minor; #ifdef HAVE_OPENGLES enum gfx_ctx_api api = GFX_CTX_OPENGL_ES_API; - const char *api_name = "OpenGL ES"; + const char *api_name = "OpenGL ES 2.0"; +#ifdef HAVE_OPENGLES3 + if (cb->context_type == RETRO_HW_CONTEXT_OPENGLES3) + { + major = 3; + minor = 0; + api_name = "OpenGL ES 3.0"; + } +#endif #else enum gfx_ctx_api api = GFX_CTX_OPENGL_API; const char *api_name = "OpenGL"; @@ -2047,7 +2056,9 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo // but still need multiple textures with PREV. gl->textures = 4; #ifdef HAVE_FBO -#ifdef HAVE_OPENGLES2 +#if defined(HAVE_OPENGLES3) + gl->hw_render_use = hw_render->context_type == RETRO_HW_CONTEXT_OPENGLES2 || hw_render->context_type == RETRO_HW_CONTEXT_OPENGLES3; +#elif defined(HAVE_OPENGLES2) gl->hw_render_use = hw_render->context_type == RETRO_HW_CONTEXT_OPENGLES2; #else gl->hw_render_use = hw_render->context_type == RETRO_HW_CONTEXT_OPENGL || diff --git a/libretro-test-gl/Makefile b/libretro-test-gl/Makefile index 7d1103d128..0e2006a7c3 100644 --- a/libretro-test-gl/Makefile +++ b/libretro-test-gl/Makefile @@ -101,7 +101,10 @@ CFLAGS += -Wall -pedantic $(fpic) ifeq ($(GLES), 1) CFLAGS += -DGLES -DHAVE_OPENGLES2 - LIBS += -lGLESv2 + ifeq ($(GLES3), 1) + CFLAGS += -DHAVE_OPENGLES3 -DGLES3 + endif + LIBS += -lGLESv2 # Still link against GLESv2 when using GLES3 API, at least on desktop Linux. OBJECTS += ../gfx/glsym/glsym_es2.o else OBJECTS += ../gfx/glsym/glsym_gl.o diff --git a/libretro-test-gl/libretro-test.c b/libretro-test-gl/libretro-test.c index 8cb0fbdff3..f2c9c6d9bc 100644 --- a/libretro-test-gl/libretro-test.c +++ b/libretro-test-gl/libretro-test.c @@ -448,7 +448,11 @@ bool retro_load_game(const struct retro_game_info *info) } #ifdef GLES +#ifdef GLES3 + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; +#else hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; +#endif #else #ifdef CORE hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; diff --git a/libretro.h b/libretro.h index 6100cc3a9c..aaff348497 100755 --- a/libretro.h +++ b/libretro.h @@ -718,9 +718,10 @@ typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); 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_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. Driver can choose to use latest compatibility context. 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_OPENGLES3, // GLES 3.0 RETRO_HW_CONTEXT_DUMMY = INT_MAX };