New gamma ramp API.

This commit is contained in:
Camilla Berglund 2013-05-19 15:46:44 +02:00
parent 6df692b61e
commit 5d308db654
8 changed files with 128 additions and 126 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,6 +39,7 @@
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{ {
HDC dc; HDC dc;
WORD values[768];
DISPLAY_DEVICE display; DISPLAY_DEVICE display;
ZeroMemory(&display, sizeof(DISPLAY_DEVICE)); ZeroMemory(&display, sizeof(DISPLAY_DEVICE));
@ -46,21 +47,39 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
EnumDisplayDevices(monitor->win32.name, 0, &display, 0); EnumDisplayDevices(monitor->win32.name, 0, &display, 0);
dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL); dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL);
GetDeviceGammaRamp(dc, (WORD*) ramp); GetDeviceGammaRamp(dc, values);
DeleteDC(dc); 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) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{ {
HDC dc; HDC dc;
WORD values[768];
DISPLAY_DEVICE display; 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)); ZeroMemory(&display, sizeof(DISPLAY_DEVICE));
display.cb = sizeof(DISPLAY_DEVICE); display.cb = sizeof(DISPLAY_DEVICE);
EnumDisplayDevices(monitor->win32.name, 0, &display, 0); EnumDisplayDevices(monitor->win32.name, 0, &display, 0);
dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL); dc = CreateDC(L"DISPLAY", display.DeviceString, NULL, NULL);
SetDeviceGammaRamp(dc, (WORD*) ramp); SetDeviceGammaRamp(dc, values);
DeleteDC(dc); DeleteDC(dc);
} }

View File

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