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.
This commit is contained in:
Camilla Löwy 2019-12-19 08:43:01 +01:00
parent 28773a069e
commit b4a8eb9b19
2 changed files with 32 additions and 22 deletions

View File

@ -144,7 +144,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
// Convert Core Graphics display mode to GLFW video mode // Convert Core Graphics display mode to GLFW video mode
// //
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode, static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
CVDisplayLinkRef link) double fallbackRefreshRate)
{ {
GLFWvidmode result; GLFWvidmode result;
result.width = (int) CGDisplayModeGetWidth(mode); result.width = (int) CGDisplayModeGetWidth(mode);
@ -152,11 +152,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode)); result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
if (result.refreshRate == 0) if (result.refreshRate == 0)
{ result.refreshRate = (int) round(fallbackRefreshRate);
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if (!(time.flags & kCVTimeIsIndefinite))
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
@ -238,6 +234,29 @@ static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)
return GLFW_FALSE; 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 ////// ////// GLFW internal API //////
@ -291,6 +310,7 @@ void _glfwPollMonitorsNS(void)
_GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height); _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i]; monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = unitNumber; monitor->ns.unitNumber = unitNumber;
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor);
free(name); free(name);
@ -318,9 +338,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return; return;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
const CFIndex count = CFArrayGetCount(modes); const CFIndex count = CFArrayGetCount(modes);
CGDisplayModeRef native = NULL; CGDisplayModeRef native = NULL;
@ -331,7 +348,8 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
if (!modeIsGood(dm)) if (!modeIsGood(dm))
continue; continue;
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); const GLFWvidmode mode =
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
if (_glfwCompareVideoModes(best, &mode) == 0) if (_glfwCompareVideoModes(best, &mode) == 0)
{ {
native = dm; native = dm;
@ -350,7 +368,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
} }
CFRelease(modes); CFRelease(modes);
CVDisplayLinkRelease(link);
} }
// Restore the previously saved (original) video mode // Restore the previously saved (original) video mode
@ -440,9 +457,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
*count = 0; *count = 0;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
const CFIndex found = CFArrayGetCount(modes); const CFIndex found = CFArrayGetCount(modes);
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode)); GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
@ -453,7 +467,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
if (!modeIsGood(dm)) if (!modeIsGood(dm))
continue; continue;
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); const GLFWvidmode mode =
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
CFIndex j; CFIndex j;
for (j = 0; j < *count; j++) for (j = 0; j < *count; j++)
@ -471,7 +486,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
} }
CFRelease(modes); CFRelease(modes);
CVDisplayLinkRelease(link);
return result; return result;
} // autoreleasepool } // autoreleasepool
@ -481,15 +495,10 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
{ {
@autoreleasepool { @autoreleasepool {
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID); CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
*mode = vidmodeFromCGDisplayMode(native, link); *mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
CGDisplayModeRelease(native); CGDisplayModeRelease(native);
CVDisplayLinkRelease(link);
} // autoreleasepool } // autoreleasepool
} }

View File

@ -170,6 +170,7 @@ typedef struct _GLFWmonitorNS
CGDisplayModeRef previousMode; CGDisplayModeRef previousMode;
uint32_t unitNumber; uint32_t unitNumber;
id screen; id screen;
double fallbackRefreshRate;
} _GLFWmonitorNS; } _GLFWmonitorNS;