From 5d308db654701f04336f66f5e7092671a4e018d7 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 19 May 2013 15:46:44 +0200 Subject: [PATCH] New gamma ramp API. --- include/GL/glfw3.h | 23 ++++++--------- src/cocoa_gamma.c | 72 +++++++++++++++++----------------------------- src/gamma.c | 55 ++++++++++++++++++++++++++--------- src/init.c | 2 +- src/internal.h | 10 ++++++- src/monitor.c | 3 ++ src/win32_gamma.c | 23 +++++++++++++-- src/x11_gamma.c | 66 +++++++++++------------------------------- 8 files changed, 128 insertions(+), 126 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index f341fe99..1f0fd344 100644 --- a/include/GL/glfw3.h +++ b/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 */ diff --git a/src/cocoa_gamma.c b/src/cocoa_gamma.c index 6cad230e..d8d01e81 100644 --- a/src/cocoa_gamma.c +++ b/src/cocoa_gamma.c @@ -30,6 +30,7 @@ #include "internal.h" #include +#include #include #include @@ -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); - for (i = 0; i < GLFW_GAMMA_RAMP_SIZE; i++) + _glfwAllocGammaRamp(ramp, size); + + 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); } diff --git a/src/gamma.c b/src/gamma.c index 39a11821..ed86e346 100644 --- a/src/gamma.c +++ b/src/gamma.c @@ -30,8 +30,31 @@ #include "internal.h" #include +#include #include +#if defined(_MSC_VER) + #include +#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); } diff --git a/src/init.c b/src/init.c index 96dc9d8c..97d605ca 100644 --- a/src/init.c +++ b/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); } diff --git a/src/internal.h b/src/internal.h index 6cb6cf18..8554a6a3 100644 --- a/src/internal.h +++ b/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); diff --git a/src/monitor.c b/src/monitor.c index ce5f7a24..9bdcc186 100644 --- a/src/monitor.c +++ b/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); diff --git a/src/win32_gamma.c b/src/win32_gamma.c index 7260a6d1..3ece6da0 100644 --- a/src/win32_gamma.c +++ b/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); } diff --git a/src/x11_gamma.c b/src/x11_gamma.c index 3de1062c..aad0888d 100644 --- a/src/x11_gamma.c +++ b/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; + XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size); - 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; - } - - 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);