From 5a7c20b945da35dcb0fc8baf659f12a409ac9804 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 19:35:41 -0700 Subject: [PATCH 1/9] hints: replace SDL_HINT_VIDEO_X11_FORCE_EGL with platform-agnostic SDL_HINT_VIDEO_FORCE_EGL This adds support for forcing the use of EGL on Windows and MacOS. The SDL_HINT_VIDEO_X11_FORCE_EGL hint is retained for backwards compatibility but is now deprecated. --- include/SDL_hints.h | 15 ++++++++++++++ src/video/SDL_egl.c | 2 +- src/video/cocoa/SDL_cocoavideo.m | 27 ++++++++++++++++---------- src/video/windows/SDL_windowsvideo.c | 29 +++++++++++++++++----------- src/video/x11/SDL_x11opengl.c | 4 +++- src/video/x11/SDL_x11opengles.c | 1 + src/video/x11/SDL_x11video.c | 3 ++- src/video/x11/SDL_x11window.c | 1 + 8 files changed, 58 insertions(+), 24 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index ce2225440f..2175cf11f3 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -1802,6 +1802,18 @@ extern "C" { */ #define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" +/** + * \brief A variable controlling whether the OpenGL context should be created + * with EGL by default + * + * This variable can be set to the following values: + * "0" - Use platform-specific GL context creation API (GLX, WGL, CGL, etc) + * "1" - Use EGL + * + * By default SDL will use the platform-specific GL context API when both are present. + */ +#define SDL_HINT_VIDEO_FORCE_EGL "SDL_VIDEO_FORCE_EGL" + /** * \brief A variable controlling whether X11 should use GLX or EGL by default * @@ -1810,6 +1822,9 @@ extern "C" { * "1" - Use EGL * * By default SDL will use GLX when both are present. + * + * \deprecated Use the platform-agnostic SDL_HINT_VIDEO_FORCE_EGL hint instead. + * */ #define SDL_HINT_VIDEO_X11_FORCE_EGL "SDL_VIDEO_X11_FORCE_EGL" diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 28d02b132c..a0e78b2bac 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -506,7 +506,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa * Khronos doc: "EGL_BAD_DISPLAY is generated if display is not an EGL display connection, unless display is EGL_NO_DISPLAY and name is EGL_EXTENSIONS." * Therefore SDL_EGL_GetVersion() shouldn't work with uninitialized display. * - it actually doesn't work on Android that has 1.5 egl client - * - it works on desktop X11 (using SDL_VIDEO_X11_FORCE_EGL=1) */ + * - it works on desktop X11 (using SDL_VIDEO_FORCE_EGL=1) */ SDL_EGL_GetVersion(_this); if (_this->egl_data->egl_version_major == 1 && _this->egl_data->egl_version_minor == 5) { diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 6c3d44efae..d957184339 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -139,16 +139,23 @@ Cocoa_CreateDevice(void) device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval; device->GL_SwapWindow = Cocoa_GL_SwapWindow; device->GL_DeleteContext = Cocoa_GL_DeleteContext; -#elif SDL_VIDEO_OPENGL_EGL - device->GL_LoadLibrary = Cocoa_GLES_LoadLibrary; - device->GL_GetProcAddress = Cocoa_GLES_GetProcAddress; - device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary; - device->GL_CreateContext = Cocoa_GLES_CreateContext; - device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent; - device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval; - device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval; - device->GL_SwapWindow = Cocoa_GLES_SwapWindow; - device->GL_DeleteContext = Cocoa_GLES_DeleteContext; +#endif +#if SDL_VIDEO_OPENGL_EGL +#if SDL_VIDEO_OPENGL_CGL + if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) { +#endif + device->GL_LoadLibrary = Cocoa_GLES_LoadLibrary; + device->GL_GetProcAddress = Cocoa_GLES_GetProcAddress; + device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary; + device->GL_CreateContext = Cocoa_GLES_CreateContext; + device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent; + device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval; + device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval; + device->GL_SwapWindow = Cocoa_GLES_SwapWindow; + device->GL_DeleteContext = Cocoa_GLES_DeleteContext; +#if SDL_VIDEO_OPENGL_CGL + } +#endif #endif #if SDL_VIDEO_VULKAN diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 0dc107bdf2..bdf887bdb9 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -226,17 +226,24 @@ WIN_CreateDevice(void) device->GL_GetSwapInterval = WIN_GL_GetSwapInterval; device->GL_SwapWindow = WIN_GL_SwapWindow; device->GL_DeleteContext = WIN_GL_DeleteContext; -#elif SDL_VIDEO_OPENGL_EGL - /* Use EGL based functions */ - device->GL_LoadLibrary = WIN_GLES_LoadLibrary; - device->GL_GetProcAddress = WIN_GLES_GetProcAddress; - device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; - device->GL_CreateContext = WIN_GLES_CreateContext; - device->GL_MakeCurrent = WIN_GLES_MakeCurrent; - device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; - device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; - device->GL_SwapWindow = WIN_GLES_SwapWindow; - device->GL_DeleteContext = WIN_GLES_DeleteContext; +#endif +#if SDL_VIDEO_OPENGL_EGL +#if SDL_VIDEO_OPENGL_WGL + if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) { +#endif + /* Use EGL based functions */ + device->GL_LoadLibrary = WIN_GLES_LoadLibrary; + device->GL_GetProcAddress = WIN_GLES_GetProcAddress; + device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; + device->GL_CreateContext = WIN_GLES_CreateContext; + device->GL_MakeCurrent = WIN_GLES_MakeCurrent; + device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; + device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; + device->GL_SwapWindow = WIN_GLES_SwapWindow; + device->GL_DeleteContext = WIN_GLES_DeleteContext; +#if SDL_VIDEO_OPENGL_WGL + } +#endif #endif #if SDL_VIDEO_VULKAN device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary; diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 60b2203cdf..8c728ea970 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -253,6 +253,7 @@ X11_GL_LoadLibrary(_THIS, const char *path) * GLX_EXT_create_context_es2_profile extension, switch over to X11_GLES functions */ if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) || + SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE) || SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) && X11_GL_UseEGL(_this) ) { #if SDL_VIDEO_OPENGL_EGL @@ -691,7 +692,8 @@ SDL_bool X11_GL_UseEGL(_THIS) { SDL_assert(_this->gl_data != NULL); - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) + if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE) || + SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) { /* use of EGL has been requested, even for desktop GL */ return SDL_TRUE; diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c index e1ec4e4d2a..7641a6cc64 100644 --- a/src/video/x11/SDL_x11opengles.c +++ b/src/video/x11/SDL_x11opengles.c @@ -36,6 +36,7 @@ X11_GLES_LoadLibrary(_THIS, const char *path) /* If the profile requested is not GL ES, switch over to X11_GL functions */ if ((_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) && + !SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE) && !SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) { #if SDL_VIDEO_OPENGL_GLX X11_GLES_UnloadLibrary(_this); diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 2e5e190bd0..569e995f3d 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -282,7 +282,8 @@ X11_CreateDevice(void) #endif #if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_GLX - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) { + if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE) || + SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) { #endif device->GL_LoadLibrary = X11_GLES_LoadLibrary; device->GL_GetProcAddress = X11_GLES_GetProcAddress; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 9b007e79d7..8e08be753f 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -429,6 +429,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) #if SDL_VIDEO_OPENGL_EGL if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) || + SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE) || SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) #if SDL_VIDEO_OPENGL_GLX && ( !_this->gl_data || X11_GL_UseEGL(_this) ) From aed980526c1c9e794cc4b839072dace087ad3b95 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 20:22:52 -0700 Subject: [PATCH 2/9] SDL_video: defer destroying window until GL/EGL/Vulkan unloaded --- src/video/SDL_video.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 7994c19432..0bb5f0e9c2 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1904,16 +1904,6 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) window->surface_valid = SDL_FALSE; } - if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */ - if (_this->DestroyWindowFramebuffer) { - _this->DestroyWindowFramebuffer(_this, window); - } - } - - if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) { - _this->DestroyWindow(_this, window); - } - if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) { if (flags & SDL_WINDOW_OPENGL) { need_gl_load = SDL_TRUE; @@ -1956,6 +1946,16 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) SDL_Vulkan_UnloadLibrary(); } + if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */ + if (_this->DestroyWindowFramebuffer) { + _this->DestroyWindowFramebuffer(_this, window); + } + } + + if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) { + _this->DestroyWindow(_this, window); + } + if (need_gl_load) { if (SDL_GL_LoadLibrary(NULL) < 0) { return -1; @@ -3297,6 +3297,12 @@ SDL_DestroyWindow(SDL_Window * window) window->surface = NULL; window->surface_valid = SDL_FALSE; } + if (window->flags & SDL_WINDOW_OPENGL) { + SDL_GL_UnloadLibrary(); + } + if (window->flags & SDL_WINDOW_VULKAN) { + SDL_Vulkan_UnloadLibrary(); + } if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */ if (_this->DestroyWindowFramebuffer) { _this->DestroyWindowFramebuffer(_this, window); @@ -3305,12 +3311,6 @@ SDL_DestroyWindow(SDL_Window * window) if (_this->DestroyWindow) { _this->DestroyWindow(_this, window); } - if (window->flags & SDL_WINDOW_OPENGL) { - SDL_GL_UnloadLibrary(); - } - if (window->flags & SDL_WINDOW_VULKAN) { - SDL_Vulkan_UnloadLibrary(); - } display = SDL_GetDisplayForWindow(window); if (display->fullscreen_window == window) { From c608cf6222937ec339b2002a26f72a7abb773ebc Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 20:29:41 -0700 Subject: [PATCH 3/9] egl: implement SDL_GL_EGL_PLATFORM attribute This implements a new SDL_GL_EGL_PLATFORM attribute to set the "platform" argument for SDL_EGL_LoadLibrary on Windows, macOS, and Linux. I've limited it to those three operating systems because that's what I've been able to test against. --- include/SDL_video.h | 3 ++- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 11 +++++++++++ src/video/cocoa/SDL_cocoaopengles.m | 4 ++-- src/video/windows/SDL_windowsopengles.c | 4 ++-- src/video/x11/SDL_x11opengles.c | 2 +- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 79d572fcc8..8e9ed8da2b 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -249,7 +249,8 @@ typedef enum SDL_GL_CONTEXT_RELEASE_BEHAVIOR, SDL_GL_CONTEXT_RESET_NOTIFICATION, SDL_GL_CONTEXT_NO_ERROR, - SDL_GL_FLOATBUFFERS + SDL_GL_FLOATBUFFERS, + SDL_GL_EGL_PLATFORM } SDL_GLattr; typedef enum diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 4bc1f111fd..20340da60a 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -391,6 +391,7 @@ struct SDL_VideoDevice int framebuffer_srgb_capable; int no_error; int retained_backing; + int egl_platform; int driver_loaded; char driver_path[256]; void *dll_handle; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 0bb5f0e9c2..6f5d468550 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3673,6 +3673,8 @@ SDL_GL_ResetAttributes() _this->gl_config.reset_notification = SDL_GL_CONTEXT_RESET_NO_NOTIFICATION; _this->gl_config.share_with_current_context = 0; + + _this->gl_config.egl_platform = 0; } int @@ -3789,6 +3791,9 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value) case SDL_GL_CONTEXT_NO_ERROR: _this->gl_config.no_error = value; break; + case SDL_GL_EGL_PLATFORM: + _this->gl_config.egl_platform = value; + break; default: retval = SDL_SetError("Unknown OpenGL attribute"); break; @@ -3998,6 +4003,12 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) *value = _this->gl_config.no_error; return 0; } + case SDL_GL_EGL_PLATFORM: + { + *value = _this->gl_config.egl_platform; + return 0; + } + break; default: return SDL_SetError("Unknown OpenGL attribute"); } diff --git a/src/video/cocoa/SDL_cocoaopengles.m b/src/video/cocoa/SDL_cocoaopengles.m index bdf2e9a084..04561b281f 100644 --- a/src/video/cocoa/SDL_cocoaopengles.m +++ b/src/video/cocoa/SDL_cocoaopengles.m @@ -51,7 +51,7 @@ Cocoa_GLES_LoadLibrary(_THIS, const char *path) } if (_this->egl_data == NULL) { - return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0); + return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform); } return 0; @@ -127,7 +127,7 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window) #if 0 /* When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), _this->gl_config.driver_loaded can be 1, while the below lines function. */ SDL_assert(!_this->gl_config.driver_loaded); #endif - if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) { + if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform) < 0) { SDL_EGL_UnloadLibrary(_this); return -1; } diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index 1e2a4f6207..49cebd62dd 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -52,7 +52,7 @@ WIN_GLES_LoadLibrary(_THIS, const char *path) { } if (_this->egl_data == NULL) { - return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0); + return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform); } return 0; @@ -113,7 +113,7 @@ WIN_GLES_SetupWindow(_THIS, SDL_Window * window) #if 0 /* When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), _this->gl_config.driver_loaded can be 1, while the below lines function. */ SDL_assert(!_this->gl_config.driver_loaded); #endif - if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) { + if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform) < 0) { SDL_EGL_UnloadLibrary(_this); return -1; } diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c index 7641a6cc64..43d7a7d892 100644 --- a/src/video/x11/SDL_x11opengles.c +++ b/src/video/x11/SDL_x11opengles.c @@ -55,7 +55,7 @@ X11_GLES_LoadLibrary(_THIS, const char *path) #endif } - return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0); + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, _this->gl_config.egl_platform); } XVisualInfo * From fb1a5812096af54742410e5381648e0cd4f6976e Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 21:29:30 -0700 Subject: [PATCH 4/9] egl: add hint to disable eglGetDisplay fallback when eglGetPlatformDisplay fails This fallback is undesirable when using ANGLE, because it will end up using some default configuration (e.g. on Windows it defaults to the D3D11 backend). --- include/SDL_hints.h | 12 ++++++++++++ src/video/SDL_egl.c | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 2175cf11f3..2f4441502f 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -1643,6 +1643,18 @@ extern "C" { */ #define SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY "SDL_VIDEO_EGL_ALLOW_TRANSPARENCY" +/** + * \brief If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay. + * + * This variable can be set to one of the following values: + * "0" - Do not fall back to eglGetDisplay + * "1" - Fall back to eglGetDisplay if eglGetPlatformDisplay fails. + * + * By default, SDL will fall back to eglGetDisplay if eglGetPlatformDisplay + * fails. + */ +#define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_GETDISPLAY_FALLBACK" + /** * \brief A variable controlling whether the graphics context is externally managed. * diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index a0e78b2bac..f1a9bc14f7 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -526,7 +526,9 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa } #endif /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */ - if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) && (_this->egl_data->eglGetDisplay != NULL)) { + if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) && + (_this->egl_data->eglGetDisplay != NULL) && + SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK, SDL_TRUE)) { _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); } if (_this->egl_data->egl_display == EGL_NO_DISPLAY) { From eacf6dc15e85dec1dca181a4ef981819af0a040e Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 22:53:25 -0700 Subject: [PATCH 5/9] egl: fix function prototype for eglGetPlatformDisplay The EGL 1.5 specification says that eglGetPlatformDisplay (unlike eglGetPlatformDisplayExt) takes an EGLAttrib* rather than EGLint* for the attribute list. --- src/video/SDL_egl_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h index 76d26f93b0..c983012e15 100644 --- a/src/video/SDL_egl_c.h +++ b/src/video/SDL_egl_c.h @@ -46,7 +46,7 @@ typedef struct SDL_EGL_VideoData EGLDisplay(EGLAPIENTRY *eglGetDisplay) (NativeDisplayType display); EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplay) (EGLenum platform, void *native_display, - const EGLint *attrib_list); + const EGLAttrib *attrib_list); EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplayEXT) (EGLenum platform, void *native_display, const EGLint *attrib_list); From 0644042eb8781781a56ff2430740ef654c3b67f1 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 19:44:35 -0700 Subject: [PATCH 6/9] egl: implement public functions to obtain internal EGL handles These functions allow applications to call EGL functions against the SDL EGL context. For example, applications can use an EGL API loader via SDL_EGL_GetCurrentDisplay and SDL_EGL_GetProcAddress, and can call functions such as eglQuerySurface against the internal EGLSurface and EGLDisplay. --- include/SDL_video.h | 48 +++++++++++ src/video/SDL_egl.c | 4 +- src/video/SDL_egl_c.h | 2 +- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 86 +++++++++++++++++++ src/video/android/SDL_androidvideo.c | 2 +- src/video/cocoa/SDL_cocoaopengles.h | 3 +- src/video/cocoa/SDL_cocoaopengles.m | 9 ++ src/video/cocoa/SDL_cocoavideo.m | 2 + src/video/emscripten/SDL_emscriptenopengles.h | 2 +- src/video/kmsdrm/SDL_kmsdrmopengles.h | 2 +- src/video/offscreen/SDL_offscreenopengles.h | 2 +- src/video/raspberry/SDL_rpiopengles.h | 2 +- src/video/vita/SDL_vitavideo.c | 2 +- src/video/vivante/SDL_vivanteopengles.h | 2 +- src/video/wayland/SDL_waylandopengles.c | 10 ++- src/video/wayland/SDL_waylandopengles.h | 3 +- src/video/wayland/SDL_waylandvideo.c | 1 + src/video/windows/SDL_windowsopengl.c | 1 + src/video/windows/SDL_windowsopengles.c | 10 +++ src/video/windows/SDL_windowsopengles.h | 3 +- src/video/windows/SDL_windowsvideo.c | 2 + src/video/winrt/SDL_winrtopengles.h | 2 +- src/video/x11/SDL_x11opengles.c | 7 ++ src/video/x11/SDL_x11opengles.h | 3 +- src/video/x11/SDL_x11video.c | 2 + 26 files changed, 197 insertions(+), 16 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 8e9ed8da2b..cfbed9c892 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -217,6 +217,13 @@ typedef enum */ typedef void *SDL_GLContext; +/** + * \brief Opaque EGL types. + */ +typedef void *SDL_EGLDisplay; +typedef void *SDL_EGLConfig; +typedef void *SDL_EGLSurface; + /** * \brief OpenGL configuration attributes */ @@ -1903,6 +1910,21 @@ extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); */ extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc); +/** + * Get an EGL library function by name. + * + * If an EGL library is loaded, this function allows applications to get entry + * points for EGL functions. This is useful to provide to an EGL API and + * extension loader. + * + * \param proc the name of an EGL function + * \returns a pointer to the named EGL function. The returned pointer should be + * cast to the appropriate function signature. + * + * \sa SDL_GL_GetCurrentEGLDisplay + */ +extern DECLSPEC void *SDLCALL SDL_EGL_GetProcAddress(const char *proc); + /** * Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary(). * @@ -2041,6 +2063,32 @@ extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void); */ extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void); +/** + * Get the currently active EGL display. + * + * \returns the currently active EGL display or NULL on failure; call + * SDL_GetError() for more information. + * + */ +extern DECLSPEC SDL_EGLDisplay SDLCALL SDL_EGL_GetCurrentEGLDisplay(void); + +/** + * Get the currently active EGL config. + * + * \returns the currently active EGL config or NULL on failure; call + * SDL_GetError() for more information. + * + */ +extern DECLSPEC SDL_EGLConfig SDLCALL SDL_EGL_GetCurrentEGLConfig(void); + +/** + * Get the EGL surface associated with the window. + * + * \returns the EGLSurface pointer associated with the window, or NULL on + * failure. + */ +extern DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowEGLSurface(SDL_Window * window); + /** * Get the size of a window's underlying drawable in pixels. * diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index f1a9bc14f7..072b99ba9b 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -242,7 +242,7 @@ SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext } void * -SDL_EGL_GetProcAddress(_THIS, const char *proc) +SDL_EGL_GetProcAddressInternal(_THIS, const char *proc) { const Uint32 eglver = (((Uint32) _this->egl_data->egl_version_major) << 16) | ((Uint32) _this->egl_data->egl_version_minor); const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32) 1) << 16) | 5); @@ -517,7 +517,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, NULL); } else { if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) { - _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT"); + _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddressInternal(_this, "eglGetPlatformDisplayEXT"); if (_this->egl_data->eglGetPlatformDisplayEXT) { _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(uintptr_t)native_display, NULL); } diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h index c983012e15..3cf3cbb57b 100644 --- a/src/video/SDL_egl_c.h +++ b/src/video/SDL_egl_c.h @@ -132,7 +132,7 @@ extern int SDL_EGL_GetAttribute(_THIS, SDL_GLattr attrib, int *value); */ extern int SDL_EGL_LoadLibraryOnly(_THIS, const char *path); extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display, EGLenum platform); -extern void *SDL_EGL_GetProcAddress(_THIS, const char *proc); +extern void *SDL_EGL_GetProcAddressInternal(_THIS, const char *proc); extern void SDL_EGL_UnloadLibrary(_THIS); extern void SDL_EGL_SetRequiredVisualId(_THIS, int visual_id); extern int SDL_EGL_ChooseConfig(_THIS); diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 20340da60a..63d3eea84d 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -275,6 +275,7 @@ struct SDL_VideoDevice SDL_GLContext(*GL_CreateContext) (_THIS, SDL_Window * window); int (*GL_MakeCurrent) (_THIS, SDL_Window * window, SDL_GLContext context); void (*GL_GetDrawableSize) (_THIS, SDL_Window * window, int *w, int *h); + SDL_EGLSurface (*GL_GetEGLSurface) (_THIS, SDL_Window * window); int (*GL_SetSwapInterval) (_THIS, int interval); int (*GL_GetSwapInterval) (_THIS); int (*GL_SwapWindow) (_THIS, SDL_Window * window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 6f5d468550..36276e9698 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -25,6 +25,7 @@ #include "SDL.h" #include "SDL_video.h" #include "SDL_sysvideo.h" +#include "SDL_egl_c.h" #include "SDL_blit.h" #include "SDL_pixels_c.h" #include "SDL_rect_c.h" @@ -3480,6 +3481,31 @@ SDL_GL_GetProcAddress(const char *proc) return func; } +void * +SDL_EGL_GetProcAddress(const char *proc) +{ +#if SDL_VIDEO_OPENGL_EGL + void *func; + + if (!_this) { + SDL_UninitializedVideo(); + return NULL; + } + func = NULL; + + if (_this->egl_data) { + func = SDL_EGL_GetProcAddressInternal(_this, proc); + } else { + SDL_SetError("No EGL library has been loaded"); + } + + return func; +#else + SDL_SetError("SDL was not built with EGL support"); + return NULL; +#endif +} + void SDL_GL_UnloadLibrary(void) { @@ -4152,6 +4178,66 @@ SDL_GL_GetCurrentContext(void) return (SDL_GLContext)SDL_TLSGet(_this->current_glctx_tls); } +SDL_EGLDisplay +SDL_EGL_GetCurrentEGLDisplay(void) +{ +#if SDL_VIDEO_OPENGL_EGL + if (!_this) { + SDL_UninitializedVideo(); + return EGL_NO_DISPLAY; + } + if (!_this->egl_data) { + SDL_SetError("There is no current EGL display"); + return EGL_NO_DISPLAY; + } + return _this->egl_data->egl_display; +#else + SDL_SetError("SDL was not built with EGL support"); + return NULL; +#endif +} + +SDL_EGLConfig +SDL_EGL_GetCurrentEGLConfig(void) +{ +#if SDL_VIDEO_OPENGL_EGL + if (!_this) { + SDL_UninitializedVideo(); + return NULL; + } + if (!_this->egl_data) { + SDL_SetError("There is no current EGL display"); + return NULL; + } + return _this->egl_data->egl_config; +#else + SDL_SetError("SDL was not built with EGL support"); + return NULL; +#endif +} + +SDL_EGLConfig +SDL_EGL_GetWindowEGLSurface(SDL_Window * window) +{ +#if SDL_VIDEO_OPENGL_EGL + if (!_this) { + SDL_UninitializedVideo(); + return NULL; + } + if (!_this->egl_data) { + SDL_SetError("There is no current EGL display"); + return NULL; + } + if (_this->GL_GetEGLSurface) { + return _this->GL_GetEGLSurface(_this, window); + } + return NULL; +#else + SDL_SetError("SDL was not built with EGL support"); + return NULL; +#endif +} + void SDL_GL_GetDrawableSize(SDL_Window * window, int *w, int *h) { CHECK_WINDOW_MAGIC(window,); diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 3ed828fde1..d405e7004d 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -50,7 +50,7 @@ static void Android_VideoQuit(_THIS); int Android_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi, float *vdpi); #include "../SDL_egl_c.h" -#define Android_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define Android_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/cocoa/SDL_cocoaopengles.h b/src/video/cocoa/SDL_cocoaopengles.h index bfabb6d57f..05800e3e42 100644 --- a/src/video/cocoa/SDL_cocoaopengles.h +++ b/src/video/cocoa/SDL_cocoaopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define Cocoa_GLES_GetAttribute SDL_EGL_GetAttribute -#define Cocoa_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define Cocoa_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define Cocoa_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define Cocoa_GLES_GetSwapInterval SDL_EGL_GetSwapInterval #define Cocoa_GLES_SetSwapInterval SDL_EGL_SetSwapInterval @@ -41,6 +41,7 @@ extern int Cocoa_GLES_SwapWindow(_THIS, SDL_Window * window); extern int Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); extern void Cocoa_GLES_DeleteContext(_THIS, SDL_GLContext context); extern int Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window); +extern SDL_EGLSurface Cocoa_GLES_GetEGLSurface(_THIS, SDL_Window * window); #endif /* SDL_VIDEO_OPENGL_EGL */ diff --git a/src/video/cocoa/SDL_cocoaopengles.m b/src/video/cocoa/SDL_cocoaopengles.m index 04561b281f..b8f17282d2 100644 --- a/src/video/cocoa/SDL_cocoaopengles.m +++ b/src/video/cocoa/SDL_cocoaopengles.m @@ -44,6 +44,7 @@ Cocoa_GLES_LoadLibrary(_THIS, const char *path) _this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval; _this->GL_SwapWindow = Cocoa_GL_SwapWindow; _this->GL_DeleteContext = Cocoa_GL_DeleteContext; + _this->GL_GetEGLSurface = NULL; return Cocoa_GL_LoadLibrary(_this, path); #else return SDL_SetError("SDL not configured with OpenGL/CGL support"); @@ -77,6 +78,7 @@ Cocoa_GLES_CreateContext(_THIS, SDL_Window * window) _this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval; _this->GL_SwapWindow = Cocoa_GL_SwapWindow; _this->GL_DeleteContext = Cocoa_GL_DeleteContext; + _this->GL_GetEGLSurface = NULL; if (Cocoa_GL_LoadLibrary(_this, NULL) != 0) { return NULL; @@ -145,6 +147,13 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window) return Cocoa_GLES_MakeCurrent(_this, current_win, current_ctx); } +SDL_EGLSurface +Cocoa_GLES_GetEGLSurface(_THIS, SDL_Window * window) +{ @autoreleasepool +{ + return ((__bridge SDL_WindowData *) window->driverdata).egl_surface; +}} + #endif /* SDL_VIDEO_DRIVER_COCOA && SDL_VIDEO_OPENGL_EGL */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index d957184339..a354a2451e 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -139,6 +139,7 @@ Cocoa_CreateDevice(void) device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval; device->GL_SwapWindow = Cocoa_GL_SwapWindow; device->GL_DeleteContext = Cocoa_GL_DeleteContext; + device->GL_GetEGLSurface = NULL; #endif #if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_CGL @@ -153,6 +154,7 @@ Cocoa_CreateDevice(void) device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval; device->GL_SwapWindow = Cocoa_GLES_SwapWindow; device->GL_DeleteContext = Cocoa_GLES_DeleteContext; + device->GL_GetEGLSurface = Cocoa_GLES_GetEGLSurface; #if SDL_VIDEO_OPENGL_CGL } #endif diff --git a/src/video/emscripten/SDL_emscriptenopengles.h b/src/video/emscripten/SDL_emscriptenopengles.h index 9d178f6902..b054dbd1a5 100644 --- a/src/video/emscripten/SDL_emscriptenopengles.h +++ b/src/video/emscripten/SDL_emscriptenopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define Emscripten_GLES_GetAttribute SDL_EGL_GetAttribute -#define Emscripten_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define Emscripten_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define Emscripten_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define Emscripten_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define Emscripten_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.h b/src/video/kmsdrm/SDL_kmsdrmopengles.h index a762ab0f37..1f3eb3631d 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.h +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define KMSDRM_GLES_GetAttribute SDL_EGL_GetAttribute -#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define KMSDRM_GLES_DeleteContext SDL_EGL_DeleteContext #define KMSDRM_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/offscreen/SDL_offscreenopengles.h b/src/video/offscreen/SDL_offscreenopengles.h index 6c9e518200..deafd09cc5 100644 --- a/src/video/offscreen/SDL_offscreenopengles.h +++ b/src/video/offscreen/SDL_offscreenopengles.h @@ -28,7 +28,7 @@ #include "../SDL_sysvideo.h" #include "../SDL_egl_c.h" -#define OFFSCREEN_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define OFFSCREEN_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define OFFSCREEN_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define OFFSCREEN_GLES_GetSwapInterval SDL_EGL_GetSwapInterval #define OFFSCREEN_GLES_SetSwapInterval SDL_EGL_SetSwapInterval diff --git a/src/video/raspberry/SDL_rpiopengles.h b/src/video/raspberry/SDL_rpiopengles.h index 2cdf0fdcf8..59b7e57202 100644 --- a/src/video/raspberry/SDL_rpiopengles.h +++ b/src/video/raspberry/SDL_rpiopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define RPI_GLES_GetAttribute SDL_EGL_GetAttribute -#define RPI_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define RPI_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define RPI_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define RPI_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define RPI_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 33758d691c..b7f4523036 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -47,7 +47,7 @@ #if defined(SDL_VIDEO_VITA_PVR_OGL) #include "SDL_vitagl_pvr_c.h" #endif - #define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddress + #define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define VITA_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define VITA_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define VITA_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/vivante/SDL_vivanteopengles.h b/src/video/vivante/SDL_vivanteopengles.h index dce74ae6bb..2484f413e1 100644 --- a/src/video/vivante/SDL_vivanteopengles.h +++ b/src/video/vivante/SDL_vivanteopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define VIVANTE_GLES_GetAttribute SDL_EGL_GetAttribute -#define VIVANTE_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define VIVANTE_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define VIVANTE_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define VIVANTE_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define VIVANTE_GLES_GetSwapInterval SDL_EGL_GetSwapInterval diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c index a0af3f5a4b..f90d7ac00c 100644 --- a/src/video/wayland/SDL_waylandopengles.c +++ b/src/video/wayland/SDL_waylandopengles.c @@ -40,7 +40,7 @@ Wayland_GLES_LoadLibrary(_THIS, const char *path) { int ret; SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; - ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0); + ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, _this->gl_config.egl_platform); Wayland_PumpEvents(_this); WAYLAND_wl_display_flush(data->display); @@ -204,6 +204,14 @@ Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context) WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display ); } +EGLSurface +Wayland_GLES_GetEGLSurface(_THIS, SDL_Window * window) +{ + SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; + + return windowdata->egl_surface; +} + #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandopengles.h b/src/video/wayland/SDL_waylandopengles.h index b9500b9f1a..39e6cdf587 100644 --- a/src/video/wayland/SDL_waylandopengles.h +++ b/src/video/wayland/SDL_waylandopengles.h @@ -33,7 +33,7 @@ typedef struct SDL_PrivateGLESData /* OpenGLES functions */ #define Wayland_GLES_GetAttribute SDL_EGL_GetAttribute -#define Wayland_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define Wayland_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define Wayland_GLES_UnloadLibrary SDL_EGL_UnloadLibrary extern int Wayland_GLES_LoadLibrary(_THIS, const char *path); @@ -43,6 +43,7 @@ extern int Wayland_GLES_GetSwapInterval(_THIS); extern int Wayland_GLES_SwapWindow(_THIS, SDL_Window * window); extern int Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); extern void Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context); +extern SDL_EGLSurface Wayland_GLES_GetEGLSurface(_THIS, SDL_Window * window); #endif /* SDL_waylandopengles_h_ */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 76b93cd095..38e1b2810a 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -237,6 +237,7 @@ Wayland_CreateDevice(void) device->GL_UnloadLibrary = Wayland_GLES_UnloadLibrary; device->GL_GetProcAddress = Wayland_GLES_GetProcAddress; device->GL_DeleteContext = Wayland_GLES_DeleteContext; + device->GL_GetEGLSurface = Wayland_GLES_GetEGLSurface; #endif device->CreateSDLWindow = Wayland_CreateWindow; diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index c1df7f6b98..ffb0d040f2 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -689,6 +689,7 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window) _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; _this->GL_SwapWindow = WIN_GLES_SwapWindow; _this->GL_DeleteContext = WIN_GLES_DeleteContext; + _this->GL_GetEGLSurface = WIN_GLES_GetEGLSurface; if (WIN_GLES_LoadLibrary(_this, NULL) != 0) { return NULL; diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index 49cebd62dd..74fd946c58 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -45,6 +45,7 @@ WIN_GLES_LoadLibrary(_THIS, const char *path) { _this->GL_GetSwapInterval = WIN_GL_GetSwapInterval; _this->GL_SwapWindow = WIN_GL_SwapWindow; _this->GL_DeleteContext = WIN_GL_DeleteContext; + _this->GL_GetEGLSurface = NULL; return WIN_GL_LoadLibrary(_this, path); #else return SDL_SetError("SDL not configured with OpenGL/WGL support"); @@ -77,6 +78,7 @@ WIN_GLES_CreateContext(_THIS, SDL_Window * window) _this->GL_GetSwapInterval = WIN_GL_GetSwapInterval; _this->GL_SwapWindow = WIN_GL_SwapWindow; _this->GL_DeleteContext = WIN_GL_DeleteContext; + _this->GL_GetEGLSurface = NULL; if (WIN_GL_LoadLibrary(_this, NULL) != 0) { return NULL; @@ -130,6 +132,14 @@ WIN_GLES_SetupWindow(_THIS, SDL_Window * window) return WIN_GLES_MakeCurrent(_this, current_win, current_ctx); } +EGLSurface +WIN_GLES_GetEGLSurface(_THIS, SDL_Window * window) +{ + SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; + + return windowdata->egl_surface; +} + #endif /* SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/windows/SDL_windowsopengles.h b/src/video/windows/SDL_windowsopengles.h index b21c56f4fe..84171ec07d 100644 --- a/src/video/windows/SDL_windowsopengles.h +++ b/src/video/windows/SDL_windowsopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define WIN_GLES_GetAttribute SDL_EGL_GetAttribute -#define WIN_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define WIN_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define WIN_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define WIN_GLES_GetSwapInterval SDL_EGL_GetSwapInterval #define WIN_GLES_SetSwapInterval SDL_EGL_SetSwapInterval @@ -41,6 +41,7 @@ extern int WIN_GLES_SwapWindow(_THIS, SDL_Window * window); extern int WIN_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); extern void WIN_GLES_DeleteContext(_THIS, SDL_GLContext context); extern int WIN_GLES_SetupWindow(_THIS, SDL_Window * window); +extern SDL_EGLSurface WIN_GLES_GetEGLSurface(_THIS, SDL_Window * window); #endif /* SDL_VIDEO_OPENGL_EGL */ diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index bdf887bdb9..2c30fd2309 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -226,6 +226,7 @@ WIN_CreateDevice(void) device->GL_GetSwapInterval = WIN_GL_GetSwapInterval; device->GL_SwapWindow = WIN_GL_SwapWindow; device->GL_DeleteContext = WIN_GL_DeleteContext; + device->GL_GetEGLSurface = NULL; #endif #if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_WGL @@ -241,6 +242,7 @@ WIN_CreateDevice(void) device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; device->GL_SwapWindow = WIN_GLES_SwapWindow; device->GL_DeleteContext = WIN_GLES_DeleteContext; + device->GL_GetEGLSurface = WIN_GLES_GetEGLSurface; #if SDL_VIDEO_OPENGL_WGL } #endif diff --git a/src/video/winrt/SDL_winrtopengles.h b/src/video/winrt/SDL_winrtopengles.h index c702c8b69d..c56d665249 100644 --- a/src/video/winrt/SDL_winrtopengles.h +++ b/src/video/winrt/SDL_winrtopengles.h @@ -30,7 +30,7 @@ /* OpenGLES functions */ #define WINRT_GLES_GetAttribute SDL_EGL_GetAttribute -#define WINRT_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define WINRT_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define WINRT_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define WINRT_GLES_GetSwapInterval SDL_EGL_GetSwapInterval #define WINRT_GLES_DeleteContext SDL_EGL_DeleteContext diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c index 43d7a7d892..8e7ffb0a00 100644 --- a/src/video/x11/SDL_x11opengles.c +++ b/src/video/x11/SDL_x11opengles.c @@ -104,6 +104,13 @@ X11_GLES_CreateContext(_THIS, SDL_Window * window) return context; } +SDL_EGLSurface +X11_GLES_GetEGLSurface(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + return data->egl_surface; +} + SDL_EGL_SwapWindow_impl(X11) SDL_EGL_MakeCurrent_impl(X11) diff --git a/src/video/x11/SDL_x11opengles.h b/src/video/x11/SDL_x11opengles.h index 5219553ca9..6d4df5ef29 100644 --- a/src/video/x11/SDL_x11opengles.h +++ b/src/video/x11/SDL_x11opengles.h @@ -37,7 +37,7 @@ typedef struct SDL_PrivateGLESData /* OpenGLES functions */ #define X11_GLES_GetAttribute SDL_EGL_GetAttribute -#define X11_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define X11_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal #define X11_GLES_UnloadLibrary SDL_EGL_UnloadLibrary #define X11_GLES_SetSwapInterval SDL_EGL_SetSwapInterval #define X11_GLES_GetSwapInterval SDL_EGL_GetSwapInterval @@ -48,6 +48,7 @@ extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display * display, int screen); extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window * window); extern int X11_GLES_SwapWindow(_THIS, SDL_Window * window); extern int X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +extern SDL_EGLSurface X11_GLES_GetEGLSurface(_THIS, SDL_Window * window); #endif /* SDL_VIDEO_OPENGL_EGL */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 569e995f3d..3044bdfc33 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -279,6 +279,7 @@ X11_CreateDevice(void) device->GL_GetSwapInterval = X11_GL_GetSwapInterval; device->GL_SwapWindow = X11_GL_SwapWindow; device->GL_DeleteContext = X11_GL_DeleteContext; + device->GL_GetEGLSurface = NULL; #endif #if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_GLX @@ -294,6 +295,7 @@ X11_CreateDevice(void) device->GL_GetSwapInterval = X11_GLES_GetSwapInterval; device->GL_SwapWindow = X11_GLES_SwapWindow; device->GL_DeleteContext = X11_GLES_DeleteContext; + device->GL_GetEGLSurface = X11_GLES_GetEGLSurface; #if SDL_VIDEO_OPENGL_GLX } #endif From 085a276d6c53392dcf1467723e881d78e94e8a5e Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Thu, 25 Aug 2022 22:41:06 -0700 Subject: [PATCH 7/9] egl: implement callbacks for defining custom EGL attributes Depending on the underlying EGL library, it may be desirable to conditionally set some specific EGL attributes depending on available extensions and other application state. SDL's EGL usage makes this a little bit complicated because: - there are multiple functions used to set up a working EGL context - some of these functions take different types of EGL attributes (EGLAttrib vs EGLint) - the EGL extension list before creating an EGLDisplay differs from the extension list after (i.e. display vs client extensions) - all of the above happens in a single SDL_CreateWindow call This leaves no place for the application to discover what EGL extensions are available and provide custom attribute lists. Until now, if a developer wants to add a custom EGL attribute for eglGetPlatformDisplay, eglCreateWindowSurface or eglCreateContext, they needed to patch SDL itself. This is very undesirable, since such developers would have to disable the SDL dynapi in order to maintain compatibility with their needs. This patch implements some callbacks which developers can use to dynamically generate custom EGL attributes for SDL to use during SDL_CreateWindow. --- include/SDL_video.h | 32 ++++++++++++++++++++ src/video/SDL_egl.c | 65 ++++++++++++++++++++++++++++++++++++---- src/video/SDL_sysvideo.h | 4 +++ src/video/SDL_video.c | 16 ++++++++++ 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index cfbed9c892..ed7bcd36f1 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -223,6 +223,14 @@ typedef void *SDL_GLContext; typedef void *SDL_EGLDisplay; typedef void *SDL_EGLConfig; typedef void *SDL_EGLSurface; +typedef intptr_t SDL_EGLAttrib; +typedef int SDL_EGLint; + +/** + * \brief EGL attribute initialization callback types. + */ +typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void); +typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void); /** * \brief OpenGL configuration attributes @@ -2089,6 +2097,30 @@ extern DECLSPEC SDL_EGLConfig SDLCALL SDL_EGL_GetCurrentEGLConfig(void); */ extern DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowEGLSurface(SDL_Window * window); +/** + * Sets the callbacks for defining custom EGLAttrib arrays for EGL + * initialization. + * + * Each callback should return a pointer to an EGL attribute array terminated + * with EGL_NONE. Callbacks may return NULL pointers to signal an error, which + * will cause the SDL_CreateWindow process to fail gracefully. + * + * The arrays returned by each callback will be appended to the existing + * attribute arrays defined by SDL. + * + * NOTE: These callback pointers will be reset after SDL_GL_ResetAttributes. + * + * \param platformAttribCallback Callback for attributes to pass to + * eglGetPlatformDisplay. + * \param surfaceAttribCallback Callback for attributes to pass to + * eglCreateSurface. + * \param contextAttribCallback Callback for attributes to pass to + * eglCreateContext. + */ +extern DECLSPEC void SDLCALL SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback, + SDL_EGLIntArrayCallback surfaceAttribCallback, + SDL_EGLIntArrayCallback contextAttribCallback); + /** * Get the size of a window's underlying drawable in pixels. * diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 072b99ba9b..78f64b59f5 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -514,7 +514,16 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa } if (_this->egl_data->eglGetPlatformDisplay) { - _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, NULL); + EGLAttrib *attribs = NULL; + if (_this->egl_platformattrib_callback) { + attribs = _this->egl_platformattrib_callback(); + if (!attribs) { + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + return SDL_SetError("EGL platform attribute callback returned NULL pointer"); + } + } + _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, attribs); } else { if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) { _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddressInternal(_this, "eglGetPlatformDisplayEXT"); @@ -934,8 +943,8 @@ SDL_EGL_ChooseConfig(_THIS) SDL_GLContext SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface) { - /* max 14 values plus terminator. */ - EGLint attribs[15]; + /* max 16 key+value pairs plus terminator. */ + EGLint attribs[33]; int attr = 0; EGLContext egl_context, share_context = EGL_NO_CONTEXT; @@ -1024,6 +1033,29 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface) } #endif + if (_this->egl_contextattrib_callback) { + const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]); + EGLint *userAttribs, *userAttribP; + userAttribs = _this->egl_contextattrib_callback(); + if (!userAttribs) { + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + SDL_SetError("EGL context attribute callback returned NULL pointer"); + return NULL; + } + + for (userAttribP = userAttribs; *userAttribP != EGL_NONE; ) { + if (attr + 3 >= maxAttribs) { + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + SDL_SetError("EGL context attribute callback returned too many attributes"); + return NULL; + } + attribs[attr++] = *userAttribP++; + attribs[attr++] = *userAttribP++; + } + } + attribs[attr++] = EGL_NONE; /* Bind the API */ @@ -1190,8 +1222,8 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) EGLint format_wanted; EGLint format_got; #endif - /* max 2 key+value pairs, plus terminator. */ - EGLint attribs[5]; + /* max 16 key+value pairs, plus terminator. */ + EGLint attribs[33]; int attr = 0; EGLSurface * surface; @@ -1232,6 +1264,29 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) } #endif + if (_this->egl_surfaceattrib_callback) { + const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]); + EGLint *userAttribs, *userAttribP; + userAttribs = _this->egl_surfaceattrib_callback(); + if (!userAttribs) { + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + SDL_SetError("EGL surface attribute callback returned NULL pointer"); + return EGL_NO_SURFACE; + } + + for (userAttribP = userAttribs; *userAttribP != EGL_NONE; ) { + if (attr + 3 >= maxAttribs) { + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + SDL_SetError("EGL surface attribute callback returned too many attributes"); + return EGL_NO_SURFACE; + } + attribs[attr++] = *userAttribP++; + attribs[attr++] = *userAttribP++; + } + } + attribs[attr++] = EGL_NONE; surface = _this->egl_data->eglCreateWindowSurface( diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 63d3eea84d..5fd794a554 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -398,6 +398,10 @@ struct SDL_VideoDevice void *dll_handle; } gl_config; + SDL_EGLAttribArrayCallback egl_platformattrib_callback; + SDL_EGLIntArrayCallback egl_surfaceattrib_callback; + SDL_EGLIntArrayCallback egl_contextattrib_callback; + /* * * */ /* Cache current GL context; don't call the OS when it hasn't changed. */ /* We have the global pointers here so Cocoa continues to work the way diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 36276e9698..294f93d544 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3646,6 +3646,18 @@ SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor) #endif } +void SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback, + SDL_EGLIntArrayCallback surfaceAttribCallback, + SDL_EGLIntArrayCallback contextAttribCallback) +{ + if (!_this) { + return; + } + _this->egl_platformattrib_callback = platformAttribCallback; + _this->egl_surfaceattrib_callback = surfaceAttribCallback; + _this->egl_contextattrib_callback = contextAttribCallback; +} + void SDL_GL_ResetAttributes() { @@ -3653,6 +3665,10 @@ SDL_GL_ResetAttributes() return; } + _this->egl_platformattrib_callback = NULL; + _this->egl_surfaceattrib_callback = NULL; + _this->egl_contextattrib_callback = NULL; + _this->gl_config.red_size = 3; _this->gl_config.green_size = 3; _this->gl_config.blue_size = 2; From e8fbb02d160ff1ef461f27ec62925284a1ed7a48 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Sun, 11 Sep 2022 12:30:18 -0700 Subject: [PATCH 8/9] windows: support forcing EGL for GL desktop This will theoretically support ANGLE's GL desktop frontend whenever it becomes fully implemented and enabled in the future. --- src/video/SDL_egl.c | 1 + src/video/windows/SDL_windowsopengles.c | 7 +++++-- src/video/windows/SDL_windowswindow.c | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 78f64b59f5..183c2546f4 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -76,6 +76,7 @@ #elif SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT /* EGL AND OpenGL ES support via ANGLE */ #define DEFAULT_EGL "libEGL.dll" +#define DEFAULT_OGL "opengl32.dll" #define DEFAULT_OGL_ES2 "libGLESv2.dll" #define DEFAULT_OGL_ES_PVR "libGLES_CM.dll" #define DEFAULT_OGL_ES "libGLESv1_CM.dll" diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index 74fd946c58..4ba30ba4fd 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -22,6 +22,7 @@ #if SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#include "SDL_hints.h" #include "SDL_windowsvideo.h" #include "SDL_windowsopengles.h" #include "SDL_windowsopengl.h" @@ -33,7 +34,8 @@ int WIN_GLES_LoadLibrary(_THIS, const char *path) { /* If the profile requested is not GL ES, switch over to WIN_GL functions */ - if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) { + if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES && + !SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) { #if SDL_VIDEO_OPENGL_WGL WIN_GLES_UnloadLibrary(_this); _this->GL_LoadLibrary = WIN_GL_LoadLibrary; @@ -66,7 +68,8 @@ WIN_GLES_CreateContext(_THIS, SDL_Window * window) SDL_WindowData *data = (SDL_WindowData *)window->driverdata; #if SDL_VIDEO_OPENGL_WGL - if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) { + if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES && + !SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) { /* Switch to WGL based functions */ WIN_GLES_UnloadLibrary(_this); _this->GL_LoadLibrary = WIN_GL_LoadLibrary; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 488b6fe1a5..ec69de5e14 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -542,9 +542,10 @@ WIN_CreateWindow(_THIS, SDL_Window * window) /* The rest of this macro mess is for OpenGL or OpenGL ES windows */ #if SDL_VIDEO_OPENGL_ES2 - if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES + if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES || + SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) && #if SDL_VIDEO_OPENGL_WGL - && (!_this->gl_data || WIN_GL_UseEGL(_this)) + (!_this->gl_data || WIN_GL_UseEGL(_this)) #endif /* SDL_VIDEO_OPENGL_WGL */ ) { #if SDL_VIDEO_OPENGL_EGL From 3d8a7e4c15bb8e1340157b73831266c9e79ff12d Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Fri, 9 Apr 2021 07:44:38 -0700 Subject: [PATCH 9/9] cocoa: implement GL_GetDrawableSize for OpenGL ES --- src/video/cocoa/SDL_cocoaopengles.h | 2 ++ src/video/cocoa/SDL_cocoaopengles.m | 23 ++++++++++++++++++++++- src/video/cocoa/SDL_cocoavideo.m | 1 + src/video/cocoa/SDL_cocoawindow.m | 7 +++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/video/cocoa/SDL_cocoaopengles.h b/src/video/cocoa/SDL_cocoaopengles.h index 05800e3e42..4b3b53cc66 100644 --- a/src/video/cocoa/SDL_cocoaopengles.h +++ b/src/video/cocoa/SDL_cocoaopengles.h @@ -39,6 +39,8 @@ extern int Cocoa_GLES_LoadLibrary(_THIS, const char *path); extern SDL_GLContext Cocoa_GLES_CreateContext(_THIS, SDL_Window * window); extern int Cocoa_GLES_SwapWindow(_THIS, SDL_Window * window); extern int Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +extern void Cocoa_GLES_GetDrawableSize(_THIS, SDL_Window * window, + int * w, int * h); extern void Cocoa_GLES_DeleteContext(_THIS, SDL_GLContext context); extern int Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window); extern SDL_EGLSurface Cocoa_GLES_GetEGLSurface(_THIS, SDL_Window * window); diff --git a/src/video/cocoa/SDL_cocoaopengles.m b/src/video/cocoa/SDL_cocoaopengles.m index b8f17282d2..6df958f1db 100644 --- a/src/video/cocoa/SDL_cocoaopengles.m +++ b/src/video/cocoa/SDL_cocoaopengles.m @@ -114,8 +114,29 @@ Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) return SDL_EGL_MakeCurrent(_this, window ? ((__bridge SDL_WindowData *) window->driverdata).egl_surface : EGL_NO_SURFACE, context); }} +void +Cocoa_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) +{ @autoreleasepool +{ + SDL_WindowData *windata = (__bridge SDL_WindowData *)window->driverdata; + NSView *contentView = windata.nswindow.contentView; + CALayer *layer = [contentView layer]; + + int width = layer.bounds.size.width * layer.contentsScale; + int height = layer.bounds.size.height * layer.contentsScale; + + if (w) { + *w = width; + } + + if (h) { + *h = height; + } +}} + int Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window) +{ @autoreleasepool { NSView* v; /* The current context is lost in here; save it and reset it. */ @@ -145,7 +166,7 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window) } return Cocoa_GLES_MakeCurrent(_this, current_win, current_ctx); -} +}} SDL_EGLSurface Cocoa_GLES_GetEGLSurface(_THIS, SDL_Window * window) diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index a354a2451e..da43da732e 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -150,6 +150,7 @@ Cocoa_CreateDevice(void) device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary; device->GL_CreateContext = Cocoa_GLES_CreateContext; device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent; + device->GL_GetDrawableSize = Cocoa_GLES_GetDrawableSize; device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval; device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval; device->GL_SwapWindow = Cocoa_GLES_SwapWindow; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index eea7f981a6..7d5ee09316 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1787,6 +1787,13 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window) if ((window->flags & SDL_WINDOW_OPENGL) && _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { [contentView setWantsLayer:TRUE]; + if (!(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) { + contentView.layer.contentsScale = 1; + } else { + if ([nswindow.screen respondsToSelector:@selector(backingScaleFactor)]) { + contentView.layer.contentsScale = nswindow.screen.backingScaleFactor; + } + } } #endif /* SDL_VIDEO_OPENGL_EGL */ #endif /* SDL_VIDEO_OPENGL_ES2 */