Title: [234377] trunk/Source/WebCore
Revision
234377
Author
[email protected]
Date
2018-07-30 12:52:51 -0700 (Mon, 30 Jul 2018)

Log Message

Match GraphicsContext3D with correct virtual screen using registryID
https://bugs.webkit.org/show_bug.cgi?id=188072
<rdar://problem/42634940>

Patch by Justin Fan <[email protected]> on 2018-07-30
Reviewed by Dean Jackson.

Follow up to https://bugs.webkit.org/show_bug.cgi?id=187750. Rather than matching rendererIDs,
which can vary between processes, match GPU to display using registryID that is unique to a GPU,
which was added to CGL in MacOS 10.13.

No new tests. Manually tested on MacBookPro13,3 and iMacPro1,1 with Apple DisplayPort Cinema Display
and RX 580 external GPU.

* platform/PlatformScreen.h:
* platform/ScreenProperties.h:
(WebCore::ScreenData::encode const):
(WebCore::ScreenData::decode):
* platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
(WebCore::setGPUByRegistryID):
(WebCore::setGPUByDisplayMask):
(WebCore::GraphicsContext3D::GraphicsContext3D):
(WebCore::GraphicsContext3D::screenDidChange):
(WebCore::identifyAndSetCurrentGPU): Deleted.
* platform/mac/PlatformScreenMac.mm:
(WebCore::collectScreenProperties):
(WebCore::primaryRegistryID):
(WebCore::registryIDForDisplay):
(WebCore::registryIDForDisplayMask):
(WebCore::rendererIDForDisplayMask): Deleted.
(WebCore::rendererIDForDisplay): Deleted.
(WebCore::primaryRendererID): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (234376 => 234377)


--- trunk/Source/WebCore/ChangeLog	2018-07-30 19:37:42 UTC (rev 234376)
+++ trunk/Source/WebCore/ChangeLog	2018-07-30 19:52:51 UTC (rev 234377)
@@ -1,3 +1,37 @@
+2018-07-30  Justin Fan  <[email protected]>
+
+        Match GraphicsContext3D with correct virtual screen using registryID
+        https://bugs.webkit.org/show_bug.cgi?id=188072
+        <rdar://problem/42634940>
+
+        Reviewed by Dean Jackson.
+
+        Follow up to https://bugs.webkit.org/show_bug.cgi?id=187750. Rather than matching rendererIDs, 
+        which can vary between processes, match GPU to display using registryID that is unique to a GPU, 
+        which was added to CGL in MacOS 10.13. 
+
+        No new tests. Manually tested on MacBookPro13,3 and iMacPro1,1 with Apple DisplayPort Cinema Display
+        and RX 580 external GPU. 
+
+        * platform/PlatformScreen.h:
+        * platform/ScreenProperties.h:
+        (WebCore::ScreenData::encode const):
+        (WebCore::ScreenData::decode):
+        * platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
+        (WebCore::setGPUByRegistryID):
+        (WebCore::setGPUByDisplayMask):
+        (WebCore::GraphicsContext3D::GraphicsContext3D):
+        (WebCore::GraphicsContext3D::screenDidChange):
+        (WebCore::identifyAndSetCurrentGPU): Deleted.
+        * platform/mac/PlatformScreenMac.mm:
+        (WebCore::collectScreenProperties):
+        (WebCore::primaryRegistryID):
+        (WebCore::registryIDForDisplay):
+        (WebCore::registryIDForDisplayMask):
+        (WebCore::rendererIDForDisplayMask): Deleted.
+        (WebCore::rendererIDForDisplay): Deleted.
+        (WebCore::primaryRendererID): Deleted.
+
 2018-07-30  Rob Buis  <[email protected]>
 
         Merge PlatformCookieJar functions into NetworkStorageSession

Modified: trunk/Source/WebCore/platform/PlatformScreen.h (234376 => 234377)


--- trunk/Source/WebCore/platform/PlatformScreen.h	2018-07-30 19:37:42 UTC (rev 234376)
+++ trunk/Source/WebCore/platform/PlatformScreen.h	2018-07-30 19:52:51 UTC (rev 234377)
@@ -58,6 +58,7 @@
 class Widget;
 
 using PlatformDisplayID = uint32_t;
+using IORegistryGPUID = int64_t; // Global IOKit I/O registryID that can match a GPU across process boundaries.
 
 int screenDepth(Widget*);
 int screenDepthPerComponent(Widget*);
@@ -100,10 +101,15 @@
 
 uint32_t primaryOpenGLDisplayMask();
 uint32_t displayMaskForDisplay(PlatformDisplayID);
-int32_t rendererIDForDisplay(PlatformDisplayID);
-int32_t primaryRendererID();
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+IORegistryGPUID primaryGPUID();
+IORegistryGPUID gpuIDForDisplay(PlatformDisplayID);
+IORegistryGPUID gpuIDForDisplayMask(uint32_t);
 #endif
 
+#endif // !PLATFORM(MAC)
+
 #if PLATFORM(IOS)
 
 float screenPPIFactor();

Modified: trunk/Source/WebCore/platform/ScreenProperties.h (234376 => 234377)


--- trunk/Source/WebCore/platform/ScreenProperties.h	2018-07-30 19:37:42 UTC (rev 234376)
+++ trunk/Source/WebCore/platform/ScreenProperties.h	2018-07-30 19:52:51 UTC (rev 234377)
@@ -46,7 +46,7 @@
     bool screenHasInvertedColors { false };
     bool screenIsMonochrome { false };
     uint32_t displayMask { 0 };
-    int32_t rendererID { 0 };
+    IORegistryGPUID gpuID { 0 };
 
     enum EncodedColorSpaceDataType {
         Null,
@@ -94,7 +94,7 @@
 template<class Encoder>
 void ScreenData::encode(Encoder& encoder) const
 {
-    encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask << rendererID;
+    encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask << gpuID;
 
     if (colorSpace) {
         // Try to encode the name.
@@ -163,9 +163,9 @@
     if (!displayMask)
         return std::nullopt;
 
-    std::optional<int32_t> rendererID;
-    decoder >> rendererID;
-    if (!rendererID)
+    std::optional<IORegistryGPUID> gpuID;
+    decoder >> gpuID;
+    if (!gpuID)
         return std::nullopt;
     
     EncodedColorSpaceDataType dataType;
@@ -203,7 +203,7 @@
     }
     }
 
-    return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask), WTFMove(*rendererID) } };
+    return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask), WTFMove(*gpuID) } };
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm (234376 => 234377)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm	2018-07-30 19:37:42 UTC (rev 234376)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm	2018-07-30 19:52:51 UTC (rev 234377)
@@ -162,13 +162,15 @@
 }
 
 #if PLATFORM(MAC)
-static void identifyAndSetCurrentGPU(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, GLint preferredRendererID)
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+static void setGPUByRegistryID(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, IORegistryGPUID preferredGPUID)
 {
-    // When the WebProcess does not have access to the WindowServer, there is no way for OpenGL to tell which GPU/renderer is connected to a display.
-    // Find the virtual screen that corresponds to the preferred renderer.
+    // When the WebProcess does not have access to the WindowServer, there is no way for OpenGL to tell which GPU is connected to a display.
+    // On 10.13+, find the virtual screen that corresponds to the preferred GPU by its registryID.
     // CGLSetVirtualScreen can then be used to tell OpenGL which GPU it should be using.
 
-    if (!contextObj || !preferredRendererID)
+    if (!contextObj || !preferredGPUID)
         return;
 
     GLint virtualScreenCount = 0;
@@ -178,16 +180,16 @@
     GLint firstAcceleratedScreen = -1;
 
     for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen) {
-        GLint rendererID = 0;
-        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFARendererID, &rendererID);
+        GLint displayMask = 0;
+        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask, &displayMask);
         ASSERT(error == kCGLNoError);
-        if (error != kCGLNoError)
-            continue;
 
-        if (rendererID == preferredRendererID) {
+        auto gpuID = gpuIDForDisplayMask(displayMask);
+
+        if (gpuID == preferredGPUID) {
             error = CGLSetVirtualScreen(contextObj, virtualScreen);
             ASSERT(error == kCGLNoError);
-            LOG(WebGL, "Context (%p) set to GPU renderer (%d).", contextObj, rendererID);
+            LOG(WebGL, "Context (%p) set to GPU with ID: (%lld).", contextObj, gpuID);
             return;
         }
 
@@ -200,15 +202,46 @@
         }
     }
 
