Selaa lähdekoodia

New gamma ramp API.

Camilla Berglund 12 vuotta sitten
vanhempi
commit
5d308db654
8 muutettua tiedostoa jossa 128 lisäystä ja 126 poistoa
  1. 9 14
      include/GL/glfw3.h
  2. 27 45
      src/cocoa_gamma.c
  3. 42 13
      src/gamma.c
  4. 1 1
      src/init.c
  5. 9 1
      src/internal.h
  6. 3 0
      src/monitor.c
  7. 21 2
      src/win32_gamma.c
  8. 16 50
      src/x11_gamma.c

+ 9 - 14
include/GL/glfw3.h

@@ -545,8 +545,6 @@ extern "C" {
 #define GLFW_CURSOR_HIDDEN          0x00040002
 #define GLFW_CURSOR_DISABLED        0x00040003
 
-#define GLFW_GAMMA_RAMP_SIZE        256
-
 #define GLFW_CONNECTED              0x00061000
 #define GLFW_DISCONNECTED           0x00061001
 
@@ -800,9 +798,10 @@ typedef struct
  */
 typedef struct
 {
-    unsigned short red[GLFW_GAMMA_RAMP_SIZE];
-    unsigned short green[GLFW_GAMMA_RAMP_SIZE];
-    unsigned short blue[GLFW_GAMMA_RAMP_SIZE];
+    unsigned short* red;
+    unsigned short* green;
+    unsigned short* blue;
+    unsigned int size;
 } GLFWgammaramp;
 
 
@@ -1072,8 +1071,8 @@ GLFWAPI GLFWvidmode glfwGetVideoMode(GLFWmonitor* monitor);
 
 /*! @brief Generates a gamma ramp and sets it for the specified monitor.
  *
- *  This function generates a gamma ramp from the specified exponent and then
- *  calls @ref glfwSetGamma with it.
+ *  This function generates a 256-element gamma ramp from the specified exponent
+ *  and then calls @ref glfwSetGamma with it.
  *
  *  @param[in] monitor The monitor whose gamma ramp to set.
  *  @param[in] gamma The desired exponent.
@@ -1087,14 +1086,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
  *  This function retrieves the current gamma ramp of the specified monitor.
  *
  *  @param[in] monitor The monitor to query.
- *  @param[out] ramp Where to store the gamma ramp.
- *
- *  @bug This function does not yet support monitors whose original gamma ramp
- *  has more or less than 256 entries.
+ *  @return The current gamma ramp.
  *
  *  @ingroup gamma
  */
-GLFWAPI void glfwGetGammaRamp(GLFWmonitor* monitor, GLFWgammaramp* ramp);
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
 
 /*! @brief Sets the current gamma ramp for the specified monitor.
  *
@@ -1103,8 +1099,7 @@ GLFWAPI void glfwGetGammaRamp(GLFWmonitor* monitor, GLFWgammaramp* ramp);
  *  @param[in] monitor The monitor whose gamma ramp to set.
  *  @param[in] ramp The gamma ramp to use.
  *
- *  @bug This function does not yet support monitors whose original gamma ramp
- *  has more or less than 256 entries.
+ *  @note Gamma ramp sizes other than 256 are not supported by all hardware.
  *
  *  @ingroup gamma
  */

+ 27 - 45
src/cocoa_gamma.c

@@ -30,6 +30,7 @@
 #include "internal.h"
 
 #include <limits.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <ApplicationServices/ApplicationServices.h>
@@ -41,64 +42,45 @@
 
 void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
 {
-    // TODO: Support ramp sizes other than 256
-
-    uint32_t sampleCount;
-    int i;
-    CGGammaValue red[GLFW_GAMMA_RAMP_SIZE];
-    CGGammaValue green[GLFW_GAMMA_RAMP_SIZE];
-    CGGammaValue blue[GLFW_GAMMA_RAMP_SIZE];
-
-    if (CGDisplayGammaTableCapacity(monitor->ns.displayID) !=
-        GLFW_GAMMA_RAMP_SIZE)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Only gamma ramps of size 256 supported");
-        return;
-    }
+    uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
+    CGGammaValue* values = (CGGammaValue*) malloc(size * 3 * sizeof(CGGammaValue));
 
     CGGetDisplayTransferByTable(monitor->ns.displayID,
-                                GLFW_GAMMA_RAMP_SIZE,
-                                red, green, blue,
-                                &sampleCount);
+                                size,
+                                values,
+                                values + size,
+                                values + size * 2,
+                                &size);
+
+    _glfwAllocGammaRamp(ramp, size);
 
