From 083c6b8872493fadbefddf26070e462b240a8b10 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 6 Feb 2026 13:39:36 -0500
Subject: [PATCH] video: Force GL_FRAMEBUFFER_SRGB state at OpenGL context
creation time.
The default varies between OpenGL and OpenGL ES, so try to force it to what
the app actually requested with SDL_GL_FRAMEBUFFER_SRGB_CAPABLE.
Fixes #14898.
---
src/video/SDL_video.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 054538c1d9285..1791c4d029099 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -61,6 +61,11 @@
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
#endif
+// This is always the same number between the various EXT/ARB/GLES extensions.
+#ifndef GL_FRAMEBUFFER_SRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
#ifdef SDL_PLATFORM_EMSCRIPTEN
#include <emscripten.h>
#endif
@@ -4780,6 +4785,7 @@ void SDL_GL_UnloadLibrary(void)
typedef GLenum (APIENTRY* PFNGLGETERRORPROC) (void);
typedef void (APIENTRY* PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
typedef const GLubyte *(APIENTRY* PFNGLGETSTRINGPROC) (GLenum name);
+typedef const void (APIENTRY* PFNGLENABLEPROC) (GLenum cap);
#ifndef SDL_VIDEO_OPENGL
typedef const GLubyte *(APIENTRY* PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
#endif
@@ -5388,6 +5394,8 @@ SDL_GLContext SDL_GL_CreateContext(SDL_Window *window)
return NULL;
}
+ const bool srgb_requested = (_this->gl_config.framebuffer_srgb_capable > 0);
+
ctx = _this->GL_CreateContext(_this, window);
// Creating a context is assumed to make it current in the SDL driver.
@@ -5397,6 +5405,25 @@ SDL_GLContext SDL_GL_CreateContext(SDL_Window *window)
SDL_SetTLS(&_this->current_glwin_tls, window, NULL);
SDL_SetTLS(&_this->current_glctx_tls, ctx, NULL);
}
+
+ // try to force the window framebuffer to the requested sRGB state.
+ PFNGLENABLEPROC glToggleFunc = (PFNGLENABLEPROC) SDL_GL_GetProcAddress(srgb_requested ? "glEnable" : "glDisable");
+ PFNGLGETSTRINGPROC glGetStringFunc = (PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString");
+ if (glToggleFunc && glGetStringFunc) {
+ bool supported = isAtLeastGL3((const char *)glGetStringFunc(GL_VERSION)); // no extensions needed in OpenGL 3+ or GLES 3+.
+ if (!supported) {
+ if (_this->gl_config.profile_mask & SDL_GL_CONTEXT_PROFILE_ES) {
+ supported = SDL_GL_ExtensionSupported("GL_EXT_sRGB_write_control");
+ } else {
+ supported = SDL_GL_ExtensionSupported("GL_EXT_framebuffer_sRGB") || SDL_GL_ExtensionSupported("GL_ARB_framebuffer_sRGB");
+ }
+ }
+
+ if (supported) {
+ glToggleFunc(GL_FRAMEBUFFER_SRGB);
+ }
+ }
+
return ctx;
}