mirror of
https://github.com/glfw/glfw.git
synced 2025-10-04 05:36:35 +00:00
cocoa: Implement OpenGL swap interval support with CVDisplayLink
Fixes VSync on macOS 10.14 (Mojave) by using CVDisplayLink to synchronise frames rather than setting NSOpenGLContextParameterSwapInterval.
This commit is contained in:
parent
72c3908e14
commit
5cb1a48fa3
12
src/nsgl_context.h
Normal file → Executable file
12
src/nsgl_context.h
Normal file → Executable file
@ -27,13 +27,21 @@
|
|||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||||
|
|
||||||
|
#import <CoreVideo/CoreVideo.h>
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
|
||||||
// NSGL-specific per-context data
|
// NSGL-specific per-context data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWcontextNSGL
|
typedef struct _GLFWcontextNSGL
|
||||||
{
|
{
|
||||||
id pixelFormat;
|
id pixelFormat;
|
||||||
id object;
|
id object;
|
||||||
|
CVDisplayLinkRef displayLink;
|
||||||
|
atomic_int swapInterval;
|
||||||
|
int swapIntervalsPassed;
|
||||||
|
id swapIntervalCond;
|
||||||
|
|
||||||
} _GLFWcontextNSGL;
|
} _GLFWcontextNSGL;
|
||||||
|
|
||||||
|
51
src/nsgl_context.m
Normal file → Executable file
51
src/nsgl_context.m
Normal file → Executable file
@ -31,6 +31,27 @@
|
|||||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink,
|
||||||
|
const CVTimeStamp* now,
|
||||||
|
const CVTimeStamp* outputTime,
|
||||||
|
CVOptionFlags flagsIn,
|
||||||
|
CVOptionFlags* flagsOut,
|
||||||
|
void* userInfo)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow *) userInfo;
|
||||||
|
|
||||||
|
const int setting = atomic_load(&window->context.nsgl.swapInterval);
|
||||||
|
if (setting > 0)
|
||||||
|
{
|
||||||
|
[window->context.nsgl.swapIntervalCond lock];
|
||||||
|
window->context.nsgl.swapIntervalsPassed++;
|
||||||
|
[window->context.nsgl.swapIntervalCond signal];
|
||||||
|
[window->context.nsgl.swapIntervalCond unlock];
|
||||||
|
}
|
||||||
|
|
||||||
|
return kCVReturnSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
@ -43,6 +64,18 @@ static void makeContextCurrentNSGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
const int setting = atomic_load(&window->context.nsgl.swapInterval);
|
||||||
|
if (setting > 0)
|
||||||
|
{
|
||||||
|
[window->context.nsgl.swapIntervalCond lock];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
[window->context.nsgl.swapIntervalCond wait];
|
||||||
|
} while (window->context.nsgl.swapIntervalsPassed % setting != 0);
|
||||||
|
window->context.nsgl.swapIntervalsPassed = 0;
|
||||||
|
[window->context.nsgl.swapIntervalCond unlock];
|
||||||
|
}
|
||||||
|
|
||||||
// ARP appears to be unnecessary, but this is future-proof
|
// ARP appears to be unnecessary, but this is future-proof
|
||||||
[window->context.nsgl.object flushBuffer];
|
[window->context.nsgl.object flushBuffer];
|
||||||
}
|
}
|
||||||
@ -51,9 +84,10 @@ static void swapIntervalNSGL(int interval)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
GLint sync = interval;
|
atomic_store(&window->context.nsgl.swapInterval, interval);
|
||||||
[window->context.nsgl.object setValues:&sync
|
[window->context.nsgl.swapIntervalCond lock];
|
||||||
forParameter:NSOpenGLContextParameterSwapInterval];
|
window->context.nsgl.swapIntervalsPassed = 0;
|
||||||
|
[window->context.nsgl.swapIntervalCond unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extensionSupportedNSGL(const char* extension)
|
static int extensionSupportedNSGL(const char* extension)
|
||||||
@ -316,6 +350,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressNSGL;
|
window->context.getProcAddress = getProcAddressNSGL;
|
||||||
window->context.destroy = destroyContextNSGL;
|
window->context.destroy = destroyContextNSGL;
|
||||||
|
|
||||||
|
CVDisplayLinkCreateWithActiveCGDisplays(&window->context.nsgl.displayLink);
|
||||||
|
CVDisplayLinkSetOutputCallback(window->context.nsgl.displayLink,
|
||||||
|
&displayLinkCallback,
|
||||||
|
window);
|
||||||
|
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(window->context.nsgl.displayLink,
|
||||||
|
window->context.nsgl.object,
|
||||||
|
window->context.nsgl.pixelFormat);
|
||||||
|
CVDisplayLinkStart(window->context.nsgl.displayLink);
|
||||||
|
|
||||||
|
window->context.nsgl.swapIntervalCond = [NSCondition new];
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user