-    for (i = 0; i < GLFW_GAMMA_RAMP_SIZE; i++)
+    for (int i = 0; i < size; i++)
     {
-        ramp->red[i] = red[i] * 65535;
-        ramp->green[i] = green[i] * 65535;
-        ramp->blue[i] = blue[i] * 65535;
+        ramp->red[i]   = (unsigned short) (values[i] * 65535);
+        ramp->green[i] = (unsigned short) (values[i + size] * 65535);
+        ramp->blue[i]  = (unsigned short) (values[i + size * 2] * 65535);
     }
+
+    free(values);
 }
 
 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
 {
-    // TODO: Support ramp sizes other than 256
+    CGGammaValue* values = (CGGammaValue*) malloc(ramp->size * 3 * sizeof(CGGammaValue));
 
-    int i;
-    int size = GLFW_GAMMA_RAMP_SIZE;
-    CGGammaValue red[GLFW_GAMMA_RAMP_SIZE];
-    CGGammaValue green[GLFW_GAMMA_RAMP_SIZE];
-    CGGammaValue blue[GLFW_GAMMA_RAMP_SIZE];
-
-    if (CGDisplayGammaTableCapacity(monitor->ns.displayID) !=
-        GLFW_GAMMA_RAMP_SIZE)
+    for (int i = 0;  i < ramp->size;  i++)
     {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Only gamma ramps of size 256 supported");
-        return;
-    }
-
-    // Convert to float & take the difference of the original gamma and
-    // the linear function.
-    for (i = 0; i < size; i++)
-    {
-        red[i] = ramp->red[i] / 65535.f;
-        green[i] = ramp->green[i] / 65535.f;
-        blue[i] = ramp->blue[i] / 65535.f;
+        values[i]                  = ramp->red[i] / 65535.f;
+        values[i + ramp->size]     = ramp->green[i] / 65535.f;
+        values[i + ramp->size * 2] = ramp->blue[i] / 65535.f;
     }
 
     CGSetDisplayTransferByTable(monitor->ns.displayID,
-                                GLFW_GAMMA_RAMP_SIZE,
-                                red, green, blue);
+                                ramp->size,
+                                values,
+                                values + ramp->size,
+                                values + ramp->size * 2);
+
+    free(values);
 }
 

+ 42 - 13
src/gamma.c

@@ -30,8 +30,31 @@
 #include "internal.h"
 
 #include <math.h>
+#include <stdlib.h>
 #include <string.h>
 
+#if defined(_MSC_VER)
+ #include <malloc.h>
+#endif
+
+
+void _glfwAllocGammaRamp(GLFWgammaramp* ramp, unsigned int size)
+{
+    ramp->red = (unsigned short*) malloc(size * sizeof(unsigned short));
+    ramp->green = (unsigned short*) malloc(size * sizeof(unsigned short));
+    ramp->blue = (unsigned short*) malloc(size * sizeof(unsigned short));
+    ramp->size = size;
+}
+
+void _glfwFreeGammaRamp(GLFWgammaramp* ramp)
+{
+    free(ramp->red);
+    free(ramp->green);
+    free(ramp->blue);
+
+    memset(ramp, 0, sizeof(GLFWgammaramp));
+}
+
 
 //////////////////////////////////////////////////////////////////////////
 //////                        GLFW public API                       //////
@@ -39,7 +62,8 @@
 
 GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
 {
-    int i, size = GLFW_GAMMA_RAMP_SIZE;
+    int i;
+    unsigned short values[256];
     GLFWgammaramp ramp;
 
     _GLFW_REQUIRE_INIT();
@@ -51,12 +75,12 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
         return;
     }
 
-    for (i = 0;  i < size;  i++)
+    for (i = 0;  i < 256;  i++)
     {
         float value;
 
         // Calculate intensity
-        value = (float) i / (float) (size - 1);
+        value = i / 255.f;
         // Apply gamma curve
         value = (float) pow(value, 1.f / gamma) * 65535.f + 0.5f;
 
@@ -66,19 +90,27 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
         else if (value > 65535.f)
             value = 65535.f;
 
-        ramp.red[i]   = (unsigned short) value;
-        ramp.green[i] = (unsigned short) value;
-        ramp.blue[i]  = (unsigned short) value;
+        values[i] = (unsigned short) value;
     }
 
+    ramp.red = values;
+    ramp.green = values;
+    ramp.blue = values;
+    ramp.size = 256;
+
     glfwSetGammaRamp(handle, &ramp);
 }
 
-GLFWAPI void glfwGetGammaRamp(GLFWmonitor* handle, GLFWgammaramp* ramp)
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
 {
     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetGammaRamp(monitor, ramp);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    _glfwFreeGammaRamp(&monitor->currentRamp);
+    _glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
+
+    return &monitor->currentRamp;
 }
 
 GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
@@ -87,11 +119,8 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
 
     _GLFW_REQUIRE_INIT();
 
-    if (!monitor->rampChanged)
-    {
+    if (!monitor->originalRamp.size)
         _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
-        monitor->rampChanged = GL_TRUE;
-    }
 
     _glfwPlatformSetGammaRamp(monitor, ramp);
 }

+ 1 - 1
src/init.c

@@ -160,7 +160,7 @@ GLFWAPI void glfwTerminate(void)
     for (i = 0;  i < _glfw.monitorCount;  i++)
     {
         _GLFWmonitor* monitor = _glfw.monitors[i];
-        if (monitor->rampChanged)
+        if (monitor->originalRamp.size)
             _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
     }
 

+ 9 - 1
src/internal.h

@@ -250,7 +250,7 @@ struct _GLFWmonitor
     int             modeCount;
 
     GLFWgammaramp   originalRamp;
-    GLboolean       rampChanged;
+    GLFWgammaramp   currentRamp;
 
     // This is defined in the window API's platform.h
     _GLFW_PLATFORM_MONITOR_STATE;
@@ -716,6 +716,14 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig);
  */
 GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig);
 
+/*! @ingroup utility
+ */
+void _glfwAllocGammaRamp(GLFWgammaramp* ramp, unsigned int size);
+
+/*! @ingroup utility
+ */
+void _glfwFreeGammaRamp(GLFWgammaramp* ramp);
+
 /*! @ingroup utility
  */
 _GLFWmonitor* _glfwCreateMonitor(const char* name, int widthMM, int heightMM);

+ 3 - 0
src/monitor.c

@@ -172,6 +172,9 @@ void _glfwDestroyMonitor(_GLFWmonitor* monitor)
     if (monitor == NULL)
         return;
 
+    _glfwFreeGammaRamp(&monitor->originalRamp);
+    _glfwFreeGammaRamp(&monitor->currentRamp);
+
     free(monitor->modes);
     free(monitor->name);
     free(monitor);

+ 21 - 2
src/win32_gamma.c

@@ -39,6 +39,7 @@
 void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
 {
     HDC dc;
+    WORD values[768];
     DISPLAY_DEVICE display;
 
     ZeroMemory(&display, sizeof(DISPLAY_DEVICE));
@@ -46,21 +47,39 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
     EnumDisplayDevices(monitor->win32.name, 0, &display, 0);
 
     dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL);
-    GetDeviceGammaRamp(dc, (WORD*) ramp);
+    GetDeviceGammaRamp(dc, values);
     DeleteDC(dc);
