Skip to content

Commit

Permalink
Add refresh rate hint
Browse files Browse the repository at this point in the history
  • Loading branch information
drobilla committed Oct 4, 2020
1 parent a36408b commit 0b876c3
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 10 deletions.
1 change: 1 addition & 0 deletions pugl/detail/implementation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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*
Expand Down
20 changes: 20 additions & 0 deletions pugl/detail/mac.m
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,26 @@ - (void) windowDidResignKey:(NSNotification*)notification
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;
Expand Down
4 changes: 2 additions & 2 deletions pugl/detail/win.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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:
Expand Down
1 change: 0 additions & 1 deletion pugl/detail/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ struct PuglInternalsImpl {
HCURSOR cursor;
HDC hdc;
PuglSurface* surface;
DWORD refreshRate;
bool flashing;
bool resizing;
bool mouseTracked;
Expand Down
13 changes: 13 additions & 0 deletions pugl/detail/x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 };
Expand Down
1 change: 1 addition & 0 deletions pugl/pugl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions pugl/pugl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions test/test_gl_hints.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions test/test_stub_hints.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions test/test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
17 changes: 12 additions & 5 deletions wscript
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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; }"""
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 0b876c3

Please sign in to comment.