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)
{