aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-10-03 19:38:55 +0200
committerDavid Robillard <d@drobilla.net>2020-10-04 12:52:37 +0200
commit0b876c3d4e87b65ea3b3f05ec3274b16600e47fc (patch)
tree09f4cb47953ac769c8b740900ea9b54ac8639a52
parenta36408b7c641e0b9052315aed87ce8e591a6a717 (diff)
Add refresh rate hint
-rw-r--r--pugl/detail/implementation.c1
-rw-r--r--pugl/detail/mac.m20
-rw-r--r--pugl/detail/win.c4
-rw-r--r--pugl/detail/win.h1
-rw-r--r--pugl/detail/x11.c13
-rw-r--r--pugl/pugl.h1
-rw-r--r--pugl/pugl.hpp4
-rw-r--r--test/test_gl_hints.c2
-rw-r--r--test/test_stub_hints.c2
-rw-r--r--test/test_utils.h2
-rw-r--r--wscript17
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 <X11/Xutil.h>
#include <X11/keysym.h>
+#ifdef HAVE_XRANDR
+# include <X11/extensions/Xrandr.h>
+#endif
+
#ifdef HAVE_XSYNC
# include <X11/extensions/sync.h>
# include <X11/extensions/syncconst.h>
@@ -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 <GL/glx.h>
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: