SDL: egl: implement public functions to obtain internal EGL handles

From 0644042eb8781781a56ff2430740ef654c3b67f1 Mon Sep 17 00:00:00 2001
From: Steven Noonan <[EMAIL REDACTED]>
Date: Thu, 25 Aug 2022 19:44:35 -0700
Subject: [PATCH] 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 8e9ed8da2b1c..cfbed9c89213 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 f1a9bc14f718..072b99ba9b2a 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 c983012e15eb..3cf3cbb57b00 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 20340da60a16..63d3eea84d23 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 6f5d468550e3..36276e969829 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 3ed828fde1bc..d405e7004d7f 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 bfabb6d57f9d..05800e3e426e 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 04561b281f16..b8f17282d2c6 100644
--- a/src/video/cocoa/SDL_cocoaopengles.m
+++ b/src/video/cocoa/SDL_cocoaopengles.m
@@ -44,6 +44,7 @@
         _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 @@
         _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 @@
     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 d95718433919..a354a2451ee7 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -139,6 +139,7 @@ @implementation SDL_VideoData
     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 @@ @implementation SDL_VideoData
         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 9d178f6902d9..b054dbd1a585 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 a762ab0f3744..1f3eb3631dc9 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 6c9e51820025..deafd09cc53f 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 2cdf0fdcf827..59b7e572028a 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 33758d691c28..b7f452303695 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 dce74ae6bb39..2484f413e1fe 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 a0af3f5a4b88..f90d7ac00cab 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 b9500b9f1aa7..39e6cdf5876e 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 76b93cd0952b..38e1b2810a56 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 c1df7f6b9811..ffb0d040f219 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 49cebd62dd2f..74fd946c5833 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 b21c56f4fedd..84171ec07df6 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 bdf887bdb902..2c30fd230953 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 c702c8b69d14..c56d6652497e 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 43d7a7d892c4..8e7ffb0a00f8 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 5219553ca969..6d4df5ef2955 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 569e995f3d3a..3044bdfc3356 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