diff --git a/README.md b/README.md index 39976fae..58f6d3ad 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,7 @@ GLFW. * Added `GLFW_VISIBLE` window hint and parameter for controlling and polling window visibility * Added `GLFW_REPEAT` key action for repeated keys + * Added `refreshRate` member to `GLFWvidmode` struct * Added key modifier parameter to key and mouse button callbacks * Added `windows` simple multi-window test program * Added `sharing` simple OpenGL object sharing test program diff --git a/docs/window.dox b/docs/window.dox index 029e6b10..77a8b6d6 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -86,6 +86,10 @@ multisampling. Zero disables multisampling. The `GLFW_SRGB_CAPABLE` hint specifies whether the framebuffer should be sRGB capable. +The `GLFW_REFRESH_RATE` hint specifies the desired refresh rate for full screen +windows. If set to zero, the highest available refresh rate will be used. This +hint is ignored for windowed mode windows. + @subsection window_hints_ctx Context related hints @@ -151,6 +155,7 @@ a robustness strategy. | `GLFW_ACCUM_ALPHA_BITS` | 0 | 0 to `INT_MAX` | | `GLFW_AUX_BUFFERS` | 0 | 0 to `INT_MAX` | | `GLFW_SAMPLES` | 0 | 0 to `INT_MAX` | +| `GLFW_REFRESH_RATE` | 0 | 0 to `INT_MAX` | | `GLFW_STEREO` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` | | `GLFW_SRGB_CAPABLE` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` | | `GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API` or `GLFW_OPENGL_ES_API` | diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 09a6ba5f..27e9cce3 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -520,6 +520,7 @@ extern "C" { #define GLFW_STEREO 0x0002100C #define GLFW_SAMPLES 0x0002100D #define GLFW_SRGB_CAPABLE 0x0002100E +#define GLFW_REFRESH_RATE 0x0002100F #define GLFW_CLIENT_API 0x00022001 #define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 8968c1ba..24154dd7 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -158,7 +158,8 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) CGDisplayModeRef bestMode = NULL; CFArrayRef modes; CFIndex count, i; - unsigned int leastSizeDiff = UINT_MAX, leastRateDiff = UINT_MAX; + unsigned int sizeDiff, leastSizeDiff = UINT_MAX; + unsigned int rateDiff, leastRateDiff = UINT_MAX; const int bpp = desired->redBits - desired->greenBits - desired->blueBits; modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); @@ -188,11 +189,14 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) 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)); + sizeDiff = (abs(modeBPP - bpp) << 25) | + ((modeWidth - desired->width) * (modeWidth - desired->width) + + (modeHeight - desired->height) * (modeHeight - desired->height)); - const unsigned int rateDiff = modeRate - desired->refreshRate; + if (desired->refreshRate) + rateDiff = abs(modeRate - desired->refreshRate); + else + rateDiff = UINT_MAX - modeRate; if ((sizeDiff < leastSizeDiff) || (sizeDiff == leastSizeDiff && rateDiff < leastRateDiff)) diff --git a/src/internal.h b/src/internal.h index 0b910676..4b0ee976 100644 --- a/src/internal.h +++ b/src/internal.h @@ -280,6 +280,7 @@ struct _GLFWlibrary GLboolean decorated; int samples; GLboolean sRGB; + int refreshRate; int clientAPI; int glMajor; int glMinor; diff --git a/src/monitor.c b/src/monitor.c index 00456f38..bacc6a70 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -230,7 +230,10 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, (current->height - desired->height) * (current->height - desired->height)); - rateDiff = abs(current->refreshRate - desired->refreshRate); + if (desired->refreshRate) + rateDiff = abs(current->refreshRate - desired->refreshRate); + else + rateDiff = UINT_MAX - current->refreshRate; if ((colorDiff < leastColorDiff) || (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) || diff --git a/src/window.c b/src/window.c index 0a2d0af9..e9b3fd16 100644 --- a/src/window.c +++ b/src/window.c @@ -201,11 +201,13 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, wndconfig.resizable = GL_TRUE; wndconfig.visible = GL_TRUE; - window->videoMode.width = width; - window->videoMode.height = height; - window->videoMode.redBits = fbconfig.redBits; - window->videoMode.greenBits = fbconfig.greenBits; - window->videoMode.blueBits = fbconfig.blueBits; + // Set up desired video mode + window->videoMode.width = width; + window->videoMode.height = height; + window->videoMode.redBits = Max(_glfw.hints.redBits, 0); + window->videoMode.greenBits = Max(_glfw.hints.greenBits, 0); + window->videoMode.blueBits = Max(_glfw.hints.blueBits, 0); + window->videoMode.refreshRate = Max(_glfw.hints.refreshRate, 0); } window->monitor = wndconfig.monitor; @@ -322,6 +324,9 @@ GLFWAPI void glfwWindowHint(int target, int hint) case GLFW_STEREO: _glfw.hints.stereo = hint; break; + case GLFW_REFRESH_RATE: + _glfw.hints.refreshRate = hint; + break; case GLFW_RESIZABLE: _glfw.hints.resizable = hint; break; diff --git a/src/x11_monitor.c b/src/x11_monitor.c index bc49622a..dbd50463 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -67,28 +67,43 @@ void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) { if (_glfw.x11.randr.available) { - int i; + int i, j; XRRScreenResources* sr; XRRCrtcInfo* ci; + XRROutputInfo* oi; RRMode bestMode = 0; - unsigned int leastSizeDiff = UINT_MAX, leastRateDiff = UINT_MAX; + unsigned int sizeDiff, leastSizeDiff = UINT_MAX; + unsigned int rateDiff, leastRateDiff = UINT_MAX; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); + oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); for (i = 0; i < sr->nmode; i++) { - XRRModeInfo* mi = sr->modes + i; + const XRRModeInfo* mi = sr->modes + i; if (mi->modeFlags & RR_Interlace) continue; - const unsigned int sizeDiff = (mi->width - desired->width) * - (mi->width - desired->width) + - (mi->height - desired->height) * - (mi->height - desired->height); + for (j = 0; j < oi->nmode; j++) + { + if (oi->modes[j] == mi->id) + break; + } - const unsigned int rateDiff = abs(calculateRefreshRate(mi) - desired->refreshRate); + if (j == oi->nmode) + continue; + + sizeDiff = (mi->width - desired->width) * + (mi->width - desired->width) + + (mi->height - desired->height) * + (mi->height - desired->height); + + if (desired->refreshRate) + rateDiff = abs(calculateRefreshRate(mi) - desired->refreshRate); + else + rateDiff = UINT_MAX - calculateRefreshRate(mi); if ((sizeDiff < leastSizeDiff) || (sizeDiff == leastSizeDiff && rateDiff < leastRateDiff)) @@ -110,6 +125,7 @@ void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) ci->outputs, ci->noutput); + XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); }