From 731812cfc14a8155ec07c1c409796f9dafa77300 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 30 May 2013 15:52:42 +0200 Subject: [PATCH] Added refresh rate to GLFWvidmode. --- include/GLFW/glfw3.h | 3 ++ src/cocoa_monitor.m | 14 +++++--- src/monitor.c | 14 ++++++-- src/win32_monitor.c | 14 +++++--- src/x11_monitor.c | 83 +++++++++++++++++++++++--------------------- tests/modes.c | 5 +-- 6 files changed, 80 insertions(+), 53 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index b6bea9a3..a455e3fc 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -802,6 +802,9 @@ typedef struct /*! The bit depth of the blue channel of the video mode. */ int blueBits; + /*! The refresh rate, in Hz, of the video mode. + */ + int refreshRate; } GLFWvidmode; /*! @brief Gamma ramp. diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 4e8816e7..8968c1ba 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -102,6 +102,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode) GLFWvidmode result; result.width = CGDisplayModeGetWidth(mode); result.height = CGDisplayModeGetHeight(mode); + result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); @@ -157,7 +158,7 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) CGDisplayModeRef bestMode = NULL; CFArrayRef modes; CFIndex count, i; - unsigned int leastSizeDiff = UINT_MAX; + unsigned int leastSizeDiff = UINT_MAX, leastRateDiff = UINT_MAX; const int bpp = desired->redBits - desired->greenBits - desired->blueBits; modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); @@ -183,17 +184,22 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) CFRelease(format); } - int modeWidth = (int) CGDisplayModeGetWidth(mode); - int modeHeight = (int) CGDisplayModeGetHeight(mode); + const int modeWidth = (int) CGDisplayModeGetWidth(mode); + const int modeHeight = (int) CGDisplayModeGetHeight(mode); + const int modeRate = (int) CGDisplayModeGetRefreshRate(mode); unsigned int sizeDiff = (abs(modeBPP - bpp) << 25) | ((modeWidth - desired->width) * (modeWidth - desired->width) + (modeHeight - desired->height) * (modeHeight - desired->height)); - if (sizeDiff < leastSizeDiff) + const unsigned int rateDiff = modeRate - desired->refreshRate; + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && rateDiff < leastRateDiff)) { bestMode = mode; leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; } } diff --git a/src/monitor.c b/src/monitor.c index a4d59864..00456f38 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -65,7 +65,12 @@ static int compareVideoModes(const void* firstPtr, const void* secondPtr) firstSize = first->width * first->height; secondSize = second->width * second->height; - return firstSize - secondSize; + if (firstSize != secondSize) + return firstSize - secondSize; + + // Lastly sort on refresh rate + + return first->refreshRate - second->refreshRate; } // Retrieves the available modes for the specified monitor @@ -205,6 +210,7 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, { int i; unsigned int sizeDiff, leastSizeDiff = UINT_MAX; + unsigned int rateDiff, leastRateDiff = UINT_MAX; unsigned int colorDiff, leastColorDiff = UINT_MAX; const GLFWvidmode* current; const GLFWvidmode* closest = NULL; @@ -224,11 +230,15 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, (current->height - desired->height) * (current->height - desired->height)); + rateDiff = abs(current->refreshRate - desired->refreshRate); + if ((colorDiff < leastColorDiff) || - (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff)) + (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) || + (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff)) { closest = current; leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; leastColorDiff = colorDiff; } } diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 57d905ec..af5485af 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -63,10 +63,12 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) return GL_TRUE; dm.dmSize = sizeof(DEVMODE); - dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; - dm.dmPelsWidth = best->width; - dm.dmPelsHeight = best->height; - dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | + DM_DISPLAYFREQUENCY; + dm.dmPelsWidth = best->width; + dm.dmPelsHeight = best->height; + dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; + dm.dmDisplayFrequency = best->refreshRate; if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; @@ -223,8 +225,9 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) continue; } - mode.width = dm.dmPelsWidth; + mode.width = dm.dmPelsWidth; mode.height = dm.dmPelsHeight; + mode.refreshRate = dm.dmDisplayFrequency; _glfwSplitBPP(dm.dmBitsPerPel, &mode.redBits, &mode.greenBits, @@ -270,6 +273,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) mode->width = dm.dmPelsWidth; mode->height = dm.dmPelsHeight; + mode->refreshRate = dm.dmDisplayFrequency; _glfwSplitBPP(dm.dmBitsPerPel, &mode->redBits, &mode->greenBits, diff --git a/src/x11_monitor.c b/src/x11_monitor.c index c3122f48..bc49622a 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -35,6 +35,28 @@ #include +static int calculateRefreshRate(const XRRModeInfo* mi) +{ + if (!mi->hTotal || !mi->vTotal) + return 0; + + return (int) ((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal)); +} + +static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id) +{ + int i; + + for (i = 0; i < sr->nmode; i++) + { + if (sr->modes[i].id == id) + return sr->modes + i; + } + + return NULL; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -45,52 +67,35 @@ void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) { if (_glfw.x11.randr.available) { - int i, j, k; + int i; XRRScreenResources* sr; XRRCrtcInfo* ci; RRMode bestMode = 0; - unsigned int leastSizeDiff = UINT_MAX; + unsigned int leastSizeDiff = UINT_MAX, leastRateDiff = UINT_MAX; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); for (i = 0; i < sr->nmode; i++) { - GLboolean usable = GL_TRUE; XRRModeInfo* mi = sr->modes + i; - for (j = 0; j < ci->noutput; j++) - { - XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, - sr, ci->outputs[j]); - - for (k = 0; k < oi->nmode; k++) - { - if (oi->modes[k] == mi->id) - break; - } - - if (k == oi->nmode) - usable = GL_FALSE; - - XRRFreeOutputInfo(oi); - } - - if (!usable) - continue; - if (mi->modeFlags & RR_Interlace) continue; - unsigned int sizeDiff = (mi->width - desired->width) * - (mi->width - desired->width) + - (mi->height - desired->height) * - (mi->height - desired->height); + const unsigned int sizeDiff = (mi->width - desired->width) * + (mi->width - desired->width) + + (mi->height - desired->height) * + (mi->height - desired->height); - if (sizeDiff < leastSizeDiff) + const unsigned int rateDiff = abs(calculateRefreshRate(mi) - desired->refreshRate); + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && rateDiff < leastRateDiff)) { bestMode = mi->id; leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; } } @@ -282,23 +287,17 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) for (i = 0; i < oi->nmode; i++) { GLFWvidmode mode; + const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); - for (j = 0; j < sr->nmode; j++) - { - if (sr->modes[j].id == oi->modes[i]) - break; - } - - if (j == sr->nmode) - continue; - - mode.width = sr->modes[j].width; - mode.height = sr->modes[j].height; + mode.width = mi->width; + mode.height = mi->height; + mode.refreshRate = calculateRefreshRate(mi); for (j = 0; j < *found; j++) { if (result[j].width == mode.width && - result[j].height == mode.height) + result[j].height == mode.height && + result[j].refreshRate == mode.refreshRate) { break; } @@ -332,6 +331,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) result[0].redBits = r; result[0].greenBits = g; result[0].blueBits = b; + result[0].refreshRate = 0; } return result; @@ -350,6 +350,8 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) mode->width = ci->width; mode->height = ci->height; + mode->refreshRate = calculateRefreshRate(getModeInfo(sr, ci->mode)); + XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } @@ -357,6 +359,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) { mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); + mode->refreshRate = 0; } _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen), diff --git a/tests/modes.c b/tests/modes.c index 5071a62d..4f0b9a8e 100644 --- a/tests/modes.c +++ b/tests/modes.c @@ -52,10 +52,11 @@ static const char* format_mode(const GLFWvidmode* mode) static char buffer[512]; sprintf(buffer, - "%i x %i x %i (%i %i %i)", + "%i x %i x %i (%i %i %i) %i Hz", mode->width, mode->height, mode->redBits + mode->greenBits + mode->blueBits, - mode->redBits, mode->greenBits, mode->blueBits); + mode->redBits, mode->greenBits, mode->blueBits, + mode->refreshRate); buffer[sizeof(buffer) - 1] = '\0'; return buffer;