From b4a8eb9b197caebcec1304cd3d55cd56e3869376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 19 Dec 2019 08:43:01 +0100 Subject: [PATCH] Cocoa: Only create per-monitor display link once The display link query is not specific to any particular display mode and so only needs to be done once. The next step is to replace the display link altogether by querying IOKit directly, which is what the display link does. --- src/cocoa_monitor.m | 53 ++++++++++++++++++++++++++------------------ src/cocoa_platform.h | 1 + 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 9ef2cdc9..631cc0f6 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -144,7 +144,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode) // Convert Core Graphics display mode to GLFW video mode // static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode, - CVDisplayLinkRef link) + double fallbackRefreshRate) { GLFWvidmode result; result.width = (int) CGDisplayModeGetWidth(mode); @@ -152,11 +152,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode, result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode)); if (result.refreshRate == 0) - { - const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); - if (!(time.flags & kCVTimeIsIndefinite)) - result.refreshRate = (int) (time.timeScale / (double) time.timeValue); - } + result.refreshRate = (int) round(fallbackRefreshRate); #if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); @@ -238,6 +234,29 @@ static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor) return GLFW_FALSE; } +// Returns a fallback refresh rate for when Core Graphics says it is zero +// +static double getFallbackRefreshRate(_GLFWmonitor* monitor) +{ + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(monitor->ns.displayID); + double refreshRate = CGDisplayModeGetRefreshRate(mode); + CGDisplayModeRelease(mode); + + if (refreshRate == 0.0) + { + CVDisplayLinkRef link = NULL; + CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); + + const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); + if (!(time.flags & kCVTimeIsIndefinite)) + refreshRate = (int) (time.timeScale / (double) time.timeValue); + + CVDisplayLinkRelease(link); + } + + return refreshRate; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -291,6 +310,7 @@ void _glfwPollMonitorsNS(void) _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height); monitor->ns.displayID = displays[i]; monitor->ns.unitNumber = unitNumber; + monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor); free(name); @@ -318,9 +338,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) if (_glfwCompareVideoModes(¤t, best) == 0) return; - CVDisplayLinkRef link; - CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); - CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); const CFIndex count = CFArrayGetCount(modes); CGDisplayModeRef native = NULL; @@ -331,7 +348,8 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) if (!modeIsGood(dm)) continue; - const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); + const GLFWvidmode mode = + vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate); if (_glfwCompareVideoModes(best, &mode) == 0) { native = dm; @@ -350,7 +368,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) } CFRelease(modes); - CVDisplayLinkRelease(link); } // Restore the previously saved (original) video mode @@ -440,9 +457,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) *count = 0; - CVDisplayLinkRef link; - CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); - CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); const CFIndex found = CFArrayGetCount(modes); GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode)); @@ -453,7 +467,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) if (!modeIsGood(dm)) continue; - const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); + const GLFWvidmode mode = + vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate); CFIndex j; for (j = 0; j < *count; j++) @@ -471,7 +486,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) } CFRelease(modes); - CVDisplayLinkRelease(link); return result; } // autoreleasepool @@ -481,15 +495,10 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) { @autoreleasepool { - CVDisplayLinkRef link; - CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); - CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID); - *mode = vidmodeFromCGDisplayMode(native, link); + *mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate); CGDisplayModeRelease(native); - CVDisplayLinkRelease(link); - } // autoreleasepool } diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 21d83bcc..c9f96ee0 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -170,6 +170,7 @@ typedef struct _GLFWmonitorNS CGDisplayModeRef previousMode; uint32_t unitNumber; id screen; + double fallbackRefreshRate; } _GLFWmonitorNS;