From 0b876c3d4e87b65ea3b3f05ec3274b16600e47fc Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 3 Oct 2020 19:38:55 +0200 Subject: Add refresh rate hint --- pugl/detail/implementation.c | 1 + pugl/detail/mac.m | 20 ++++++++++++++++++++ pugl/detail/win.c | 4 ++-- pugl/detail/win.h | 1 - pugl/detail/x11.c | 13 +++++++++++++ pugl/pugl.h | 1 + pugl/pugl.hpp | 4 ++-- test/test_gl_hints.c | 2 ++ test/test_stub_hints.c | 2 ++ test/test_utils.h | 2 ++ wscript | 17 ++++++++++++----- 11 files changed, 57 insertions(+), 10 deletions(-) diff --git a/pugl/detail/implementation.c b/pugl/detail/implementation.c index 31ee643..6a5f932 100644 --- a/pugl/detail/implementation.c +++ b/pugl/detail/implementation.c @@ -117,6 +117,7 @@ puglSetDefaultHints(PuglHints hints) hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE; hints[PUGL_RESIZABLE] = PUGL_FALSE; hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE; + hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE; } PuglWorld* diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m index 0c50d20..64590c6 100644 --- a/pugl/detail/mac.m +++ b/pugl/detail/mac.m @@ -880,6 +880,26 @@ puglRealize(PuglView* view) view->hints[PUGL_ALPHA_BITS] = 8; } + CGDirectDisplayID displayId = CGMainDisplayID(); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); + + // Try to get refresh rate from mode (usually fails) + view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode); + + CGDisplayModeRelease(mode); + if (view->hints[PUGL_REFRESH_RATE] == 0) { + // Get refresh rate from a display link + // TODO: Keep and actually use the display link for something? + CVDisplayLinkRef link; + CVDisplayLinkCreateWithCGDisplay(displayId, &link); + + const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); + const double r = p.timeScale / (double)p.timeValue; + view->hints[PUGL_REFRESH_RATE] = (int)lrint(r); + + CVDisplayLinkRelease(link); + } + if (view->frame.width == 0.0 && view->frame.height == 0.0) { if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { return PUGL_BAD_CONFIGURATION; diff --git a/pugl/detail/win.c b/pugl/detail/win.c index 38eca9d..17346cb 100644 --- a/pugl/detail/win.c +++ b/pugl/detail/win.c @@ -183,7 +183,7 @@ puglRealize(PuglView* view) // Get refresh rate for resize draw timer DEVMODEA devMode = {0}; EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode); - view->impl->refreshRate = devMode.dmDisplayFrequency; + view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency; // Register window class if necessary if (!puglRegisterWindowClass(view->world->className)) { @@ -592,7 +592,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) view->impl->resizing = true; SetTimer(view->impl->hwnd, PUGL_RESIZE_TIMER_ID, - 1000 / view->impl->refreshRate, + 1000 / (UINT)view->hints[PUGL_REFRESH_RATE], NULL); break; case WM_TIMER: diff --git a/pugl/detail/win.h b/pugl/detail/win.h index 1b9b0c4..547bd02 100644 --- a/pugl/detail/win.h +++ b/pugl/detail/win.h @@ -38,7 +38,6 @@ struct PuglInternalsImpl { HCURSOR cursor; HDC hdc; PuglSurface* surface; - DWORD refreshRate; bool flashing; bool resizing; bool mouseTracked; diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index 7b8daf2..f9a45e8 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -37,6 +37,10 @@ #include #include +#ifdef HAVE_XRANDR +# include +#endif + #ifdef HAVE_XSYNC # include # include @@ -325,6 +329,15 @@ puglRealize(PuglView* view) return st; } +#ifdef HAVE_XRANDR + // Set refresh rate hint to the real refresh rate + XRRScreenConfiguration* conf = XRRGetScreenInfo(display, xParent); + short current_rate = XRRConfigCurrentRate(conf); + + view->hints[PUGL_REFRESH_RATE] = current_rate; + XRRFreeScreenConfigInfo(conf); +#endif + updateSizeHints(view); XClassHint classHint = { world->className, world->className }; diff --git a/pugl/pugl.h b/pugl/pugl.h index 7e27425..bbe1b5d 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -841,6 +841,7 @@ typedef enum { PUGL_SWAP_INTERVAL, ///< Number of frames between buffer swaps PUGL_RESIZABLE, ///< True if view should be resizable PUGL_IGNORE_KEY_REPEAT, ///< True if key repeat events are ignored + PUGL_REFRESH_RATE, ///< Refresh rate in Hz PUGL_NUM_VIEW_HINTS } PuglViewHint; diff --git a/pugl/pugl.hpp b/pugl/pugl.hpp index 4968da4..f6172d1 100644 --- a/pugl/pugl.hpp +++ b/pugl/pugl.hpp @@ -358,10 +358,10 @@ enum class ViewHint { swapInterval, ///< @copydoc PUGL_SWAP_INTERVAL resizable, ///< @copydoc PUGL_RESIZABLE ignoreKeyRepeat, ///< @copydoc PUGL_IGNORE_KEY_REPEAT + refreshRate, ///< @copydoc PUGL_REFRESH_RATE }; -static_assert(ViewHint(PUGL_IGNORE_KEY_REPEAT) == ViewHint::ignoreKeyRepeat, - ""); +static_assert(ViewHint(PUGL_REFRESH_RATE) == ViewHint::refreshRate, ""); using ViewHintValue = PuglViewHintValue; ///< @copydoc PuglViewHintValue diff --git a/test/test_gl_hints.c b/test/test_gl_hints.c index 0e8efbb..a40fdfa 100644 --- a/test/test_gl_hints.c +++ b/test/test_gl_hints.c @@ -57,6 +57,7 @@ main(void) assert(!puglSetViewHint(view, PUGL_STENCIL_BITS, PUGL_DONT_CARE)); assert(!puglSetViewHint(view, PUGL_SAMPLES, PUGL_DONT_CARE)); assert(!puglSetViewHint(view, PUGL_DOUBLE_BUFFER, PUGL_DONT_CARE)); + assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE)); // Realize view and print all hints for debugging convenience assert(!puglRealize(view)); @@ -78,6 +79,7 @@ main(void) assert(puglGetViewHint(view, PUGL_SWAP_INTERVAL) != PUGL_DONT_CARE); assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE); assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE); + assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE); // Tear down puglFreeView(view); diff --git a/test/test_stub_hints.c b/test/test_stub_hints.c index a74927e..96b2914 100644 --- a/test/test_stub_hints.c +++ b/test/test_stub_hints.c @@ -53,6 +53,7 @@ main(void) assert(!puglSetViewHint(view, PUGL_GREEN_BITS, PUGL_DONT_CARE)); assert(!puglSetViewHint(view, PUGL_BLUE_BITS, PUGL_DONT_CARE)); assert(!puglSetViewHint(view, PUGL_ALPHA_BITS, PUGL_DONT_CARE)); + assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE)); // Realize view and print all hints for debugging convenience assert(!puglRealize(view)); @@ -69,6 +70,7 @@ main(void) assert(puglGetViewHint(view, PUGL_ALPHA_BITS) != PUGL_DONT_CARE); assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE); assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE); + assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE); // Tear down puglFreeView(view); diff --git a/test/test_utils.h b/test/test_utils.h index 4253619..6148d84 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -255,6 +255,8 @@ puglViewHintString(const PuglViewHint hint) return "Resizable"; case PUGL_IGNORE_KEY_REPEAT: return "Ignore key repeat"; + case PUGL_REFRESH_RATE: + return "Refresh rate"; case PUGL_NUM_VIEW_HINTS: return "Unknown"; } diff --git a/wscript b/wscript index 10be77c..9317a87 100644 --- a/wscript +++ b/wscript @@ -146,6 +146,8 @@ def configure(conf): if platform == 'darwin': conf.check_cc(framework_name='Cocoa', framework='Cocoa', uselib_store='COCOA') + conf.check_cc(framework_name='Corevideo', framework='Corevideo', + uselib_store='COREVIDEO') if not Options.options.no_gl: conf.check_cc(framework_name='OpenGL', uselib_store='GL', mandatory=False) @@ -176,6 +178,11 @@ def configure(conf): mandatory=False): conf.define('HAVE_XCURSOR', 1) + if conf.check_cc(lib='Xrandr', + uselib_store='XRANDR', + mandatory=False): + conf.define('HAVE_XRANDR', 1) + if not Options.options.no_gl: glx_fragment = """#include int main(void) { glXSwapBuffers(0, 0); return 0; }""" @@ -343,27 +350,27 @@ def build(bld): elif bld.env.TARGET_PLATFORM == 'darwin': platform = 'mac' build_platform('mac', - framework=['Cocoa'], + framework=['Cocoa', 'Corevideo'], source=lib_source + ['pugl/detail/mac.m']) build_backend('mac', 'stub', - framework=['Cocoa'], + framework=['Cocoa', 'Corevideo'], source=['pugl/detail/mac_stub.m']) if bld.env.HAVE_GL: build_backend('mac', 'gl', - framework=['Cocoa', 'OpenGL'], + framework=['Cocoa', 'Corevideo', 'OpenGL'], source=['pugl/detail/mac_gl.m']) if bld.env.HAVE_CAIRO: build_backend('mac', 'cairo', - framework=['Cocoa'], + framework=['Cocoa', 'Corevideo'], uselib=['CAIRO'], source=['pugl/detail/mac_cairo.m']) else: platform = 'x11' build_platform('x11', - uselib=['M', 'X11', 'XSYNC', 'XCURSOR'], + uselib=['M', 'X11', 'XSYNC', 'XCURSOR', 'XRANDR'], source=lib_source + ['pugl/detail/x11.c']) if bld.env.HAVE_GL: -- cgit v1.2.1