From d62f141b291bd756b85b12a56c9c2333383de146 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 14 Nov 2025 10:45:37 -0500
Subject: [PATCH] opengl: Fixes for sRGB framebuffer support.
This changes the default for SDL_GL_FRAMEBUFFER_SRGB_CAPABLE to -1 (for
"don't care"). Minor ABI break, but technically this never worked correctly.
Fixes #13055.
---
include/SDL3/SDL_video.h | 2 +-
src/video/SDL_video.c | 2 +-
src/video/windows/SDL_windowsopengl.c | 20 ++++++++++++++------
src/video/windows/SDL_windowsopengl.h | 1 +
src/video/x11/SDL_x11opengl.c | 11 +++++++++--
src/video/x11/SDL_x11opengl.h | 1 +
6 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h
index d72194674819d..f5f92fcd1946b 100644
--- a/include/SDL3/SDL_video.h
+++ b/include/SDL3/SDL_video.h
@@ -490,7 +490,7 @@ typedef enum SDL_GLAttr
SDL_GL_CONTEXT_FLAGS, /**< some combination of 0 or more of elements of the SDL_GLContextFlag enumeration; defaults to 0. */
SDL_GL_CONTEXT_PROFILE_MASK, /**< type of GL context (Core, Compatibility, ES). See SDL_GLProfile; default value depends on platform. */
SDL_GL_SHARE_WITH_CURRENT_CONTEXT, /**< OpenGL context sharing; defaults to 0. */
- SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB capable visual; defaults to 0. */
+ SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB-capable visual if 1. Defaults to -1 ("don't care"). This is a request; GL drivers might not comply! */
SDL_GL_CONTEXT_RELEASE_BEHAVIOR, /**< sets context the release behavior. See SDL_GLContextReleaseFlag; defaults to FLUSH. */
SDL_GL_CONTEXT_RESET_NOTIFICATION, /**< set context reset notification. See SDL_GLContextResetNotification; defaults to NO_NOTIFICATION. */
SDL_GL_CONTEXT_NO_ERROR,
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 18e7bd0e0feed..17dc158c08470 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -4948,7 +4948,7 @@ void SDL_GL_ResetAttributes(void)
}
_this->gl_config.flags = 0;
- _this->gl_config.framebuffer_srgb_capable = 0;
+ _this->gl_config.framebuffer_srgb_capable = -1;
_this->gl_config.no_error = 0;
_this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
_this->gl_config.reset_notification = SDL_GL_CONTEXT_RESET_NO_NOTIFICATION;
diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c
index 7210a9749d634..cc10f93ad6fe7 100644
--- a/src/video/windows/SDL_windowsopengl.c
+++ b/src/video/windows/SDL_windowsopengl.c
@@ -512,6 +512,13 @@ void WIN_GL_InitExtensions(SDL_VideoDevice *_this)
_this->gl_data->HAS_WGL_ARB_create_context_no_error = true;
}
+ // Check for WGL_ARB_framebuffer_sRGB
+ if (HasExtension("WGL_ARB_framebuffer_sRGB", extensions)) {
+ _this->gl_data->HAS_WGL_ARB_framebuffer_sRGB = true;
+ } else if (HasExtension("WGL_EXT_framebuffer_sRGB", extensions)) { // same thing.
+ _this->gl_data->HAS_WGL_ARB_framebuffer_sRGB = true;
+ }
+
/* Check for WGL_ARB_pixel_format_float */
_this->gl_data->HAS_WGL_ARB_pixel_format_float =
HasExtension("WGL_ARB_pixel_format_float", extensions);
@@ -532,9 +539,6 @@ static int WIN_GL_ChoosePixelFormatARB(SDL_VideoDevice *_this, int *iAttribs, fl
int pixel_format = 0;
unsigned int matching;
- int qAttrib = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
- int srgb = 0;
-
hwnd =
CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
10, 10, NULL, NULL, SDL_Instance, NULL);
@@ -556,7 +560,11 @@ static int WIN_GL_ChoosePixelFormatARB(SDL_VideoDevice *_this, int *iAttribs, fl
&matching);
// Check whether we actually got an SRGB capable buffer
- _this->gl_data->wglGetPixelFormatAttribivARB(hdc, pixel_format, 0, 1, &qAttrib, &srgb);
+ int srgb = 0;
+ if (_this->gl_data->HAS_WGL_ARB_framebuffer_sRGB) {
+ int qAttrib = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
+ _this->gl_data->wglGetPixelFormatAttribivARB(hdc, pixel_format, 0, 1, &qAttrib, &srgb);
+ }
_this->gl_config.framebuffer_srgb_capable = srgb;
}
@@ -651,9 +659,9 @@ static bool WIN_GL_SetupWindowInternal(SDL_VideoDevice *_this, SDL_Window *windo
*iAttr++ = WGL_TYPE_RGBA_FLOAT_ARB;
}
- if (_this->gl_config.framebuffer_srgb_capable) {
+ if ((_this->gl_config.framebuffer_srgb_capable >= 0) && _this->gl_data->HAS_WGL_ARB_framebuffer_sRGB) {
*iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
- *iAttr++ = _this->gl_config.framebuffer_srgb_capable;
+ *iAttr++ = _this->gl_config.framebuffer_srgb_capable ? GL_TRUE : GL_FALSE;
}
/* We always choose either FULL or NO accel on Windows, because of flaky
diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h
index c35120473e2c6..71f4e34bbe4f4 100644
--- a/src/video/windows/SDL_windowsopengl.h
+++ b/src/video/windows/SDL_windowsopengl.h
@@ -66,6 +66,7 @@ struct SDL_GLDriverData
bool HAS_WGL_ARB_create_context_no_error;
bool HAS_WGL_ARB_pixel_format_float;
bool HAS_WGL_EXT_create_context_es2_profile;
+ bool HAS_WGL_ARB_framebuffer_sRGB;
/* Max version of OpenGL ES context that can be created if the
implementation supports WGL_EXT_create_context_es2_profile.
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index e005400cf00b0..041b5e88955dd 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -466,6 +466,13 @@ static void X11_GL_InitExtensions(SDL_VideoDevice *_this)
_this->gl_data->HAS_GLX_ARB_create_context_no_error = true;
}
+ // Check for GLX_ARB_framebuffer_sRGB
+ if (HasExtension("GLX_ARB_framebuffer_sRGB", extensions)) {
+ _this->gl_data->HAS_GLX_ARB_framebuffer_sRGB = true;
+ } else if (HasExtension("GLX_EXT_framebuffer_sRGB", extensions)) { // same thing.
+ _this->gl_data->HAS_GLX_ARB_framebuffer_sRGB = true;
+ }
+
if (context) {
_this->gl_data->glXMakeCurrent(display, None, NULL);
_this->gl_data->glXDestroyContext(display, context);
@@ -576,9 +583,9 @@ static int X11_GL_GetAttributes(SDL_VideoDevice *_this, Display *display, int sc
attribs[i++] = GLX_RGBA_FLOAT_TYPE_ARB;
}
- if (_this->gl_config.framebuffer_srgb_capable) {
+ if ((_this->gl_config.framebuffer_srgb_capable >= 0) && _this->gl_data->HAS_GLX_ARB_framebuffer_sRGB) {
attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
- attribs[i++] = True; // always needed, for_FBConfig or not!
+ attribs[i++] = _this->gl_config.framebuffer_srgb_capable ? True : False; // always needed, for_FBConfig or not!
}
if (_this->gl_config.accelerated >= 0 &&
diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h
index 24db485be7b07..8470e7ccabdb6 100644
--- a/src/video/x11/SDL_x11opengl.h
+++ b/src/video/x11/SDL_x11opengl.h
@@ -47,6 +47,7 @@ struct SDL_GLDriverData
bool HAS_GLX_ARB_context_flush_control;
bool HAS_GLX_ARB_create_context_robustness;
bool HAS_GLX_ARB_create_context_no_error;
+ bool HAS_GLX_ARB_framebuffer_sRGB;
/* Max version of OpenGL ES context that can be created if the
implementation supports GLX_EXT_create_context_es2_profile.