Dav*_*her 10 core-graphics objective-c iokit core-foundation multi-gpu
在Mac OS X中,每个显示都会CGDirectDisplayID分配一个唯一的编号.您可以使用CGGetActiveDisplayList()或[NSScreen screens]访问它们等.根据Apple的文档:
显示ID可以在进程和系统重新引导之间持续存在,并且只要某些显示参数不变,通常保持不变.
在2010年年中的MacBook Pro上,Apple开始使用自动切换Intel/nVidia显卡.笔记本电脑有两个GPU,一个低功耗的英特尔和一个高性能的nVidia.以前的双GPU笔记本电脑(2009型号)没有自动GPU切换,需要用户进行设置更改,注销,然后再次登录以进行GPU切换.即使是较旧的系统也只有一个GPU.
2010年中期的模型存在一个问题,当显示器从一个GPU切换到另一个GPU时,CGDirectDisplayID不会保持不变.例如:
我的问题是,如果由于GPU更改而改变时,如何将旧显示ID与新显示ID匹配?
想到:
我注意到显示ID只改变了2,但我没有足够的测试Mac可用来确定这是否适用于所有新MacBook Pro,或者只是我的.无论如何,如果"仅检查彼此+/- 2的显示ID",那就是一种kludge.
尝试:
CGDisplayRegisterReconfigurationCallback(),当显示器要改变时通知前后,没有匹配的逻辑.在这个注册的方法中放置这样的东西是行不通的:
// Run before display settings change:
CGDirectDisplayID directDisplayID = ...;
io_service_t servicePort = CGDisplayIOServicePort(directDisplayID);
CFDictionaryRef oldInfoDict = IODisplayCreateInfoDictionary(servicePort, kIODisplayMatchingInfo);
// ...display settings change...
// Run after display settings change:
CGDirectDisplayID directDisplayID = ...;
io_service_t servicePort = CGDisplayIOServicePort(directDisplayID);
CFDictionaryRef newInfoDict = IODisplayCreateInfoDictionary(servicePort, kIODisplayMatchingInfo);
BOOL match = IODisplayMatchDictionaries(oldInfoDict, newInfoDict, 0);
if (match)
NSLog(@"Displays are a match");
else
NSLog(@"Displays are not a match");
Run Code Online (Sandbox Code Playgroud)
上面发生的是:
IODisplayMatchDictionaries()IODisplayMatchDictionaries() 返回一个BOOL,或者是YES它们是相同的,或者NO它们是不同的.不幸的是,IODisplayMatchDictionaries()如果相同的显示改变了GPU ,则不会返回YES.这是一个比较字典的例子(看一下IODisplayLocation键):
// oldInfoDict (Display ID: 30002)
oldInfoDict: {
DisplayProductID = 40144;
DisplayVendorID = 1552;
IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/IGPU@2/AppleIntelFramebuffer/display0/AppleBacklightDisplay";
}
// newInfoDict (Display ID: 30004)
newInfoDict: {
DisplayProductID = 40144;
DisplayVendorID = 1552;
IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/P0P2@1/IOPCI2PCIBridge/GFX0@0/NVDA,Display-A@0/NVDA/display0/AppleBacklightDisplay";
}
Run Code Online (Sandbox Code Playgroud)
如您所见,IODisplayLocation当GPU切换时,键会发生变化,因此IODisplayMatchDictionaries()不起作用.
理论上,我可以比较DisplayProductID和DisplayVendorID键,但我正在编写最终用户软件,并且担心用户插入了两个或更多相同的监视器(意味着它们都具有相同的DisplayProductID/DisplayVendorID) .换句话说,这是一个不太完美的解决方案,可能会出现潜在的故障.
任何帮助是极大的赞赏!:)
使用 CFUUIDRef 可以通过以下方式获得:
CGDisplayCreateUUIDFromDisplayID(CGDirectDisplayID displayID)
您可以使用以下方法取回显示 ID:
CGDisplayGetDisplayIDFromUUID(CFUUIDRef uuid)
这就是我用来唯一标识显示器的方法,即使它们的 CGDirectDisplayID 发生变化,例如插入不同的端口。不幸的是,Apple 没有正确记录这些功能,但我在具有多个显示器的多台 Mac 上的测试表明,获得的 CFUUIDRef 是唯一且一致的 - 即使在重新启动后 - 无论 CGDirectDisplayID 是否因任何原因发生变化。
要检查一个显示是否是新的/唯一的,取其 CGDirectDisplayID 并将其转换为 CFUUIDRef,然后比较 UUID,这是一个多对一的关系,许多 CGDirectDisplayID 将映射到单个 CFUUIDRef。
这些 API 调用在 10.7 - 10.12 中的 ApplicationServices 和 10.13 以后的 ColorSync 中可用。
虽然我不是专业人士,但我相信答案是让 Apple在用户更改显示时通知您。回调中的信息包含添加和删除的标志CGDirectDisplayID。
用户不应该在操作期间添加或删除显卡,因此我会在启动时制作列表,并且每当您获得“删除”标志时,都会设置下一个“添加”操作来替换列表中的该 ID。
CGDisplayRegisterReconfigurationCallback我会尝试只打印每次调用函数时返回的信息。看看您是否得到一个带有“删除”标志的 DeviceUID,然后随后调用另一个带有“添加”标志的设备UID。检查这些 IDCGGetActiveDisplayList也有助于了解发生了什么。
这是我最好的选择,希望有帮助!
| 归档时间: |
|
| 查看次数: |
3072 次 |
| 最近记录: |