From ff543723c4a09235eac7d30ebda21bde4beda8ca Mon Sep 17 00:00:00 2001
From: Andrei Alexeyev <[EMAIL REDACTED]>
Date: Mon, 16 Mar 2026 02:19:59 +0100
Subject: [PATCH] Fix SDL_HINT_OPENGL_ES_DRIVER interaction with
SDL_HINT_OPENGL_LIBRARY for x11 and windows
If SDL_HINT_OPENGL_ES_DRIVER is enabled and a GLES context is requested,
don't try to load the WGL/GLX library. Doing so may fail, because
SDL_HINT_OPENGL_LIBRARY may have been set to a custom libGLESv2 (e.g.
ANGLE). This effectively restores the SDL2 behavior.
Other video drivers shouldn't be affected, because they always use EGL
for GLES.
Incidentally, this patch also fixes a missing GL_GetEGLSurface callback
in the X11 fallback path.
---
src/video/windows/SDL_windowsopengl.c | 40 +++++++++++++++++---------
src/video/x11/SDL_x11opengl.c | 41 +++++++++++++++++----------
2 files changed, 53 insertions(+), 28 deletions(-)
diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c
index 5e3b79c196ed6..b87f90e6b4cf7 100644
--- a/src/video/windows/SDL_windowsopengl.c
+++ b/src/video/windows/SDL_windowsopengl.c
@@ -106,10 +106,35 @@ typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC,
#define SetPixelFormat _this->gl_data->wglSetPixelFormat
#endif
+static bool WIN_GL_LoadLibrary_EGLFallback(SDL_VideoDevice *_this, const char *path)
+{
+#ifdef SDL_VIDEO_OPENGL_EGL
+ WIN_GL_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
+ _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
+ _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
+ _this->GL_CreateContext = WIN_GLES_CreateContext;
+ _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
+ _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
+ _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
+ _this->GL_SwapWindow = WIN_GLES_SwapWindow;
+ _this->GL_DestroyContext = WIN_GLES_DestroyContext;
+ _this->GL_GetEGLSurface = WIN_GLES_GetEGLSurface;
+ return WIN_GLES_LoadLibrary(_this, path);
+#else
+ return SDL_SetError("SDL not configured with EGL support");
+#endif
+}
+
bool WIN_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
void *handle;
+ if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) &&
+ SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, false)) {
+ return WIN_GL_LoadLibrary_EGLFallback(_this, path);
+ }
+
if (path == NULL) {
path = SDL_GetHint(SDL_HINT_OPENGL_LIBRARY);
}
@@ -740,19 +765,8 @@ SDL_GLContext WIN_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && WIN_GL_UseEGL(_this)) {
#ifdef SDL_VIDEO_OPENGL_EGL
// Switch to EGL based functions
- WIN_GL_UnloadLibrary(_this);
- _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
- _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
- _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
- _this->GL_CreateContext = WIN_GLES_CreateContext;
- _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
- _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
- _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
- _this->GL_SwapWindow = WIN_GLES_SwapWindow;
- _this->GL_DestroyContext = WIN_GLES_DestroyContext;
- _this->GL_GetEGLSurface = WIN_GLES_GetEGLSurface;
-
- if (!WIN_GLES_LoadLibrary(_this, NULL)) {
+
+ if (!WIN_GL_LoadLibrary_EGLFallback(_this, NULL)) {
return NULL;
}
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index 07e895d46c8b6..9724913c73e96 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -163,6 +163,26 @@ typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display *dpy,
static void X11_GL_InitExtensions(SDL_VideoDevice *_this);
+static bool X11_GL_LoadLibrary_EGLFallback(SDL_VideoDevice *_this, const char *path)
+{
+#ifdef SDL_VIDEO_OPENGL_EGL
+ X11_GL_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
+ _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
+ _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
+ _this->GL_CreateContext = X11_GLES_CreateContext;
+ _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
+ _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
+ _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
+ _this->GL_SwapWindow = X11_GLES_SwapWindow;
+ _this->GL_DestroyContext = X11_GLES_DestroyContext;
+ _this->GL_GetEGLSurface = X11_GLES_GetEGLSurface;
+ return X11_GLES_LoadLibrary(_this, path);
+#else
+ return SDL_SetError("SDL not configured with EGL support");
+#endif
+}
+
bool X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
Display *display;
@@ -172,6 +192,11 @@ bool X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
return SDL_SetError("OpenGL context already created");
}
+ if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) &&
+ SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, false)) {
+ return X11_GL_LoadLibrary_EGLFallback(_this, path);
+ }
+
// Load the OpenGL library
if (path == NULL) {
path = SDL_GetHint(SDL_HINT_OPENGL_LIBRARY);
@@ -254,21 +279,7 @@ bool X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) &&
X11_GL_UseEGL(_this)) {
-#ifdef SDL_VIDEO_OPENGL_EGL
- X11_GL_UnloadLibrary(_this);
- _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
- _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
- _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
- _this->GL_CreateContext = X11_GLES_CreateContext;
- _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
- _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
- _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
- _this->GL_SwapWindow = X11_GLES_SwapWindow;
- _this->GL_DestroyContext = X11_GLES_DestroyContext;
- return X11_GLES_LoadLibrary(_this, NULL);
-#else
- return SDL_SetError("SDL not configured with EGL support");
-#endif
+ return X11_GL_LoadLibrary_EGLFallback(_this, NULL);
}
return true;