diff --git a/src/nsgl_context.m b/src/nsgl_context.m index ba4e422f..3bcfafcc 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