فهرست منبع

opengl: added SDL_HINT_OPENGL_FORCE_SRGB_CAPABLE.

Reference Issue #14898.
Ryan C. Gordon 4 هفته پیش
والد
کامیت
632c83b722
5فایلهای تغییر یافته به همراه84 افزوده شده و 14 حذف شده
  1. 36 0
      include/SDL3/SDL_hints.h
  2. 12 7
      src/video/SDL_egl.c
  3. 8 1
      src/video/uikit/SDL_uikitopengles.m
  4. 14 3
      src/video/windows/SDL_windowsopengl.c
  5. 14 3
      src/video/x11/SDL_x11opengl.c

+ 36 - 0
include/SDL3/SDL_hints.h

@@ -3040,6 +3040,42 @@ extern "C" {
  */
 #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
  *

+ 12 - 7
src/video/SDL_egl.c

@@ -38,6 +38,7 @@
 
 #include "SDL_sysvideo.h"
 #include "SDL_egl_c.h"
+#include "../SDL_hints_c.h"
 
 #ifdef EGL_KHR_create_context
 // 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);
 #endif
 
-    if (_this->gl_config.framebuffer_srgb_capable >= 0) {
 #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++] = _this->gl_config.framebuffer_srgb_capable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR;
-        } else
-#endif
-        if (_this->gl_config.framebuffer_srgb_capable > 0) {
-            SDL_SetError("EGL implementation does not support sRGB system framebuffers");
-            return EGL_NO_SURFACE;
         }
     }
+#endif
 
     int opaque_ext_idx = -1;
 

+ 8 - 1
src/video/uikit/SDL_uikitopengles.m

@@ -31,6 +31,7 @@
 #include "../../events/SDL_keyboard_c.h"
 #include "../../events/SDL_mouse_c.h"
 #include "../../power/uikit/SDL_syspower.h"
+#include "../../SDL_hints_c.h"
 #include <dlfcn.h>
 
 @interface SDLEAGLContext : EAGLContext
@@ -153,6 +154,12 @@ SDL_GLContext UIKit_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
             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
         view = [[SDL_uikitopenglview alloc] initWithFrame:frame
                                                     scale:scale
@@ -163,7 +170,7 @@ SDL_GLContext UIKit_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
                                                     aBits:_this->gl_config.alpha_size
                                                 depthBits:_this->gl_config.depth_size
                                               stencilBits:_this->gl_config.stencil_size
-                                                     sRGB:_this->gl_config.framebuffer_srgb_capable
+                                                     sRGB:srgb
                                              multisamples:samples
                                                   context:context];
 

+ 14 - 3
src/video/windows/SDL_windowsopengl.c

@@ -24,6 +24,7 @@
 
 #include "SDL_windowsvideo.h"
 #include "SDL_windowsopengles.h"
+#include "../../SDL_hints_c.h"
 
 // WGL implementation of SDL OpenGL support
 
@@ -659,9 +660,19 @@ static bool WIN_GL_SetupWindowInternal(SDL_VideoDevice *_this, SDL_Window *windo
         *iAttr++ = WGL_TYPE_RGBA_FLOAT_ARB;
     }
 
-    if (_this->gl_data->HAS_WGL_ARB_framebuffer_sRGB && _this->gl_config.framebuffer_srgb_capable) {
-        *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
-        *iAttr++ = GL_TRUE;
+    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++ = GL_TRUE;
+        }
     }
 
     /* We always choose either FULL or NO accel on Windows, because of flaky

+ 14 - 3
src/video/x11/SDL_x11opengl.c

@@ -25,6 +25,7 @@
 
 #include "SDL_x11video.h"
 #include "SDL_x11xsync.h"
+#include "../../SDL_hints_c.h"
 
 // GLX implementation of SDL OpenGL support
 
@@ -583,9 +584,19 @@ static int X11_GL_GetAttributes(SDL_VideoDevice *_this, Display *display, int sc
         attribs[i++] = GLX_RGBA_FLOAT_TYPE_ARB;
     }
 
-    if (_this->gl_data->HAS_GLX_ARB_framebuffer_sRGB && _this->gl_config.framebuffer_srgb_capable) {
-        attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
-        attribs[i++] = True; // always needed, for_FBConfig or not!
+    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++] = True; // always needed, for_FBConfig or not!
+        }
     }
 
     if (_this->gl_config.accelerated >= 0 &&