+
+    memcpy(ramp->red,   values +   0, 256 * sizeof(unsigned short));
+    memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
+    memcpy(ramp->blue,  values + 512, 256 * sizeof(unsigned short));
+
+    ramp->size = 256;
 }
 
 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
 {
     HDC dc;
+    WORD values[768];
     DISPLAY_DEVICE display;
 
+    if (ramp->size != 256)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: Gamma ramp size must be 256");
+        return;
+    }
+
+    memcpy(values +   0, ramp->red,   256 * sizeof(unsigned short));
+    memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
+    memcpy(values + 512, ramp->blue,  256 * sizeof(unsigned short));
+
     ZeroMemory(&display, sizeof(DISPLAY_DEVICE));
     display.cb = sizeof(DISPLAY_DEVICE);
     EnumDisplayDevices(monitor->win32.name, 0, &display, 0);
 
     dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL);
-    SetDeviceGammaRamp(dc, (WORD*) ramp);
+    SetDeviceGammaRamp(dc, values);
     DeleteDC(dc);
 }
 

+ 16 - 50
src/x11_gamma.c

@@ -72,26 +72,18 @@ void _glfwInitGammaRamp(void)
 
 void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
 {
-    // TODO: Support ramp sizes other than 256
-
     if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
     {
-        XRRCrtcGamma* gamma;
-        size_t size = GLFW_GAMMA_RAMP_SIZE * sizeof(unsigned short);
+        const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
+                                                monitor->x11.crtc);
+        XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
+                                              monitor->x11.crtc);
 
-        if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) !=
-            GLFW_GAMMA_RAMP_SIZE)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "X11: Only gamma ramps of size 256 supported");
-            return;
-        }
+        _glfwAllocGammaRamp(ramp, size);
 
-        gamma = XRRGetCrtcGamma(_glfw.x11.display, monitor->x11.crtc);
-
-        memcpy(ramp->red, gamma->red, size);
-        memcpy(ramp->green, gamma->green, size);
-        memcpy(ramp->blue, gamma->blue, size);
+        memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
+        memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
+        memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
 
         XRRFreeGamma(gamma);
     }
@@ -100,17 +92,11 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
         int size;
         XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
 
-        if (size != GLFW_GAMMA_RAMP_SIZE)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "X11: Only gamma ramps of size 256 supported");
-            return;
-        }
+        _glfwAllocGammaRamp(ramp, size);
 
         XF86VidModeGetGammaRamp(_glfw.x11.display,
                                 _glfw.x11.screen,
-                                GLFW_GAMMA_RAMP_SIZE,
-                                ramp->red, ramp->green, ramp->blue);
+                                ramp->size, ramp->red, ramp->green, ramp->blue);
     }
 }
 
@@ -118,40 +104,20 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
 {
     if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
     {
-        size_t size = GLFW_GAMMA_RAMP_SIZE * sizeof(unsigned short);
-        XRRCrtcGamma* gamma;
-
-        if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) !=
-            GLFW_GAMMA_RAMP_SIZE)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "X11: Only gamma ramps of size 256 supported");
-            return;
-        }
+        XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
 
-        gamma = XRRAllocGamma(GLFW_GAMMA_RAMP_SIZE);
-
-        memcpy(gamma->red, ramp->red, size);
-        memcpy(gamma->green, ramp->green, size);
-        memcpy(gamma->blue, ramp->blue, size);
+        memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
+        memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
+        memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
 
         XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
+        XRRFreeGamma(gamma);
     }
     else if (_glfw.x11.vidmode.available)
     {
-        int size;
-        XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
-
-        if (size != GLFW_GAMMA_RAMP_SIZE)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "X11: Only gamma ramps of size 256 supported");
-            return;
-        }
-
         XF86VidModeSetGammaRamp(_glfw.x11.display,
                                 _glfw.x11.screen,
-                                GLFW_GAMMA_RAMP_SIZE,
+                                ramp->size,
                                 (unsigned short*) ramp->red,
                                 (unsigned short*) ramp->green,
                                 (unsigned short*) ramp->blue);