opengl: added SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE.

Reference Issue #14898.
This commit is contained in:
Ryan C. Gordon
2026-02-04 13:47:10 -05:00
parent 0cadc15ef6
commit 632c83b722
5 changed files with 84 additions and 14 deletions
+36
View File
@@ -3040,6 +3040,42 @@ extern "C" {
*/ */
#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" #define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER"
/**
* A variable controlling whether to force an sRGB-capable OpenGL context.
*
* At OpenGL context creation time, some platforms can request an sRGB-capable
* context. However, sometimes any form of the request can cause surprising
* results on some drivers, platforms, and hardware. Usually the surprise is
* in the form of rendering that is either a little darker or a little
* brighter than intended.
*
* This hint allows the user to override the app's sRGB requests and either
* force a specific value, or avoid requesting anything at all, depending on
* what makes things work correctly for their system.
*
* This is meant as a fail-safe; apps should probably not explicitly set this,
* and most users should not, either.
*
* Note that some platforms cannot make this request at all, and on all
* platforms this request can be denied by the operating system.
*
* The variable can be set to the following values:
*
* - "0": Force a request for an OpenGL context that is _not_ sRGB-capable.
* - "1": Force a request for an OpenGL context that _is_ sRGB-capable.
* - "skip": Don't make any request for an sRGB-capable context
* (don't specify the attribute at all during context creation time).
* - any other string is undefined behavior.
*
* If unset, or set to an empty string, SDL will make a request using the
* value the app specified with the SDL_GL_FRAMEBUFFER_SRGB_CAPABLE attribute.
*
* This hint should be set before an OpenGL context is created.
*
* \since This hint is available since SDL 3.4.2.
*/
#define SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE "SDL_OPENGL_FORCE_SRGB_CAPABLE"
/** /**
* Mechanism to specify openvr_api library location * Mechanism to specify openvr_api library location
* *
+12 -7
View File
@@ -38,6 +38,7 @@
#include "SDL_sysvideo.h" #include "SDL_sysvideo.h"
#include "SDL_egl_c.h" #include "SDL_egl_c.h"
#include "../SDL_hints_c.h"
#ifdef EGL_KHR_create_context #ifdef EGL_KHR_create_context
// EGL_OPENGL_ES3_BIT_KHR was added in version 13 of the extension. // EGL_OPENGL_ES3_BIT_KHR was added in version 13 of the extension.
@@ -1288,18 +1289,22 @@ EGLSurface SDL_EGL_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, Nat
ANativeWindow_setBuffersGeometry(nw, 0, 0, format_wanted); ANativeWindow_setBuffersGeometry(nw, 0, 0, format_wanted);
#endif #endif
if (_this->gl_config.framebuffer_srgb_capable >= 0) {
#ifdef EGL_KHR_gl_colorspace #ifdef EGL_KHR_gl_colorspace
if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) { if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) {
const char *srgbhint = SDL_GetHint(SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE);
if (srgbhint && *srgbhint) {
if (SDL_strcmp(srgbhint, "skip") == 0) {
// don't set an attribute at all.
} else {
attribs[attr++] = EGL_GL_COLORSPACE_KHR;
attribs[attr++] = SDL_GetStringBoolean(srgbhint, false) ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR;
}
} else if (_this->gl_config.framebuffer_srgb_capable >= 0) { // default behavior without the hint.
attribs[attr++] = EGL_GL_COLORSPACE_KHR; attribs[attr++] = EGL_GL_COLORSPACE_KHR;
attribs[attr++] = _this->gl_config.framebuffer_srgb_capable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR; attribs[attr++] = _this->gl_config.framebuffer_srgb_capable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR;
} else }
}
#endif #endif
if (_this->gl_config.framebuffer_srgb_capable > 0) {
SDL_SetError("EGL implementation does not support sRGB system framebuffers");
return EGL_NO_SURFACE;
}
}
int opaque_ext_idx = -1; int opaque_ext_idx = -1;
+8 -1
View File
@@ -31,6 +31,7 @@
#include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h" #include "../../events/SDL_mouse_c.h"
#include "../../power/uikit/SDL_syspower.h" #include "../../power/uikit/SDL_syspower.h"
#include "../../SDL_hints_c.h"
#include <dlfcn.h> #include <dlfcn.h>
@interface SDLEAGLContext : EAGLContext @interface SDLEAGLContext : EAGLContext
@@ -153,6 +154,12 @@ SDL_GLContext UIKit_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
return NULL; return NULL;
} }
int srgb = _this->gl_config.framebuffer_srgb_capable;
const char *srgbhint = SDL_GetHint(SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE);
if (srgbhint && *srgbhint) {
srgb = SDL_GetStringBoolean(srgbhint, false) ? 1 : 0; // there is no "skip" here, since initWithFrame expects it, so we'll treat it as false.
}
// construct our view, passing in SDL's OpenGL configuration data // construct our view, passing in SDL's OpenGL configuration data
view = [[SDL_uikitopenglview alloc] initWithFrame:frame view = [[SDL_uikitopenglview alloc] initWithFrame:frame
scale:scale scale:scale
@@ -163,7 +170,7 @@ SDL_GLContext UIKit_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
aBits:_this->gl_config.alpha_size aBits:_this->gl_config.alpha_size
depthBits:_this->gl_config.depth_size depthBits:_this->gl_config.depth_size
stencilBits:_this->gl_config.stencil_size stencilBits:_this->gl_config.stencil_size
sRGB:_this->gl_config.framebuffer_srgb_capable sRGB:srgb
multisamples:samples multisamples:samples
context:context]; context:context];
+12 -1
View File
@@ -24,6 +24,7 @@
#include "SDL_windowsvideo.h" #include "SDL_windowsvideo.h"
#include "SDL_windowsopengles.h" #include "SDL_windowsopengles.h"
#include "../../SDL_hints_c.h"
// WGL implementation of SDL OpenGL support // WGL implementation of SDL OpenGL support
@@ -659,10 +660,20 @@ static bool WIN_GL_SetupWindowInternal(SDL_VideoDevice *_this, SDL_Window *windo
*iAttr++ = WGL_TYPE_RGBA_FLOAT_ARB; *iAttr++ = WGL_TYPE_RGBA_FLOAT_ARB;
} }
if (_this->gl_data->HAS_WGL_ARB_framebuffer_sRGB && _this->gl_config.framebuffer_srgb_capable) { if (_this->gl_data->HAS_WGL_ARB_framebuffer_sRGB) {
const char *srgbhint = SDL_GetHint(SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE);
if (srgbhint && *srgbhint) {
if (SDL_strcmp(srgbhint, "skip") == 0) {
// don't set an attribute at all.
} else {
*iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
*iAttr++ = SDL_GetStringBoolean(srgbhint, false) ? GL_TRUE : GL_FALSE;
}
} else if (_this->gl_config.framebuffer_srgb_capable) { // default behavior without the hint.
*iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
*iAttr++ = GL_TRUE; *iAttr++ = GL_TRUE;
} }
}
/* We always choose either FULL or NO accel on Windows, because of flaky /* We always choose either FULL or NO accel on Windows, because of flaky
drivers. If the app didn't specify, we use FULL, because that's drivers. If the app didn't specify, we use FULL, because that's
+12 -1
View File
@@ -25,6 +25,7 @@
#include "SDL_x11video.h" #include "SDL_x11video.h"
#include "SDL_x11xsync.h" #include "SDL_x11xsync.h"
#include "../../SDL_hints_c.h"
// GLX implementation of SDL OpenGL support // GLX implementation of SDL OpenGL support
@@ -583,10 +584,20 @@ static int X11_GL_GetAttributes(SDL_VideoDevice *_this, Display *display, int sc
attribs[i++] = GLX_RGBA_FLOAT_TYPE_ARB; attribs[i++] = GLX_RGBA_FLOAT_TYPE_ARB;
} }
if (_this->gl_data->HAS_GLX_ARB_framebuffer_sRGB && _this->gl_config.framebuffer_srgb_capable) { if (_this->gl_data->HAS_GLX_ARB_framebuffer_sRGB) {
const char *srgbhint = SDL_GetHint(SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE);
if (srgbhint && *srgbhint) {
if (SDL_strcmp(srgbhint, "skip") == 0) {
// don't set an attribute at all.
} else {
attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
attribs[i++] = SDL_GetStringBoolean(srgbhint, false) ? True : False; // always needed, for_FBConfig or not!
}
} else if (_this->gl_config.framebuffer_srgb_capable) { // default behavior without the hint.
attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB; attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
attribs[i++] = True; // always needed, for_FBConfig or not! attribs[i++] = True; // always needed, for_FBConfig or not!
} }
}
if (_this->gl_config.accelerated >= 0 && if (_this->gl_config.accelerated >= 0 &&
_this->gl_data->HAS_GLX_EXT_visual_rating) { _this->gl_data->HAS_GLX_EXT_visual_rating) {