From c3ca88055f7c2c8b02b38cb90fc1989990552977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 10 Nov 2019 19:09:23 +0100 Subject: [PATCH] NSGL: Simulate vsync for occluded windows This only supports a swap interval of zero or one, as that is all NSGL supports. --- src/nsgl_context.m | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 6c20fca0..e011fa5e 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -28,6 +28,9 @@ #include "internal.h" +#include +#include + static void makeContextCurrentNSGL(_GLFWwindow* window) { @autoreleasepool { @@ -45,7 +48,31 @@ static void makeContextCurrentNSGL(_GLFWwindow* window) static void swapBuffersNSGL(_GLFWwindow* window) { @autoreleasepool { + + // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to + // windows with a non-visible occlusion state + if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)) + { + int interval = 0; + [window->context.nsgl.object getValues:&interval + forParameter:NSOpenGLContextParameterSwapInterval]; + + if (interval > 0) + { + const double framerate = 60.0; + const uint64_t frequency = _glfwPlatformGetTimerFrequency(); + const uint64_t value = _glfwPlatformGetTimerValue(); + + const double elapsed = value / (double) frequency; + const double period = 1.0 / framerate; + const double delay = period - fmod(elapsed, period); + + usleep(floorl(delay * 1e6)); + } + } + [window->context.nsgl.object flushBuffer]; + } // autoreleasepool } @@ -53,11 +80,11 @@ static void swapIntervalNSGL(int interval) { @autoreleasepool { - NSOpenGLContext* context = [NSOpenGLContext currentContext]; - if (context) + _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + if (window) { - [context setValues:&interval - forParameter:NSOpenGLContextParameterSwapInterval]; + [window->context.nsgl.object setValues:&interval + forParameter:NSOpenGLContextParameterSwapInterval]; } } // autoreleasepool