From 92a71e07d30fa3c9ba562ced606be4bddd693c79 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 12 Feb 2013 13:50:41 +0100 Subject: [PATCH] Made gamma ramp functions per-monitor. --- include/GL/glfw3.h | 19 ++++---- src/cocoa_gamma.c | 32 +++++++++--- src/cocoa_init.m | 8 --- src/gamma.c | 23 ++++++--- src/init.c | 9 ++++ src/internal.h | 17 ++++--- src/win32_gamma.c | 26 ++++++++-- src/win32_init.c | 8 --- src/x11_gamma.c | 118 ++++++++++++++++++--------------------------- src/x11_init.c | 2 - src/x11_platform.h | 1 - tests/gamma.c | 2 +- 12 files changed, 139 insertions(+), 126 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 7a70b335..0d6cbfc5 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -883,27 +883,28 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); */ GLFWAPI GLFWvidmode glfwGetVideoMode(GLFWmonitor* monitor); -/*! @brief Sets the system gamma ramp for all connected monitors to one - * generated from the specified exponent. +/*! @brief Generates a gamma ramp and sets it for the specified monitor. + * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * @ingroup gamma * - * @remarks This is a helper function layered on top of @ref glfwSetGammaRamp. + * @remarks This is a helper function on top of @ref glfwSetGammaRamp. */ -GLFWAPI void glfwSetGamma(float gamma); +GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); -/*! @brief Retrieves the current system gamma ramp. +/*! @brief Retrieves the current gamma ramp for the specified monitor. + * @param[in] monitor The monitor to query. * @param[out] ramp Where to store the gamma ramp. * @ingroup gamma */ -GLFWAPI void glfwGetGammaRamp(GLFWgammaramp* ramp); +GLFWAPI void glfwGetGammaRamp(GLFWmonitor* monitor, GLFWgammaramp* ramp); -/*! @brief Sets the system gamma ramp for all connected monitors to the one - * specified. +/*! @brief Sets the gamma ramp for the specified monitor. + * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * @ingroup gamma */ -GLFWAPI void glfwSetGammaRamp(const GLFWgammaramp* ramp); +GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); /*! @brief Resets all window hints to their default values * diff --git a/src/cocoa_gamma.c b/src/cocoa_gamma.c index dfcc15b6..6cad230e 100644 --- a/src/cocoa_gamma.c +++ b/src/cocoa_gamma.c @@ -39,19 +39,27 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) +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]; - // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE - if (_glfw.originalRampSize != 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; + } - CGGetDisplayTransferByTable(CGMainDisplayID(), GLFW_GAMMA_RAMP_SIZE, red, green, blue, + CGGetDisplayTransferByTable(monitor->ns.displayID, + GLFW_GAMMA_RAMP_SIZE, + red, green, blue, &sampleCount); for (i = 0; i < GLFW_GAMMA_RAMP_SIZE; i++) @@ -62,17 +70,23 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) } } -void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { + // TODO: Support ramp sizes other than 256 + 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]; - // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE - if (_glfw.originalRampSize != 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; + } // Convert to float & take the difference of the original gamma and // the linear function. @@ -83,6 +97,8 @@ void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) blue[i] = ramp->blue[i] / 65535.f; } - CGSetDisplayTransferByTable(CGMainDisplayID(), GLFW_GAMMA_RAMP_SIZE, red, green, blue); + CGSetDisplayTransferByTable(monitor->ns.displayID, + GLFW_GAMMA_RAMP_SIZE, + red, green, blue); } diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 35b7d3e4..a1a7d88a 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -93,10 +93,6 @@ int _glfwPlatformInit(void) changeToResourcesDirectory(); #endif - // Save the original gamma ramp - _glfw.originalRampSize = CGDisplayGammaTableCapacity(CGMainDisplayID()); - _glfwPlatformGetGammaRamp(&_glfw.originalRamp); - _glfwInitTimer(); _glfwInitJoysticks(); @@ -123,10 +119,6 @@ void _glfwPlatformTerminate(void) _glfw.ns.eventSource = NULL; } - // Restore the original gamma ramp - if (_glfw.rampChanged) - _glfwPlatformSetGammaRamp(&_glfw.originalRamp); - [NSApp setDelegate:nil]; [_glfw.ns.delegate release]; _glfw.ns.delegate = nil; diff --git a/src/gamma.c b/src/gamma.c index b3ca7daf..d70227f6 100644 --- a/src/gamma.c +++ b/src/gamma.c @@ -37,7 +37,7 @@ ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// -GLFWAPI void glfwSetGamma(float gamma) +GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma) { int i, size = GLFW_GAMMA_RAMP_SIZE; GLFWgammaramp ramp; @@ -75,29 +75,38 @@ GLFWAPI void glfwSetGamma(float gamma) ramp.blue[i] = (unsigned short) value; } - glfwSetGammaRamp(&ramp); + glfwSetGammaRamp(handle, &ramp); } -GLFWAPI void glfwGetGammaRamp(GLFWgammaramp* ramp) +GLFWAPI void glfwGetGammaRamp(GLFWmonitor* handle, GLFWgammaramp* ramp) { + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + if (!_glfwInitialized) { _glfwInputError(GLFW_NOT_INITIALIZED, NULL); return; } - _glfwPlatformGetGammaRamp(ramp); + _glfwPlatformGetGammaRamp(monitor, ramp); } -GLFWAPI void glfwSetGammaRamp(const GLFWgammaramp* ramp) +GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) { + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + if (!_glfwInitialized) { _glfwInputError(GLFW_NOT_INITIALIZED, NULL); return; } - _glfwPlatformSetGammaRamp(ramp); - _glfw.rampChanged = GL_TRUE; + if (!monitor->rampChanged) + { + _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp); + monitor->rampChanged = GL_TRUE; + } + + _glfwPlatformSetGammaRamp(monitor, ramp); } diff --git a/src/init.c b/src/init.c index 4595084a..3b5f43df 100644 --- a/src/init.c +++ b/src/init.c @@ -150,6 +150,8 @@ GLFWAPI int glfwInit(void) GLFWAPI void glfwTerminate(void) { + int i; + if (!_glfwInitialized) return; @@ -157,6 +159,13 @@ GLFWAPI void glfwTerminate(void) while (_glfw.windowListHead) glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead); + for (i = 0; i < _glfw.monitorCount; i++) + { + _GLFWmonitor* monitor = _glfw.monitors[i]; + if (monitor->rampChanged) + _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp); + } + _glfwDestroyMonitors(); _glfwPlatformTerminate(); diff --git a/src/internal.h b/src/internal.h index f51a0a03..1c91fe2c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -267,6 +267,9 @@ struct _GLFWmonitor GLFWvidmode* modes; int modeCount; + GLFWgammaramp originalRamp; + GLboolean rampChanged; + // This is defined in the window API's platform.h _GLFW_PLATFORM_MONITOR_STATE; }; @@ -285,10 +288,6 @@ struct _GLFWlibrary int monitorCount; GLFWmonitorfun monitorCallback; - GLFWgammaramp originalRamp; - int originalRampSize; - GLboolean rampChanged; - // This is defined in the window API's platform.h _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; // This is defined in the context API's platform.h @@ -376,17 +375,19 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); */ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode); -/*! @brief Returns the current system gamma ramp. +/*! @brief Retrieves the current gamma ramp for the specified monitor. + * @param[in] monitor The monitor to query. * @param[out] ramp The current system gamma ramp. * @ingroup platform */ -void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); +void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp); -/*! @brief Sets the system gamma ramp. +/*! @brief Sets the gamma ramp for the specified monitor. + * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The desired system gamma ramp. * @ingroup platform */ -void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); /*! @brief Sets the system clipboard to the specified string. * @param[in] window The window who will own the system clipboard contents, on diff --git a/src/win32_gamma.c b/src/win32_gamma.c index 8c0c50b0..7260a6d1 100644 --- a/src/win32_gamma.c +++ b/src/win32_gamma.c @@ -36,13 +36,31 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) +void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { - GetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); + HDC dc; + DISPLAY_DEVICE display; + + 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); + GetDeviceGammaRamp(dc, (WORD*) ramp); + DeleteDC(dc); } -void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { - SetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); + HDC dc; + DISPLAY_DEVICE display; + + 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); + DeleteDC(dc); } diff --git a/src/win32_init.c b/src/win32_init.c index dffc7c73..31fee9d5 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -168,10 +168,6 @@ int _glfwPlatformInit(void) _control87(MCW_EM, MCW_EM); #endif - // Save the original gamma ramp - _glfw.originalRampSize = 256; - _glfwPlatformGetGammaRamp(&_glfw.originalRamp); - if (!_glfwInitContextAPI()) return GL_FALSE; @@ -184,10 +180,6 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { - // Restore the original gamma ramp - if (_glfw.rampChanged) - _glfwPlatformSetGammaRamp(&_glfw.originalRamp); - if (_glfw.win32.classAtom) { UnregisterClass(_GLFW_WNDCLASSNAME, GetModuleHandle(NULL)); diff --git a/src/x11_gamma.c b/src/x11_gamma.c index db0fd734..ae5b1cd8 100644 --- a/src/x11_gamma.c +++ b/src/x11_gamma.c @@ -37,7 +37,7 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -// Detect gamma ramp support and save original gamma ramp, if available +// Detect gamma ramp support // void _glfwInitGammaRamp(void) { @@ -54,9 +54,7 @@ void _glfwInitGammaRamp(void) XRRScreenResources* rr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); - _glfw.originalRampSize = XRRGetCrtcGammaSize(_glfw.x11.display, - rr->crtcs[0]); - if (_glfw.originalRampSize == 0) + if (XRRGetCrtcGammaSize(_glfw.x11.display, rr->crtcs[0])) { // This is probably older Nvidia RandR with broken gamma support // Flag it as useless and try Xf86VidMode below, if available @@ -65,28 +63,6 @@ void _glfwInitGammaRamp(void) XRRFreeScreenResources(rr); } - - if (_glfw.x11.vidmode.available && !_glfw.originalRampSize) - { - // Get the gamma size using XF86VidMode - XF86VidModeGetGammaRampSize(_glfw.x11.display, - _glfw.x11.screen, - &_glfw.originalRampSize); - } - - if (_glfw.originalRampSize) - { - // Save the original gamma ramp - _glfwPlatformGetGammaRamp(&_glfw.originalRamp); - } -} - -// Restore original gamma ramp if necessary -// -void _glfwTerminateGammaRamp(void) -{ - if (_glfw.originalRampSize && _glfw.rampChanged) - _glfwPlatformSetGammaRamp(&_glfw.originalRamp); } @@ -94,83 +70,85 @@ void _glfwTerminateGammaRamp(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) +void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { - // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE - if (_glfw.originalRampSize != GLFW_GAMMA_RAMP_SIZE) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: Failed to get gamma ramp due to size " - "incompatibility"); - return; - } + // 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); - XRRScreenResources* rr = XRRGetScreenResources(_glfw.x11.display, - _glfw.x11.root); + 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 = XRRGetCrtcGamma(_glfw.x11.display, - rr->crtcs[0]); - - // TODO: Handle case of original ramp size having a size other than 256 + 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); XRRFreeGamma(gamma); - XRRFreeScreenResources(rr); } 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; + } + XF86VidModeGetGammaRamp(_glfw.x11.display, _glfw.x11.screen, GLFW_GAMMA_RAMP_SIZE, - ramp->red, - ramp->green, - ramp->blue); + ramp->red, ramp->green, ramp->blue); } } -void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { - // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE - if (_glfw.originalRampSize != GLFW_GAMMA_RAMP_SIZE) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: Failed to set gamma ramp due to size " - "incompatibility"); - return; - } - if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) { - int i; size_t size = GLFW_GAMMA_RAMP_SIZE * sizeof(unsigned short); + XRRCrtcGamma* gamma; - XRRScreenResources* rr = XRRGetScreenResources(_glfw.x11.display, - _glfw.x11.root); - - // Update gamma per monitor - for (i = 0; i < rr->ncrtc; i++) + if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != + GLFW_GAMMA_RAMP_SIZE) { - XRRCrtcGamma* gamma = XRRAllocGamma(GLFW_GAMMA_RAMP_SIZE); - - memcpy(gamma->red, ramp->red, size); - memcpy(gamma->green, ramp->green, size); - memcpy(gamma->blue, ramp->blue, size); - - XRRSetCrtcGamma(_glfw.x11.display, rr->crtcs[i], gamma); - XRRFreeGamma(gamma); + _glfwInputError(GLFW_PLATFORM_ERROR, + "X11: Only gamma ramps of size 256 supported"); + return; } - XRRFreeScreenResources(rr); + gamma = XRRAllocGamma(GLFW_GAMMA_RAMP_SIZE); + + memcpy(gamma->red, ramp->red, size); + memcpy(gamma->green, ramp->green, size); + memcpy(gamma->blue, ramp->blue, size); + + XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, 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, diff --git a/src/x11_init.c b/src/x11_init.c index acbee3db..763a1363 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -603,8 +603,6 @@ void _glfwPlatformTerminate(void) _glfw.x11.cursor = (Cursor) 0; } - _glfwTerminateGammaRamp(); - _glfwTerminateJoysticks(); _glfwTerminateContextAPI(); diff --git a/src/x11_platform.h b/src/x11_platform.h index a50f3fed..e7c78011 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -210,7 +210,6 @@ void _glfwInitTimer(void); // Gamma void _glfwInitGammaRamp(void); -void _glfwTerminateGammaRamp(void); // OpenGL support int _glfwInitContextAPI(void); diff --git a/tests/gamma.c b/tests/gamma.c index 8c971eae..7fb45add 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -49,7 +49,7 @@ static void set_gamma(float value) { gamma_value = value; printf("Gamma: %f\n", gamma_value); - glfwSetGamma(gamma_value); + glfwSetGamma(glfwGetPrimaryMonitor(), gamma_value); } static void error_callback(int error, const char* description)