-    // No renderer match found; set to first hardware-accelerated virtual screen.
+    // No registryID match found; set to first hardware-accelerated virtual screen.
     if (firstAcceleratedScreen >= 0) {
         error = CGLSetVirtualScreen(contextObj, firstAcceleratedScreen);
         ASSERT(error == kCGLNoError);
-        LOG(WebGL, "Renderer (%d) not matched; Context (%p) set to virtual screen (%d).", preferredRendererID, contextObj, firstAcceleratedScreen);
+        LOG(WebGL, "RegistryID (%lld) not matched; Context (%p) set to virtual screen (%d).", preferredGPUID, contextObj, firstAcceleratedScreen);
     }
 }
+#else // __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
+static void setGPUByDisplayMask(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, uint32_t preferredDisplayMask)
+{
+    // A common case for multiple GPUs, external GPUs, is not supported before macOS 10.13.4.
+    // In the rarer case where there are still multiple displays plugged into multiple GPUs, this should still work.
+    // See code example at https://developer.apple.com/library/content/technotes/tn2229/_index.html#//apple_ref/doc/uid/DTS40008924-CH1-SUBSECTION7
+    // FIXME: Window server is not blocked before 10.14. There might be a more straightforward way to detect the correct GPU.
+
+    if (!contextObj || !preferredDisplayMask)
+        return;
+
+    GLint virtualScreenCount = 0;
+    CGLError error = CGLDescribePixelFormat(pixelFormatObj, 0, kCGLPFAVirtualScreenCount, &virtualScreenCount);
+    ASSERT(error == kCGLNoError);
+
+    for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen) {
+        GLint displayMask = 0;
+        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask, &displayMask);
+        ASSERT(error == kCGLNoError);
+        if (error != kCGLNoError)
+            continue;
+
+        if (displayMask & preferredDisplayMask) {
+            error = CGLSetVirtualScreen(contextObj, virtualScreen);
+            ASSERT(error == kCGLNoError);
+            return;
+        }
+    }
+}
 #endif
 
+#endif // !PLATFORM(MAC)
+
 GraphicsContext3D::GraphicsContext3D(GraphicsContext3DAttributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle, GraphicsContext3D* sharedContext)
     : m_attrs(attrs)
 #if PLATFORM(IOS)
@@ -278,12 +311,22 @@
     CGLSetParameter(m_contextObj, kCGLCPAbortOnGPURestartStatusBlacklisted, &abortOnBlacklist);
     
 #if PLATFORM(MAC)
-    GLint rendererID = (hostWindow && hostWindow->displayID()) ? rendererIDForDisplay(hostWindow->displayID()) : primaryRendererID();
-    identifyAndSetCurrentGPU(m_contextObj, pixelFormatObj, rendererID);
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+    auto gpuID = (hostWindow && hostWindow->displayID()) ? gpuIDForDisplay(hostWindow->displayID()) : primaryGPUID();
+    setGPUByRegistryID(m_contextObj, pixelFormatObj, gpuID);
 #else
-    UNUSED_PARAM(hostWindow);
+    if (auto displayMask = primaryOpenGLDisplayMask()) {
+        if (hostWindow && hostWindow->displayID())
+            displayMask = displayMaskForDisplay(hostWindow->displayID());
+        setGPUByDisplayMask(m_contextObj, pixelFormatObj, displayMask);
+    }
 #endif
 
+#else
+    UNUSED_PARAM(hostWindow);
+#endif // !PLATFORM(MAC)
+
     CGLDestroyPixelFormat(pixelFormatObj);
     
     if (err != kCGLNoError || !m_contextObj) {
@@ -603,10 +646,13 @@
 {
     if (!m_contextObj)
         return;
-
-    identifyAndSetCurrentGPU(m_contextObj, CGLGetPixelFormat(m_contextObj), rendererIDForDisplay(displayID));
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+    setGPUByRegistryID(m_contextObj, CGLGetPixelFormat(m_contextObj), gpuIDForDisplay(displayID));
+#else
+    setGPUByDisplayMask(m_contextObj, CGLGetPixelFormat(m_contextObj), displayMaskForDisplay(displayID));
+#endif
 }
-#endif
+#endif // !PLATFORM(MAC)
 
 }
 

