Changeset 234377 in webkit


Ignore:
Timestamp:
Jul 30, 2018, 12:52:51 PM (7 years ago)
Author:
commit-queue@webkit.org
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 <Justin Fan> 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.

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r234376 r234377  
     12018-07-30  Justin Fan  <justin_fan@apple.com>
     2
     3        Match GraphicsContext3D with correct virtual screen using registryID
     4        https://bugs.webkit.org/show_bug.cgi?id=188072
     5        <rdar://problem/42634940>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Follow up to https://bugs.webkit.org/show_bug.cgi?id=187750. Rather than matching rendererIDs,
     10        which can vary between processes, match GPU to display using registryID that is unique to a GPU,
     11        which was added to CGL in MacOS 10.13.
     12
     13        No new tests. Manually tested on MacBookPro13,3 and iMacPro1,1 with Apple DisplayPort Cinema Display
     14        and RX 580 external GPU.
     15
     16        * platform/PlatformScreen.h:
     17        * platform/ScreenProperties.h:
     18        (WebCore::ScreenData::encode const):
     19        (WebCore::ScreenData::decode):
     20        * platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
     21        (WebCore::setGPUByRegistryID):
     22        (WebCore::setGPUByDisplayMask):
     23        (WebCore::GraphicsContext3D::GraphicsContext3D):
     24        (WebCore::GraphicsContext3D::screenDidChange):
     25        (WebCore::identifyAndSetCurrentGPU): Deleted.
     26        * platform/mac/PlatformScreenMac.mm:
     27        (WebCore::collectScreenProperties):
     28        (WebCore::primaryRegistryID):
     29        (WebCore::registryIDForDisplay):
     30        (WebCore::registryIDForDisplayMask):
     31        (WebCore::rendererIDForDisplayMask): Deleted.
     32        (WebCore::rendererIDForDisplay): Deleted.
     33        (WebCore::primaryRendererID): Deleted.
     34
    1352018-07-30  Rob Buis  <rbuis@igalia.com>
    236
  • trunk/Source/WebCore/platform/PlatformScreen.h

    r234074 r234377  
    5959
    6060using PlatformDisplayID = uint32_t;
     61using IORegistryGPUID = int64_t; // Global IOKit I/O registryID that can match a GPU across process boundaries.
    6162
    6263int screenDepth(Widget*);
     
    101102uint32_t primaryOpenGLDisplayMask();
    102103uint32_t displayMaskForDisplay(PlatformDisplayID);
    103 int32_t rendererIDForDisplay(PlatformDisplayID);
    104 int32_t primaryRendererID();
     104
     105#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     106IORegistryGPUID primaryGPUID();
     107IORegistryGPUID gpuIDForDisplay(PlatformDisplayID);
     108IORegistryGPUID gpuIDForDisplayMask(uint32_t);
    105109#endif
     110
     111#endif // !PLATFORM(MAC)
    106112
    107113#if PLATFORM(IOS)
  • trunk/Source/WebCore/platform/ScreenProperties.h

    r234074 r234377  
    4747    bool screenIsMonochrome { false };
    4848    uint32_t displayMask { 0 };
    49     int32_t rendererID { 0 };
     49    IORegistryGPUID gpuID { 0 };
    5050
    5151    enum EncodedColorSpaceDataType {
     
    9595void ScreenData::encode(Encoder& encoder) const
    9696{
    97     encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask << rendererID;
     97    encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask << gpuID;
    9898
    9999    if (colorSpace) {
     
    164164        return std::nullopt;
    165165
    166     std::optional<int32_t> rendererID;
    167     decoder >> rendererID;
    168     if (!rendererID)
     166    std::optional<IORegistryGPUID> gpuID;
     167    decoder >> gpuID;
     168    if (!gpuID)
    169169        return std::nullopt;
    170170   
     
    204204    }
    205205
    206     return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask), WTFMove(*rendererID) } };
     206    return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask), WTFMove(*gpuID) } };
    207207}
    208208
  • trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm

    r234117 r234377  
    163163
    164164#if PLATFORM(MAC)
    165 static void identifyAndSetCurrentGPU(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, GLint preferredRendererID)
    166 {
    167     // 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.
    168     // Find the virtual screen that corresponds to the preferred renderer.
     165
     166#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     167static void setGPUByRegistryID(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, IORegistryGPUID preferredGPUID)
     168{
     169    // 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.
     170    // On 10.13+, find the virtual screen that corresponds to the preferred GPU by its registryID.
    169171    // CGLSetVirtualScreen can then be used to tell OpenGL which GPU it should be using.
    170172
    171     if (!contextObj || !preferredRendererID)
     173    if (!contextObj || !preferredGPUID)
    172174        return;
    173175
     
    179181
    180182    for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen) {
    181         GLint rendererID = 0;
    182         error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFARendererID, &rendererID);
     183        GLint displayMask = 0;
     184        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask, &displayMask);
    183185        ASSERT(error == kCGLNoError);
    184         if (error != kCGLNoError)
    185             continue;
    186 
    187         if (rendererID == preferredRendererID) {
     186
     187        auto gpuID = gpuIDForDisplayMask(displayMask);
     188
     189        if (gpuID == preferredGPUID) {
    188190            error = CGLSetVirtualScreen(contextObj, virtualScreen);
    189191            ASSERT(error == kCGLNoError);
    190             LOG(WebGL, "Context (%p) set to GPU renderer (%d).", contextObj, rendererID);
     192            LOG(WebGL, "Context (%p) set to GPU with ID: (%lld).", contextObj, gpuID);
    191193            return;
    192194        }
     
    201203    }
    202204
    203     // No renderer match found; set to first hardware-accelerated virtual screen.
     205    // No registryID match found; set to first hardware-accelerated virtual screen.
    204206    if (firstAcceleratedScreen >= 0) {
    205207        error = CGLSetVirtualScreen(contextObj, firstAcceleratedScreen);
    206208        ASSERT(error == kCGLNoError);
    207         LOG(WebGL, "Renderer (%d) not matched; Context (%p) set to virtual screen (%d).", preferredRendererID, contextObj, firstAcceleratedScreen);
    208     }
    209 }
    210 #endif
     209        LOG(WebGL, "RegistryID (%lld) not matched; Context (%p) set to virtual screen (%d).", preferredGPUID, contextObj, firstAcceleratedScreen);
     210    }
     211}
     212#else // __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
     213static void setGPUByDisplayMask(PlatformGraphicsContext3D contextObj, CGLPixelFormatObj pixelFormatObj, uint32_t preferredDisplayMask)
     214{
     215    // A common case for multiple GPUs, external GPUs, is not supported before macOS 10.13.4.
     216    // In the rarer case where there are still multiple displays plugged into multiple GPUs, this should still work.
     217    // See code example at https://developer.apple.com/library/content/technotes/tn2229/_index.html#//apple_ref/doc/uid/DTS40008924-CH1-SUBSECTION7
     218    // FIXME: Window server is not blocked before 10.14. There might be a more straightforward way to detect the correct GPU.
     219
     220    if (!contextObj || !preferredDisplayMask)
     221        return;
     222
     223    GLint virtualScreenCount = 0;
     224    CGLError error = CGLDescribePixelFormat(pixelFormatObj, 0, kCGLPFAVirtualScreenCount, &virtualScreenCount);
     225    ASSERT(error == kCGLNoError);
     226
     227    for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen) {
     228        GLint displayMask = 0;
     229        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask, &displayMask);
     230        ASSERT(error == kCGLNoError);
     231        if (error != kCGLNoError)
     232            continue;
     233
     234        if (displayMask & preferredDisplayMask) {
     235            error = CGLSetVirtualScreen(contextObj, virtualScreen);
     236            ASSERT(error == kCGLNoError);
     237            return;
     238        }
     239    }
     240}
     241#endif
     242
     243#endif // !PLATFORM(MAC)
    211244
    212245GraphicsContext3D::GraphicsContext3D(GraphicsContext3DAttributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle, GraphicsContext3D* sharedContext)
     
    279312   
    280313#if PLATFORM(MAC)
    281     GLint rendererID = (hostWindow && hostWindow->displayID()) ? rendererIDForDisplay(hostWindow->displayID()) : primaryRendererID();
    282     identifyAndSetCurrentGPU(m_contextObj, pixelFormatObj, rendererID);
     314
     315#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     316    auto gpuID = (hostWindow && hostWindow->displayID()) ? gpuIDForDisplay(hostWindow->displayID()) : primaryGPUID();
     317    setGPUByRegistryID(m_contextObj, pixelFormatObj, gpuID);
     318#else
     319    if (auto displayMask = primaryOpenGLDisplayMask()) {
     320        if (hostWindow && hostWindow->displayID())
     321            displayMask = displayMaskForDisplay(hostWindow->displayID());
     322        setGPUByDisplayMask(m_contextObj, pixelFormatObj, displayMask);
     323    }
     324#endif
     325
    283326#else
    284327    UNUSED_PARAM(hostWindow);
    285 #endif
     328#endif // !PLATFORM(MAC)
    286329
    287330    CGLDestroyPixelFormat(pixelFormatObj);
     
    604647    if (!m_contextObj)
    605648        return;
    606 
    607     identifyAndSetCurrentGPU(m_contextObj, CGLGetPixelFormat(m_contextObj), rendererIDForDisplay(displayID));
    608 }
    609 #endif
     649#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     650    setGPUByRegistryID(m_contextObj, CGLGetPixelFormat(m_contextObj), gpuIDForDisplay(displayID));
     651#else
     652    setGPUByDisplayMask(m_contextObj, CGLGetPixelFormat(m_contextObj), displayMaskForDisplay(displayID));
     653#endif
     654}
     655#endif // !PLATFORM(MAC)
    610656
    611657}
  • trunk/Source/WebCore/platform/mac/PlatformScreenMac.mm

    r234224 r234377  
    108108}
    109109
    110 static GLint rendererIDForDisplayMask(GLuint displayMask)
    111 {
    112     GLint numRenderers;
    113     CGLRendererInfoObj rendererInfo;
    114     CGLError error = CGLQueryRendererInfo(displayMask, &rendererInfo, &numRenderers);
    115     ASSERT(error == kCGLNoError);
    116 
    117     GLint rendererID;
    118     error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRendererID, &rendererID);
    119     ASSERT(error == kCGLNoError);
    120 
    121     // The 0th renderer should not be the software renderer.
    122     GLint isAccelerated;
    123     error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPAccelerated, &isAccelerated);
    124     ASSERT(error == kCGLNoError);
    125     ASSERT(isAccelerated);
    126 
    127     return rendererID;
    128 }
    129 
    130110ScreenProperties collectScreenProperties()
    131111{
     
    148128        bool screenIsMonochrome = CGDisplayUsesForceToGray();
    149129        uint32_t displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
    150         GLint rendererID = rendererIDForDisplayMask(displayMask);
    151 
    152         screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask, rendererID });
     130        IORegistryGPUID gpuID = 0;
     131
     132#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     133        gpuID = gpuIDForDisplayMask(displayMask);
     134#endif
     135
     136        screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask, gpuID });
    153137
    154138        if (!screenProperties.primaryDisplayID)
     
    197181}
    198182
    199 GLint rendererIDForDisplay(PlatformDisplayID displayID)
     183#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
     184IORegistryGPUID primaryGPUID()
     185{
     186    return gpuIDForDisplay(screenProperties().primaryDisplayID);
     187}
     188
     189IORegistryGPUID gpuIDForDisplay(PlatformDisplayID displayID)
    200190{
    201191#if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
    202192    if (!screenProperties().screenDataMap.isEmpty())
    203         return screenData(displayID).rendererID;
     193        return screenData(displayID).gpuID;
    204194#else
    205     return rendererIDForDisplayMask(CGDisplayIDToOpenGLDisplayMask(displayID));
     195    return gpuIDForDisplayMask(CGDisplayIDToOpenGLDisplayMask(displayID));
    206196#endif
    207197    return 0;
    208198}
    209199
    210 GLint primaryRendererID()
    211 {
    212     return rendererIDForDisplay(screenProperties().primaryDisplayID);
    213 }
     200IORegistryGPUID gpuIDForDisplayMask(GLuint displayMask)
     201{
     202    GLint numRenderers;
     203    CGLRendererInfoObj rendererInfo;
     204    CGLError error = CGLQueryRendererInfo(displayMask, &rendererInfo, &numRenderers);
     205    ASSERT(error == kCGLNoError);
     206
     207    // The 0th renderer should not be the software renderer.
     208    GLint isAccelerated;
     209    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPAccelerated, &isAccelerated);
     210    ASSERT(error == kCGLNoError);
     211    ASSERT(isAccelerated);
     212
     213    GLint gpuIDLow;
     214    GLint gpuIDHigh;
     215
     216    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDLow, &gpuIDLow);
     217    ASSERT(error == kCGLNoError);
     218    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDHigh, &gpuIDHigh);
     219    ASSERT(error == kCGLNoError);
     220
     221    return (IORegistryGPUID) gpuIDHigh << 32 | gpuIDLow;
     222}
     223#endif // !__MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
    214224
    215225static ScreenData getScreenProperties(Widget* widget)
Note: See TracChangeset for help on using the changeset viewer.