diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index 18c9103157..b24fb3e3ca 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -446,6 +446,59 @@ static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo) return fb; } +static EGLint *egl_fill_attribs(EGLint *attr) +{ + switch (g_api) + { +#ifdef EGL_KHR_create_context + case GFX_CTX_OPENGL_API: + { + unsigned version = g_major * 1000 + g_minor; + bool core = version >= 3001; +#ifdef GL_DEBUG + bool debug = true; +#else + bool debug = g_extern.system.hw_render_callback.debug_context; +#endif + + if (core) + { + *attr++ = EGL_CONTEXT_MAJOR_VERSION_KHR; + *attr++ = g_major; + *attr++ = EGL_CONTEXT_MINOR_VERSION_KHR; + *attr++ = g_minor; + // Technically, we don't have core/compat until 3.2. + // Version 3.1 is either compat or not depending on GL_ARB_compatibility. + if (version >= 3002) + { + *attr++ = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + *attr++ = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + } + } + + if (debug) + { + *attr++ = EGL_CONTEXT_FLAGS_KHR; + *attr++ = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + } + + break; + } +#endif + + case GFX_CTX_OPENGL_ES_API: + *attr++ = EGL_CONTEXT_CLIENT_VERSION; + *attr++ = g_major ? (EGLint)g_major : 2; + break; + + default: + break; + } + + *attr = EGL_NONE; + return attr; +} + static bool gfx_ctx_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) @@ -484,7 +537,7 @@ static bool gfx_ctx_set_video_mode(void *data, EGL_NONE, }; -#ifdef EGL_OPENGL_ES3_BIT_KHR +#ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, @@ -498,12 +551,6 @@ static bool gfx_ctx_set_video_mode(void *data, EGL_NONE, }; - // GLES 2.0+. Don't use for any other API. - const EGLint gles_context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, g_major ? (EGLint)g_major : 2, - EGL_NONE - }; - const EGLint *attrib_ptr; switch (g_api) { @@ -511,7 +558,7 @@ static bool gfx_ctx_set_video_mode(void *data, attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: -#ifdef EGL_OPENGL_ES3_BIT_KHR +#ifdef EGL_KHR_create_context if (g_major >= 3) attrib_ptr = egl_attribs_gles3; else @@ -594,14 +641,20 @@ static bool gfx_ctx_set_video_mode(void *data, if (!eglChooseConfig(g_egl_dpy, attrib_ptr, &g_config, 1, &n) || n != 1) 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); + EGLint egl_attribs[16]; + EGLint *attr = egl_attribs; + attr = egl_fill_attribs(attr); + + g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, + attr != egl_attribs ? egl_attribs : NULL); + 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); + attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[KMS/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx); if (g_egl_hw_ctx == EGL_NO_CONTEXT) @@ -659,10 +712,11 @@ void gfx_ctx_destroy(void *data) // Be as careful as possible in deinit. // If we screw up, the KMS tty will not restore. - g_egl_ctx = NULL; - g_egl_surf = NULL; - g_egl_dpy = NULL; - g_config = 0; + g_egl_ctx = NULL; + g_egl_hw_ctx = NULL; + g_egl_surf = NULL; + g_egl_dpy = NULL; + g_config = 0; // Restore original CRTC. if (g_orig_crtc) @@ -718,9 +772,13 @@ static bool gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major, u switch (api) { case GFX_CTX_OPENGL_API: +#ifndef EGL_KHR_create_context + if ((major * 1000 + minor) >= 3001) + return false; +#endif return eglBindAPI(EGL_OPENGL_API); case GFX_CTX_OPENGL_ES_API: -#ifndef EGL_OPENGL_ES3_BIT_KHR +#ifndef EGL_KHR_create_context if (major >= 3) return false; #endif diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index c52298173a..c2dd6ba027 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -402,8 +402,14 @@ static bool gfx_ctx_set_video_mode(void *data, *aptr++ = g_major; *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB; *aptr++ = g_minor; - *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; - *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + + // Technically, we don't have core/compat until 3.2. + // Version 3.1 is either compat or not depending on GL_ARB_compatibility. + if ((g_major * 1000 + g_minor) >= 3002) + { + *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; + *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } } if (g_debug) diff --git a/gfx/context/wgl_ctx.c b/gfx/context/wgl_ctx.c index 90e87b7f63..0a9eac1e8a 100644 --- a/gfx/context/wgl_ctx.c +++ b/gfx/context/wgl_ctx.c @@ -157,8 +157,14 @@ static void create_gl_context(HWND hwnd) *aptr++ = g_major; *aptr++ = WGL_CONTEXT_MINOR_VERSION_ARB; *aptr++ = g_minor; - *aptr++ = WGL_CONTEXT_PROFILE_MASK_ARB; - *aptr++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + + // Technically, we don't have core/compat until 3.2. + // Version 3.1 is either compat or not depending on GL_ARB_compatibility. + if ((g_major * 1000 + g_minor) >= 3002) + { + *aptr++ = WGL_CONTEXT_PROFILE_MASK_ARB; + *aptr++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + } } if (debug) diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index ae1628f76d..63f0b25fc6 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -257,7 +257,7 @@ static bool gfx_ctx_init(void *data) EGL_NONE, }; -#ifdef EGL_OPENGL_ES3_BIT_KHR +#ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, @@ -278,7 +278,7 @@ static bool gfx_ctx_init(void *data) attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: -#ifdef EGL_OPENGL_ES3_BIT_KHR +#ifdef EGL_KHR_create_context if (g_major >= 3) attrib_ptr = egl_attribs_gles3; else @@ -336,6 +336,59 @@ error: return false; } +static EGLint *egl_fill_attribs(EGLint *attr) +{ + switch (g_api) + { +#ifdef EGL_KHR_create_context + case GFX_CTX_OPENGL_API: + { + unsigned version = g_major * 1000 + g_minor; + bool core = version >= 3001; +#ifdef GL_DEBUG + bool debug = true; +#else + bool debug = g_extern.system.hw_render_callback.debug_context; +#endif + + if (core) + { + *attr++ = EGL_CONTEXT_MAJOR_VERSION_KHR; + *attr++ = g_major; + *attr++ = EGL_CONTEXT_MINOR_VERSION_KHR; + *attr++ = g_minor; + // Technically, we don't have core/compat until 3.2. + // Version 3.1 is either compat or not depending on GL_ARB_compatibility. + if (version >= 3002) + { + *attr++ = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + *attr++ = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + } + } + + if (debug) + { + *attr++ = EGL_CONTEXT_FLAGS_KHR; + *attr++ = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + } + + break; + } +#endif + + case GFX_CTX_OPENGL_ES_API: + *attr++ = EGL_CONTEXT_CLIENT_VERSION; + *attr++ = g_major ? (EGLint)g_major : 2; + break; + + default: + break; + } + + *attr = EGL_NONE; + return attr; +} + static bool gfx_ctx_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) @@ -357,11 +410,10 @@ static bool gfx_ctx_set_video_mode(void *data, int (*old_handler)(Display*, XErrorEvent*) = NULL; - // GLES 2.0+. Don't use for any other API. - const EGLint egl_ctx_gles_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, g_major ? (EGLint)g_major : 2, - EGL_NONE, - }; + EGLint egl_attribs[16]; + EGLint *attr = egl_attribs; + + attr = egl_fill_attribs(attr); EGLint vid; if (!eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &vid)) @@ -421,7 +473,7 @@ static bool gfx_ctx_set_video_mode(void *data, XSetWindowBackground(g_dpy, g_win, 0); g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, - (g_api == GFX_CTX_OPENGL_ES_API) ? egl_ctx_gles_attribs : NULL); + attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx); if (g_egl_ctx == EGL_NO_CONTEXT) @@ -430,7 +482,7 @@ static bool gfx_ctx_set_video_mode(void *data, 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); + attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx); if (g_egl_hw_ctx == EGL_NO_CONTEXT) @@ -532,10 +584,11 @@ static void gfx_ctx_destroy(void *data) eglTerminate(g_egl_dpy); } - g_egl_ctx = NULL; - g_egl_surf = NULL; - g_egl_dpy = NULL; - g_config = 0; + g_egl_ctx = NULL; + g_egl_hw_ctx = NULL; + g_egl_surf = NULL; + g_egl_dpy = NULL; + g_config = 0; if (g_win) { @@ -616,9 +669,13 @@ static bool gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major, u switch (api) { case GFX_CTX_OPENGL_API: +#ifndef EGL_KHR_create_context + if ((major * 1000 + minor) >= 3001) + return false; +#endif return eglBindAPI(EGL_OPENGL_API); case GFX_CTX_OPENGL_ES_API: -#ifndef EGL_OPENGL_ES3_BIT_KHR +#ifndef EGL_KHR_create_context if (major >= 3) return false; #endif