diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index f89e21b1a..3a84e4a27 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -81,6 +81,10 @@ #define DEFAULT_OGL_ES "libGLESv1_CM.so.1" #endif /* SDL_VIDEO_DRIVER_RPI */ +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif + /** If we happen to not have this defined because of an older EGL version, just define it 0x0 as eglGetPlatformDisplayEXT will most likely be NULL if this is missing */ @@ -943,6 +947,34 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface) return NULL; } + /* Check whether making contexts current without a surface is supported. + * First condition: EGL must support it. That's the case for EGL 1.5 + * or later, or if the EGL_KHR_surfaceless_context extension is present. */ + if ((_this->egl_data->egl_version_major > 1) || + ((_this->egl_data->egl_version_major == 1) && (_this->egl_data->egl_version_minor >= 5)) || + SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_surfaceless_context")) + { + /* Secondary condition: The client API must support it. */ + if (profile_es) { + /* On OpenGL ES, the GL_OES_surfaceless_context extension must be + * present. */ + if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) { + _this->gl_allow_no_surface = 1; + } + } else { + /* Desktop OpenGL supports it by default from version 3.0 on. */ + void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params); + glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv"); + if (glGetIntegervFunc) { + GLint v = 0; + glGetIntegervFunc(GL_MAJOR_VERSION, &v); + if (v >= 3) { + _this->gl_allow_no_surface = 1; + } + } + } + } + return (SDL_GLContext) egl_context; } @@ -958,7 +990,7 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context) /* The android emulator crashes badly if you try to eglMakeCurrent * with a valid context and invalid surface, so we have to check for both here. */ - if (!egl_context || !egl_surface) { + if (!egl_context || (!egl_surface && !_this->gl_allow_no_surface)) { _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } else { if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h index 83bd6345d..b01d4bec7 100644 --- a/src/video/SDL_egl_c.h +++ b/src/video/SDL_egl_c.h @@ -147,12 +147,7 @@ BACKEND ## _GLES_SwapWindow(_THIS, SDL_Window * window) \ #define SDL_EGL_MakeCurrent_impl(BACKEND) int \ BACKEND ## _GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) \ {\ - if (window && context) { \ - return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context); \ - }\ - else {\ - return SDL_EGL_MakeCurrent(_this, NULL, NULL);\ - }\ + return SDL_EGL_MakeCurrent(_this, window ? ((SDL_WindowData *) window->driverdata)->egl_surface : EGL_NO_SURFACE, context);\ } #define SDL_EGL_CreateContext_impl(BACKEND) SDL_GLContext \ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 6f1faa031..ea907c219 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -375,6 +375,11 @@ struct SDL_VideoDevice SDL_TLSID current_glwin_tls; SDL_TLSID current_glctx_tls; + /* Flag that stores whether it's allowed to call SDL_GL_MakeCurrent() + * with a NULL window, but a non-NULL context. (Not allowed in most cases, + * except on EGL under some circumstances.) */ + int gl_allow_no_surface; + /* * * */ /* Data used by the Vulkan drivers */ struct diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index d8778aa4d..5cb82b6f4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3585,12 +3585,14 @@ SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx) if (!ctx) { window = NULL; - } else { + } else if (window) { CHECK_WINDOW_MAGIC(window, -1); if (!(window->flags & SDL_WINDOW_OPENGL)) { return SDL_SetError("The specified window isn't an OpenGL window"); } + } else if (!_this->gl_allow_no_surface) { + return SDL_SetError("Use of OpenGL without a window is not supported on this platform"); } retval = _this->GL_MakeCurrent(_this, window, ctx);