Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to resolve CGDirectDisplayID changing issues on newer multi-GPU Apple laptops in Core Foundation/IO Kit?
    primarykey
    data
    text
    <p>In Mac OS X, every display gets a unique <code>CGDirectDisplayID</code> number assigned to it. You can use <code>CGGetActiveDisplayList(</code>) or <code>[NSScreen screens]</code> to access them, among others. Per <a href="http://CGDisplayRegisterReconfigurationCallback" rel="noreferrer">Apple's docs</a>:</p> <blockquote> <p>A display ID can persist across processes and system reboot, and typically remains constant as long as certain display parameters do not change.</p> </blockquote> <p>On newer mid-2010 MacBook Pro's, Apple started using auto-switching Intel/nVidia graphics. Laptops have two GPU's, a low-powered Intel, and a high-powered nVidia. Previous dual-GPU laptops (2009 models) didn't have auto-GPU switching, and required the user to make a settings change, logoff, and then logon again to make a GPU switch occur. Even older systems only had one GPU.</p> <p>There's an issue with the mid-2010 models where CGDirectDisplayID's don't remain the same when a display switches from one GPU to the next. For example:</p> <ol> <li>Laptop powers on.</li> <li>Built-In <strong>LCD Screen</strong> is driven by Intel chipset. Display ID: <strong>30002</strong></li> <li><strong>External Display</strong> is plugged in.</li> <li>Built-In <strong>LCD Screen</strong> switches to nVidia chipset. It's display ID changes: <strong>30004</strong></li> <li><strong>External Display</strong> is driven by nVidia chipset.</li> <li>...at this point, the Intel chipset is dormant...</li> <li>User unplugs <strong>External Display</strong>.</li> <li>Built-In <strong>LCD Screen</strong> switches back to Intel chipset. It's display ID changes back to original: <strong>30002</strong></li> </ol> <p><strong>My question is, how can I match an old display ID to a new display ID when they alter due to a GPU change?</strong></p> <hr> <p><strong>Thought about:</strong></p> <p>I've noticed that the display ID only changes by 2, but I don't have enough test Mac's available to determine if this is common to all new MacBook Pro's, or just mine. Kind of a kludge if "just check for display ID's which are +/-2 from one another" works, anyway.</p> <hr> <p><strong>Tried:</strong></p> <p><code>CGDisplayRegisterReconfigurationCallback()</code>, which notifies before-and-after when displays are going to change, has no matching logic. Putting something like this inside a method registered with it doesn't work:</p> <pre><code>// 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"); </code></pre> <p>What's happening above is:</p> <ol> <li>I'm caching <strong>oldInfoDict</strong> before display settings change.</li> <li>Waiting for display settings to change</li> <li>Then comparing <strong>oldInfoDict</strong> to <strong>newInfoDict</strong> by using <code>IODisplayMatchDictionaries()</code></li> <li><code>IODisplayMatchDictionaries()</code> returns a BOOL, either YES they're the same, or NO they're different.</li> </ol> <p>Unfortunately, <code>IODisplayMatchDictionaries()</code> doesn't return YES if the same display changed GPU's. Here's an example of the dictionary's it's comparing (look at the <code>IODisplayLocation</code> key):</p> <pre><code>// 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"; } </code></pre> <p>As you can see, the <code>IODisplayLocation</code> key changes when GPU's are switched, hence <code>IODisplayMatchDictionaries()</code> doesn't work.</p> <p>I can, theoretically, compared just the <code>DisplayProductID</code> and <code>DisplayVendorID</code> keys, but I'm writing end-user software, and am worried of a situation where users have two or more identical monitors plugged in (meaning they'll both have the same DisplayProductID/DisplayVendorID). In other words, it's a less-than-perfect solution open to potential glitches.</p> <hr> <p>Any help is greatly appreciated! :)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload