【发布时间】:2014-08-12 10:38:52
【问题描述】:
我需要在显示器确实具有不同特征的范围内对显示器进行唯一标识。因此,插入同一个物理端口的相同型号的显示器不会被视为不同,但基本上其他一切都会被视为不同。
当系统 GPU 发生变化时,CGDirectDisplayID 也会发生变化,但不会以记录的方式发生变化。实验表明,相同的屏幕 ID 会根据使用的 GPU 相差 2。
解决此问题的一种方法是获取显示的 IO 注册表字符串:
io_service_t servicePort = CGDisplayIOServicePort (cgDisplayID);
io_service_t root = IODisplayForFramebuffer (servicePort, kNilOptions);
NSDictionary* ioRegistryDict = nil;
NSString* displayKey = nil;
IORegistryEntryCreateCFProperties (root, (CFMutableDictionaryRef *)&ioRegistryDict, kCFAllocatorDefault, kNilOptions);
if (ioRegistryDict)
displayKey = [ioRegistryDict objectForKey:@"IODisplayPrefsKey"];
这很好用,除了在 10.9 中,CGDisplayIOServicePort 已被弃用。
鉴于所有这一切,以及 Apple 的建议不要缓存 NSScreens(无论如何它都不能真正用于此目的),可靠识别屏幕的最佳方法是什么,以便我可以分辨(例如)在家屏幕和工作屏幕?
我不想依赖屏幕分辨率,因为用户更改分辨率不应被视为不同的显示器。不同 GPU 上的相同屏幕也不应被视为不同。
次要目标是找到一种方法,在给定 CGDirectDisplayID 的情况下,如果发生 GPU 切换,我如何确定同一屏幕的 CGDirectDisplayID 是什么?只要我可以匹配来自两个 GPU 控制器的两个结果,这至少可以让我通过 CGDirectDisplayID 跟踪显示。
【问题讨论】:
-
我不确定您希望显示的哪些属性会影响“相同”与“不同”的概念,但您应该查看 Quartz 显示服务功能,例如
CGDisplayModelNumber()、CGDisplaySerialNumber()、CGDisplayUnitNumber()和CGDisplayVendorNumber()。 -
Quartz 参考声明“在分配显示 ID 时,Quartz 会考虑以下参数:供应商、型号、序列号和 I/O 套件注册表中的位置”当我在集成的 MBP 上运行时我得到的 GPU:displayID:2077805631。在快速 GPU (AMD Radeon) 上,我得到一个 displayID:69678016。在这两种情况下,供应商、型号、序列号和单位都是相同的:1552、40143、0、0。那么苹果还做了什么导致这些ID 不同?
-
我不知道。我怀疑该列表是否旨在详尽无遗。但你为什么在乎?我以为您正在寻找一种方法来识别没有随 GPU 发生变化的显示器。
-
确实,这可能适用于第一个问题。但是对于第二个,我正在寻找一种方法来确定 69678016 和 2077805631 指的是同一个屏幕……我希望能够从另一个中派生出其中一个。这是因为 Apple 使用 DisplayID 来确定桌面和空间,但 Apple 只会使用其中一个(我称之为主 ID),即使 GPU 已经规定“辅助 ID”是从任何查询返回的内容NSS 屏幕。
-
我有另一个想法(尽管我仍然不确定我是否理解您在寻找什么)。尝试将
CGDisplayIDToOpenGLDisplayMask()与两个显示 ID 一起使用。它们可能映射到 OpenGL 显示掩码中的同一位。您还可以尝试通过CGOpenGLDisplayMaskToDisplayID()来回返回,看看它是否“标准化”为单个显示 ID。
标签: xcode macos gpu retina-display