Modified: trunk/Source/WebCore/platform/mac/PlatformScreenMac.mm (234376 => 234377)


--- trunk/Source/WebCore/platform/mac/PlatformScreenMac.mm	2018-07-30 19:37:42 UTC (rev 234376)
+++ trunk/Source/WebCore/platform/mac/PlatformScreenMac.mm	2018-07-30 19:52:51 UTC (rev 234377)
@@ -107,26 +107,6 @@
     return screenProperties().primaryDisplayID;
 }
 
-static GLint rendererIDForDisplayMask(GLuint displayMask)
-{
-    GLint numRenderers;
-    CGLRendererInfoObj rendererInfo;
-    CGLError error = CGLQueryRendererInfo(displayMask, &rendererInfo, &numRenderers);
-    ASSERT(error == kCGLNoError);
-
-    GLint rendererID;
-    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRendererID, &rendererID);
-    ASSERT(error == kCGLNoError);
-
-    // The 0th renderer should not be the software renderer.
-    GLint isAccelerated;
-    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPAccelerated, &isAccelerated);
-    ASSERT(error == kCGLNoError);
-    ASSERT(isAccelerated);
-
-    return rendererID;
-}
-
 ScreenProperties collectScreenProperties()
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
@@ -147,10 +127,14 @@
         bool screenHasInvertedColors = CGDisplayUsesInvertedPolarity();
         bool screenIsMonochrome = CGDisplayUsesForceToGray();
         uint32_t displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
-        GLint rendererID = rendererIDForDisplayMask(displayMask);
+        IORegistryGPUID gpuID = 0;
 
-        screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask, rendererID });
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+        gpuID = gpuIDForDisplayMask(displayMask);
+#endif
 
+        screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask, gpuID });
+
         if (!screenProperties.primaryDisplayID)
             screenProperties.primaryDisplayID = displayID;
     }
@@ -196,21 +180,47 @@
     return 0;
 }
 
-GLint rendererIDForDisplay(PlatformDisplayID displayID)
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
+IORegistryGPUID primaryGPUID()
 {
+    return gpuIDForDisplay(screenProperties().primaryDisplayID);
+}
+
+IORegistryGPUID gpuIDForDisplay(PlatformDisplayID displayID)
+{
 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
     if (!screenProperties().screenDataMap.isEmpty())
-        return screenData(displayID).rendererID;
+        return screenData(displayID).gpuID;
 #else
-    return rendererIDForDisplayMask(CGDisplayIDToOpenGLDisplayMask(displayID));
+    return gpuIDForDisplayMask(CGDisplayIDToOpenGLDisplayMask(displayID));
 #endif
     return 0;
 }
 
-GLint primaryRendererID()
+IORegistryGPUID gpuIDForDisplayMask(GLuint displayMask)
 {
-    return rendererIDForDisplay(screenProperties().primaryDisplayID);
+    GLint numRenderers;
+    CGLRendererInfoObj rendererInfo;
+    CGLError error = CGLQueryRendererInfo(displayMask, &rendererInfo, &numRenderers);
+    ASSERT(error == kCGLNoError);
+
+    // The 0th renderer should not be the software renderer.
+    GLint isAccelerated;
+    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPAccelerated, &isAccelerated);
+    ASSERT(error == kCGLNoError);
+    ASSERT(isAccelerated);
+
+    GLint gpuIDLow;
+    GLint gpuIDHigh;
+
+    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDLow, &gpuIDLow);
+    ASSERT(error == kCGLNoError);
+    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDHigh, &gpuIDHigh);
+    ASSERT(error == kCGLNoError);
+
+    return (IORegistryGPUID) gpuIDHigh << 32 | gpuIDLow;
 }
+#endif // !__MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
 
 static ScreenData getScreenProperties(Widget* widget)
 {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to