Browse Source

Merge pull request #6317 from tycho/wip/angle-egl

EGL: fixes for better ANGLE support
Ryan C. Gordon 2 years ago
parent
commit
040a17a50f

+ 27 - 0
include/SDL_hints.h

@@ -1652,6 +1652,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.
  *
@@ -1811,6 +1823,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
  *
@@ -1819,6 +1843,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"
 

+ 82 - 1
include/SDL_video.h

@@ -217,6 +217,21 @@ typedef enum
  */
 typedef void *SDL_GLContext;
 
+/**
+ *  \brief Opaque EGL types.
+ */
+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
  */
@@ -249,7 +264,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
@@ -1902,6 +1918,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().
  *
@@ -2040,6 +2071,56 @@ 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);
+
+/**
+ * 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.
  *

+ 67 - 9
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"
@@ -242,7 +243,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)
 {
     void *retval = NULL;
     if (_this->egl_data != NULL) {
@@ -518,7 +519,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) {
@@ -526,10 +527,19 @@ 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_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);
                 }
@@ -538,7 +548,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) {
@@ -944,8 +956,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;
@@ -1034,6 +1046,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 */
@@ -1200,8 +1235,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;
@@ -1242,6 +1277,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(

+ 2 - 2
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);
@@ -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);

+ 6 - 0
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);
@@ -391,11 +392,16 @@ 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;
     } 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

+ 129 - 16
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"
@@ -1902,16 +1903,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;
@@ -1942,6 +1933,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;
@@ -3283,6 +3284,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);
@@ -3291,12 +3298,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) {
@@ -3466,6 +3467,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)
 {
@@ -3606,6 +3632,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()
 {
@@ -3613,6 +3651,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;
@@ -3659,6 +3701,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
@@ -3775,6 +3819,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;
@@ -3984,6 +4031,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");
     }
@@ -4129,6 +4182,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,);

+ 1 - 1
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

+ 4 - 1
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
@@ -39,8 +39,11 @@ 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);
 
 #endif /* SDL_VIDEO_OPENGL_EGL */
 

+ 33 - 3
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");
@@ -51,7 +52,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;
@@ -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;
@@ -112,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. */
@@ -127,7 +150,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;
         }
@@ -143,7 +166,14 @@ 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 */
 

+ 20 - 10
src/video/cocoa/SDL_cocoavideo.m

@@ -139,16 +139,26 @@ 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;
+    device->GL_GetEGLSurface = NULL;
+#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_GetDrawableSize = Cocoa_GLES_GetDrawableSize;
+        device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval;
+        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
 #endif
 
 #if SDL_VIDEO_VULKAN

+ 7 - 0
src/video/cocoa/SDL_cocoawindow.m

@@ -1799,6 +1799,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 */

+ 0 - 1
src/video/emscripten/SDL_emscriptenopengles.h

@@ -28,7 +28,6 @@
 #include "../SDL_sysvideo.h"
 
 /* OpenGLES functions */
-
 extern int Emscripten_GLES_LoadLibrary(_THIS, const char *path);
 extern void Emscripten_GLES_UnloadLibrary(_THIS);
 extern void * Emscripten_GLES_GetProcAddress(_THIS, const char *proc);

+ 1 - 1
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
 

+ 1 - 1
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

+ 1 - 1
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

+ 1 - 1
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

+ 1 - 1
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

+ 9 - 1
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: */

+ 2 - 1
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_ */
 

+ 1 - 0
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;

+ 1 - 0
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;

+ 17 - 4
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;
@@ -45,6 +47,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");
@@ -52,7 +55,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;
@@ -65,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;
@@ -77,6 +81,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;
@@ -113,7 +118,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;
         }
@@ -130,6 +135,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: */

+ 2 - 1
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 */
 

+ 20 - 11
src/video/windows/SDL_windowsvideo.c

@@ -226,17 +226,26 @@ 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;
+    device->GL_GetEGLSurface = NULL;
+#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;
+        device->GL_GetEGLSurface = WIN_GLES_GetEGLSurface;
+#if SDL_VIDEO_OPENGL_WGL
+    }
+#endif
 #endif
 #if SDL_VIDEO_VULKAN
     device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary;

+ 3 - 2
src/video/windows/SDL_windowswindow.c

@@ -543,9 +543,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

+ 1 - 1
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

+ 3 - 1
src/video/x11/SDL_x11opengl.c

@@ -251,6 +251,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
@@ -689,7 +690,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;

+ 9 - 1
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);
@@ -54,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 *
@@ -103,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)
 

+ 2 - 1
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 */
 

+ 4 - 1
src/video/x11/SDL_x11video.c

@@ -284,10 +284,12 @@ 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
-    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;
@@ -298,6 +300,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

+ 1 - 0
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) )