From 803fba9cfdbe24fff7bac19c0a2f62b5627ff31e Mon Sep 17 00:00:00 2001 From: Luflosi Date: Sat, 23 May 2020 13:14:49 +0200 Subject: [PATCH] Cocoa: Replace display link with IOKit query From upstream: https://github.com/glfw/glfw/commit/4ec7daf3e92440efab8dac7c1f4c60707d990ed0. --- glfw/cocoa_monitor.m | 73 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/glfw/cocoa_monitor.m b/glfw/cocoa_monitor.m index 44f6b0184..00d4c7f24 100644 --- a/glfw/cocoa_monitor.m +++ b/glfw/cocoa_monitor.m @@ -236,26 +236,65 @@ static bool refreshMonitorScreen(_GLFWmonitor* monitor) return false; } -// Returns a fallback refresh rate for when Core Graphics says it is zero +// Returns the display refresh rate queried from the I/O registry // -static double getFallbackRefreshRate(_GLFWmonitor* monitor) +static double getFallbackRefreshRate(CGDirectDisplayID displayID) { - CGDisplayModeRef mode = CGDisplayCopyDisplayMode(monitor->ns.displayID); - double refreshRate = CGDisplayModeGetRefreshRate(mode); - CGDisplayModeRelease(mode); + double refreshRate = 60.0; - if (refreshRate == 0.0) + io_iterator_t it; + io_service_t service; + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, + IOServiceMatching("IOFramebuffer"), + &it) != 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; } + while ((service = IOIteratorNext(it)) != 0) + { + const CFNumberRef indexRef = + IORegistryEntryCreateCFProperty(service, + CFSTR("IOFramebufferOpenGLIndex"), + kCFAllocatorDefault, + kNilOptions); + if (!indexRef) + continue; + + uint32_t index = 0; + CFNumberGetValue(indexRef, kCFNumberIntType, &index); + CFRelease(indexRef); + + if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID) + continue; + + const CFNumberRef clockRef = + IORegistryEntryCreateCFProperty(service, + CFSTR("IOFBCurrentPixelClock"), + kCFAllocatorDefault, + kNilOptions); + const CFNumberRef countRef = + IORegistryEntryCreateCFProperty(service, + CFSTR("IOFBCurrentPixelCount"), + kCFAllocatorDefault, + kNilOptions); + if (!clockRef || !countRef) + break; + + uint32_t clock = 0, count = 0; + CFNumberGetValue(clockRef, kCFNumberIntType, &clock); + CFNumberGetValue(countRef, kCFNumberIntType, &count); + CFRelease(clockRef); + CFRelease(countRef); + + if (clock > 0 && count > 0) + refreshRate = clock / (double) count; + + break; + } + + IOObjectRelease(it); return refreshRate; } @@ -351,11 +390,15 @@ void _glfwPollMonitorsNS(void) _GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height); monitor->ns.displayID = displays[i]; monitor->ns.unitNumber = unitNumber; - monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor); createDisplayLink(monitor->ns.displayID); free(name); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]); + if (CGDisplayModeGetRefreshRate(mode) == 0.0) + monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]); + CGDisplayModeRelease(mode); + _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); }