Changeset 234074 in webkit


Ignore:
Timestamp:
Jul 20, 2018 4:43:01 PM (6 years ago)
Author:
commit-queue@webkit.org
Message:

Safari WebGL does not consistently provide correct GPU context on eGPU systems
https://bugs.webkit.org/show_bug.cgi?id=187750
<rdar://problem/39531436>

Patch by Justin Fan <Justin Fan> on 2018-07-20
Reviewed by Dean Jackson.

Move GraphicsContext3DManager into its own class, and notify it when page/Chrome receives a
windowScreenDidChange message. Add a private data struct to track which hostWindow created each context.
Upon notification, Manager updates the contexts that match the hostWindow with the
provided displayID. Each context matches displayID to rendererID (set during process creation
if window server is blocked), which is matched to a virtual screen, and updates its GPU accordingly.

No new tests. This requires multiple GPUs or eGPUs, each with attached display(s), to test.

  • WebCore.xcodeproj/project.pbxproj:
  • page/Chrome.cpp:

(WebCore::Chrome::windowScreenDidChange): Now calls GraphicsContext3DManager::screenDidChange().

  • platform/PlatformScreen.h:
  • platform/ScreenProperties.h: Add rendererID to struct.

(WebCore::ScreenData::encode const):
(WebCore::ScreenData::decode):

  • platform/graphics/GraphicsContext3D.h:
  • platform/graphics/GraphicsContext3DManager.cpp: Added (copied out of GraphicsContext3DCocoa.mm).

(WebCore::attachToAppleGraphicsControl):
(WebCore::hasMuxCapability):
(WebCore::hasMuxableGPU):
(WebCore::GraphicsContext3DManager::sharedManager):
(WebCore::displayWasReconfigured):
(WebCore::GraphicsContext3DManager::updateAllContexts):
(WebCore::GraphicsContext3DManager::screenDidChange):
(WebCore::GraphicsContext3DManager::addContext):
(WebCore::GraphicsContext3DManager::removeContext):
(WebCore::GraphicsContext3DManager::hostWindowForContext const):
(WebCore::GraphicsContext3DManager::addContextRequiringHighPerformance):
(WebCore::GraphicsContext3DManager::removeContextRequiringHighPerformance):
(WebCore::GraphicsContext3DManager::updateHighPerformanceState):
(WebCore::GraphicsContext3DManager::disableHighPerformanceGPUTimerFired):
(WebCore::GraphicsContext3DManager::recycleContextIfNecessary):

  • platform/graphics/GraphicsContext3DManager.h: Added (copied out of GraphicsContext3DCocoa.mm).

(WebCore::GraphicsContext3DManager::hasTooManyContexts const):
(WebCore::GraphicsContext3DManager::GraphicsContext3DManager):

  • platform/graphics/cocoa/GraphicsContext3DCocoa.mm:

(WebCore::GraphicsContext3D::create):
(WebCore::GraphicsContext3D::createShared):
(WebCore::identifyAndSetCurrentGPU): Now matches rendererIDs to determine virtual screen.
(WebCore::GraphicsContext3D::GraphicsContext3D):
(WebCore::GraphicsContext3D::~GraphicsContext3D):
(WebCore::GraphicsContext3D::setContextVisibility):
(WebCore::GraphicsContext3D::simulateContextChanged):
(WebCore::GraphicsContext3D::screenDidChange):
(WebCore::attachToAppleGraphicsControl): Deleted.
(WebCore::hasMuxCapability): Deleted.
(WebCore::hasMuxableGPU): Deleted.
(WebCore::GraphicsContext3DManager::GraphicsContext3DManager): Deleted.
(WebCore::GraphicsContext3DManager::hasTooManyContexts const): Deleted.
(WebCore::manager): Deleted.
(WebCore::displayWasReconfigured): Deleted.
(WebCore::GraphicsContext3DManager::updateAllContexts): Deleted.
(WebCore::GraphicsContext3DManager::addContext): Deleted.
(WebCore::GraphicsContext3DManager::removeContext): Deleted.
(WebCore::GraphicsContext3DManager::addContextRequiringHighPerformance): Deleted.
(WebCore::GraphicsContext3DManager::removeContextRequiringHighPerformance): Deleted.
(WebCore::GraphicsContext3DManager::updateHighPerformanceState): Deleted.
(WebCore::GraphicsContext3DManager::disableHighPerformanceGPUTimerFired): Deleted.
(WebCore::GraphicsContext3DManager::recycleContextIfNecessary): Deleted.

  • platform/mac/PlatformScreenMac.mm: Provide a display's rendererID.

(WebCore::rendererIDForDisplayMask):
(WebCore::collectScreenProperties):
(WebCore::rendererIDForDisplay):
(WebCore::primaryRendererID):

Location:
trunk/Source/WebCore
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r234073 r234074  
     12018-07-20  Justin Fan  <justin_fan@apple.com>
     2
     3        Safari WebGL does not consistently provide correct GPU context on eGPU systems
     4        https://bugs.webkit.org/show_bug.cgi?id=187750
     5        <rdar://problem/39531436>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Move GraphicsContext3DManager into its own class, and notify it when page/Chrome receives a
     10        windowScreenDidChange message. Add a private data struct to track which hostWindow created each context.
     11        Upon notification, Manager updates the contexts that match the hostWindow with the
     12        provided displayID. Each context matches displayID to rendererID (set during process creation
     13        if window server is blocked), which is matched to a virtual screen, and updates its GPU accordingly.
     14
     15        No new tests. This requires multiple GPUs or eGPUs, each with attached display(s), to test.
     16
     17        * WebCore.xcodeproj/project.pbxproj:
     18        * page/Chrome.cpp:
     19        (WebCore::Chrome::windowScreenDidChange): Now calls GraphicsContext3DManager::screenDidChange().
     20        * platform/PlatformScreen.h:
     21        * platform/ScreenProperties.h: Add rendererID to struct.
     22        (WebCore::ScreenData::encode const):
     23        (WebCore::ScreenData::decode):
     24        * platform/graphics/GraphicsContext3D.h:
     25        * platform/graphics/GraphicsContext3DManager.cpp: Added (copied out of GraphicsContext3DCocoa.mm).
     26        (WebCore::attachToAppleGraphicsControl):
     27        (WebCore::hasMuxCapability):
     28        (WebCore::hasMuxableGPU):
     29        (WebCore::GraphicsContext3DManager::sharedManager):
     30        (WebCore::displayWasReconfigured):
     31        (WebCore::GraphicsContext3DManager::updateAllContexts):
     32        (WebCore::GraphicsContext3DManager::screenDidChange):
     33        (WebCore::GraphicsContext3DManager::addContext):
     34        (WebCore::GraphicsContext3DManager::removeContext):
     35        (WebCore::GraphicsContext3DManager::hostWindowForContext const):
     36        (WebCore::GraphicsContext3DManager::addContextRequiringHighPerformance):
     37        (WebCore::GraphicsContext3DManager::removeContextRequiringHighPerformance):
     38        (WebCore::GraphicsContext3DManager::updateHighPerformanceState):
     39        (WebCore::GraphicsContext3DManager::disableHighPerformanceGPUTimerFired):
     40        (WebCore::GraphicsContext3DManager::recycleContextIfNecessary):
     41        * platform/graphics/GraphicsContext3DManager.h: Added (copied out of GraphicsContext3DCocoa.mm).
     42        (WebCore::GraphicsContext3DManager::hasTooManyContexts const):
     43        (WebCore::GraphicsContext3DManager::GraphicsContext3DManager):
     44        * platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
     45        (WebCore::GraphicsContext3D::create):
     46        (WebCore::GraphicsContext3D::createShared):
     47        (WebCore::identifyAndSetCurrentGPU): Now matches rendererIDs to determine virtual screen.
     48        (WebCore::GraphicsContext3D::GraphicsContext3D):
     49        (WebCore::GraphicsContext3D::~GraphicsContext3D):
     50        (WebCore::GraphicsContext3D::setContextVisibility):
     51        (WebCore::GraphicsContext3D::simulateContextChanged):
     52        (WebCore::GraphicsContext3D::screenDidChange):
     53        (WebCore::attachToAppleGraphicsControl): Deleted.
     54        (WebCore::hasMuxCapability): Deleted.
     55        (WebCore::hasMuxableGPU): Deleted.
     56        (WebCore::GraphicsContext3DManager::GraphicsContext3DManager): Deleted.
     57        (WebCore::GraphicsContext3DManager::hasTooManyContexts const): Deleted.
     58        (WebCore::manager): Deleted.
     59        (WebCore::displayWasReconfigured): Deleted.
     60        (WebCore::GraphicsContext3DManager::updateAllContexts): Deleted.
     61        (WebCore::GraphicsContext3DManager::addContext): Deleted.
     62        (WebCore::GraphicsContext3DManager::removeContext): Deleted.
     63        (WebCore::GraphicsContext3DManager::addContextRequiringHighPerformance): Deleted.
     64        (WebCore::GraphicsContext3DManager::removeContextRequiringHighPerformance): Deleted.
     65        (WebCore::GraphicsContext3DManager::updateHighPerformanceState): Deleted.
     66        (WebCore::GraphicsContext3DManager::disableHighPerformanceGPUTimerFired): Deleted.
     67        (WebCore::GraphicsContext3DManager::recycleContextIfNecessary): Deleted.
     68        * platform/mac/PlatformScreenMac.mm: Provide a display's rendererID.
     69        (WebCore::rendererIDForDisplayMask):
     70        (WebCore::collectScreenProperties):
     71        (WebCore::rendererIDForDisplay):
     72        (WebCore::primaryRendererID):
     73
    1742018-07-19  Simon Fraser  <simon.fraser@apple.com>
    275
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r234000 r234074  
    41244124                D06C0D8F0CFD11460065F43F /* RemoveFormatCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C0D8D0CFD11460065F43F /* RemoveFormatCommand.h */; };
    41254125                D07DEABA0A36554A00CA30F8 /* InsertListCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */; };
     4126                D0843A4B20FEBE3D00FE860E /* GraphicsContext3DManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D0843A4A20FEBE3D00FE860E /* GraphicsContext3DManager.h */; };
     4127                D0843A4D20FEC16500FE860E /* GraphicsContext3DManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0843A4C20FEC16500FE860E /* GraphicsContext3DManager.cpp */; };
    41264128                D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D086FE9609D53AAB005BC74D /* UnlinkCommand.h */; };
    41274129                D08B00E220A282490004BC0A /* WebGLCompressedTextureASTC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A20D562092A0A600E0C259 /* WebGLCompressedTextureASTC.cpp */; };
     
    1354213544                D07DEAB70A36554A00CA30F8 /* InsertListCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InsertListCommand.cpp; sourceTree = "<group>"; };
    1354313545                D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InsertListCommand.h; sourceTree = "<group>"; };
     13546                D0843A4A20FEBE3D00FE860E /* GraphicsContext3DManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GraphicsContext3DManager.h; sourceTree = "<group>"; };
     13547                D0843A4C20FEC16500FE860E /* GraphicsContext3DManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DManager.cpp; sourceTree = "<group>"; };
    1354413548                D086FE9609D53AAB005BC74D /* UnlinkCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkCommand.h; sourceTree = "<group>"; };
    1354513549                D086FE9709D53AAB005BC74D /* UnlinkCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkCommand.cpp; sourceTree = "<group>"; };
     
    2364623650                                49C7B9FB1042D3650009D447 /* GraphicsContext3D.h */,
    2364723651                                7C330A011DF8FAC600D3395C /* GraphicsContext3DAttributes.h */,
     23652                                D0843A4C20FEC16500FE860E /* GraphicsContext3DManager.cpp */,
     23653                                D0843A4A20FEBE3D00FE860E /* GraphicsContext3DManager.h */,
    2364823654                                0F0012401FAD881000531D76 /* GraphicsContextImpl.cpp */,
    2364923655                                0F00123F1FAD87D600531D76 /* GraphicsContextImpl.h */,
     
    2808428090                                7C330A021DF8FAC600D3395C /* GraphicsContext3DAttributes.h in Headers */,
    2808528091                                31AB5000122878A2001A7DB0 /* GraphicsContext3DIOS.h in Headers */,
     28092                                D0843A4B20FEBE3D00FE860E /* GraphicsContext3DManager.h in Headers */,
    2808628093                                934907E4125BBBC8007F23A0 /* GraphicsContextCG.h in Headers */,
    2808728094                                A80D67080E9E9DEB00E420F0 /* GraphicsContextPlatformPrivateCG.h in Headers */,
     
    3147831485                                837964CF1F8DB69D00218EA0 /* GeolocationPositionIOS.mm in Sources */,
    3147931486                                6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */,
     31487                                D0843A4D20FEC16500FE860E /* GraphicsContext3DManager.cpp in Sources */,
    3148031488                                7C3E510B18DF8F3500C112F7 /* HTMLConverter.mm in Sources */,
    3148131489                                A8D06B3A0A265DCD005E7203 /* HTMLNames.cpp in Sources */,
  • trunk/Source/WebCore/page/Chrome.cpp

    r232640 r234074  
    6161#endif
    6262
     63#if PLATFORM(MAC) && ENABLE(GRAPHICS_CONTEXT_3D)
     64#include "GraphicsContext3DManager.h"
     65#endif
     66
    6367namespace WebCore {
    6468
     
    511515            frame->document()->windowScreenDidChange(displayID);
    512516    }
     517
     518#if PLATFORM(MAC) && ENABLE(GRAPHICS_CONTEXT_3D)
     519    GraphicsContext3DManager::sharedManager().screenDidChange(displayID, this);
     520#endif
     521
    513522}
    514523
  • trunk/Source/WebCore/platform/PlatformScreen.h

    r232535 r234074  
    101101uint32_t primaryOpenGLDisplayMask();
    102102uint32_t displayMaskForDisplay(PlatformDisplayID);
     103int32_t rendererIDForDisplay(PlatformDisplayID);
     104int32_t primaryRendererID();
    103105#endif
    104106
  • trunk/Source/WebCore/platform/ScreenProperties.h

    r232535 r234074  
    4747    bool screenIsMonochrome { false };
    4848    uint32_t displayMask { 0 };
     49    int32_t rendererID { 0 };
    4950
    5051    enum EncodedColorSpaceDataType {
     
    9495void ScreenData::encode(Encoder& encoder) const
    9596{
    96     encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask;
     97    encoder << screenAvailableRect << screenRect << screenDepth << screenDepthPerComponent << screenSupportsExtendedColor << screenHasInvertedColors << screenIsMonochrome << displayMask << rendererID;
    9798
    9899    if (colorSpace) {
     
    161162    decoder >> displayMask;
    162163    if (!displayMask)
     164        return std::nullopt;
     165
     166    std::optional<int32_t> rendererID;
     167    decoder >> rendererID;
     168    if (!rendererID)
    163169        return std::nullopt;
    164170   
     
    198204    }
    199205
    200     return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask) } };
     206    return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect), WTFMove(cgColorSpace), WTFMove(*screenDepth), WTFMove(*screenDepthPerComponent), WTFMove(*screenSupportsExtendedColor), WTFMove(*screenHasInvertedColors), WTFMove(*screenIsMonochrome), WTFMove(*displayMask), WTFMove(*rendererID) } };
    201207}
    202208
  • trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h

    r232535 r234074  
    12831283    unsigned textureSeed(GC3Duint texture) { return m_state.textureSeedCount.count(texture); }
    12841284
     1285#if PLATFORM(MAC)
     1286    using PlatformDisplayID = uint32_t;
     1287    void screenDidChange(PlatformDisplayID);
     1288#endif
     1289
    12851290private:
    12861291    GraphicsContext3D(GraphicsContext3DAttributes, HostWindow*, RenderStyle = RenderOffscreen, GraphicsContext3D* sharedContext = nullptr);
  • trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm

    r232535 r234074  
    3636#import "Extensions3DOpenGL.h"
    3737#import "GraphicsContext.h"
     38#import "GraphicsContext3DManager.h"
    3839#import "HTMLCanvasElement.h"
    3940#import "HostWindow.h"
     
    7071static const unsigned statusCheckThreshold = 5;
    7172
    72 #if HAVE(APPLE_GRAPHICS_CONTROL)
    73 
    74 enum {
    75     kAGCOpen,
    76     kAGCClose
    77 };
    78 
    79 static io_connect_t attachToAppleGraphicsControl()
    80 {
    81     mach_port_t masterPort = MACH_PORT_NULL;
    82 
    83     if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
    84         return MACH_PORT_NULL;
    85 
    86     CFDictionaryRef classToMatch = IOServiceMatching("AppleGraphicsControl");
    87     if (!classToMatch)
    88         return MACH_PORT_NULL;
    89 
    90     kern_return_t kernResult;
    91     io_iterator_t iterator;
    92     if ((kernResult = IOServiceGetMatchingServices(masterPort, classToMatch, &iterator)) != KERN_SUCCESS)
    93         return MACH_PORT_NULL;
    94 
    95     io_service_t serviceObject = IOIteratorNext(iterator);
    96     IOObjectRelease(iterator);
    97     if (!serviceObject)
    98         return MACH_PORT_NULL;
    99 
    100     io_connect_t dataPort;
    101     IOObjectRetain(serviceObject);
    102     kernResult = IOServiceOpen(serviceObject, mach_task_self(), 0, &dataPort);
    103     IOObjectRelease(serviceObject);
    104 
    105     return (kernResult == KERN_SUCCESS) ? dataPort : MACH_PORT_NULL;
    106 }
    107 
    108 static bool hasMuxCapability()
    109 {
    110     io_connect_t dataPort = attachToAppleGraphicsControl();
    111 
    112     if (dataPort == MACH_PORT_NULL)
    113         return false;
    114 
    115     bool result;
    116     if (IOConnectCallScalarMethod(dataPort, kAGCOpen, nullptr, 0, nullptr, nullptr) == KERN_SUCCESS) {
    117         IOConnectCallScalarMethod(dataPort, kAGCClose, nullptr, 0, nullptr, nullptr);
    118         result = true;
    119     } else
    120         result = false;
    121 
    122     IOServiceClose(dataPort);
    123 
    124     if (result) {
    125         // This is detecting Mac hardware with an Intel g575 GPU, which
    126         // we don't want to make available to muxing.
    127         // Based on information from Apple's OpenGL team, such devices
    128         // have four or fewer processors.
    129         // <rdar://problem/30060378>
    130         int names[2] = { CTL_HW, HW_NCPU };
    131         int cpuCount;
    132         size_t cpuCountLength = sizeof(cpuCount);
    133         sysctl(names, 2, &cpuCount, &cpuCountLength, nullptr, 0);
    134         result = cpuCount > 4;
    135     }
    136    
    137     return result;
    138 }
    139 
    140 static bool hasMuxableGPU()
    141 {
    142     static bool canMux = hasMuxCapability();
    143     return canMux;
    144 }
    145 #endif
    146 
    147 const unsigned MaxContexts = 16;
    148 
    149 class GraphicsContext3DManager {
    150 public:
    151     GraphicsContext3DManager()
    152         : m_disableHighPerformanceGPUTimer(*this, &GraphicsContext3DManager::disableHighPerformanceGPUTimerFired)
    153     {
    154     }
    155 
    156     void addContext(GraphicsContext3D*);
    157     void removeContext(GraphicsContext3D*);
    158 
    159     void addContextRequiringHighPerformance(GraphicsContext3D*);
    160     void removeContextRequiringHighPerformance(GraphicsContext3D*);
    161 
    162     void recycleContextIfNecessary();
    163     bool hasTooManyContexts() const { return m_contexts.size() >= MaxContexts; }
    164 
    165     void updateAllContexts();
    166 
    167 private:
    168     void updateHighPerformanceState();
    169     void disableHighPerformanceGPUTimerFired();
    170 
    171     Vector<GraphicsContext3D*> m_contexts;
    172     HashSet<GraphicsContext3D*> m_contextsRequiringHighPerformance;
    173 
    174     Timer m_disableHighPerformanceGPUTimer;
    175 
    176 #if PLATFORM(MAC)
    177     CGLPixelFormatObj m_pixelFormatObj { nullptr };
    178 #endif
    179 };
    180 
    181 static GraphicsContext3DManager& manager()
    182 {
    183     static NeverDestroyed<GraphicsContext3DManager> s_manager;
    184     return s_manager;
    185 }
    186 
    187 #if PLATFORM(MAC)
    188 static void displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void*)
    189 {
    190     if (flags & kCGDisplaySetModeFlag)
    191         manager().updateAllContexts();
    192 }
    193 #endif
    194 
    195 void GraphicsContext3DManager::updateAllContexts()
    196 {
    197 #if PLATFORM(MAC)
    198     for (auto* context : m_contexts) {
    199         context->updateCGLContext();
    200         context->dispatchContextChangedNotification();
    201     }
    202 #endif
    203 }
    204 
    205 void GraphicsContext3DManager::addContext(GraphicsContext3D* context)
    206 {
    207     ASSERT(context);
    208     if (!context)
    209         return;
    210 
    211 #if PLATFORM(MAC)
    212     if (!m_contexts.size())
    213         CGDisplayRegisterReconfigurationCallback(displayWasReconfigured, nullptr);
    214 #endif
    215 
    216     ASSERT(!m_contexts.contains(context));
    217     m_contexts.append(context);
    218 }
    219 
    220 void GraphicsContext3DManager::removeContext(GraphicsContext3D* context)
    221 {
    222     ASSERT(m_contexts.contains(context));
    223     m_contexts.removeFirst(context);
    224     removeContextRequiringHighPerformance(context);
    225 
    226 #if PLATFORM(MAC)
    227     if (!m_contexts.size())
    228         CGDisplayRemoveReconfigurationCallback(displayWasReconfigured, nullptr);
    229 #endif
    230 }
    231 
    232 void GraphicsContext3DManager::addContextRequiringHighPerformance(GraphicsContext3D* context)
    233 {
    234     ASSERT(context);
    235     if (!context)
    236         return;
    237 
    238     ASSERT(m_contexts.contains(context));
    239     ASSERT(!m_contextsRequiringHighPerformance.contains(context));
    240 
    241     LOG(WebGL, "This context (%p) requires the high-performance GPU.", context);
    242     m_contextsRequiringHighPerformance.add(context);
    243 
    244     updateHighPerformanceState();
    245 }
    246 
    247 void GraphicsContext3DManager::removeContextRequiringHighPerformance(GraphicsContext3D* context)
    248 {
    249     if (!m_contextsRequiringHighPerformance.contains(context))
    250         return;
    251 
    252     LOG(WebGL, "This context (%p) no longer requires the high-performance GPU.", context);
    253     m_contextsRequiringHighPerformance.remove(context);
    254 
    255     updateHighPerformanceState();
    256 }
    257 
    258 void GraphicsContext3DManager::updateHighPerformanceState()
    259 {
    260 #if PLATFORM(MAC)
    261     if (!hasMuxableGPU())
    262         return;
    263 
    264     if (m_contextsRequiringHighPerformance.size()) {
    265 
    266         if (m_disableHighPerformanceGPUTimer.isActive()) {
    267             LOG(WebGL, "Cancel pending timer for turning off high-performance GPU.");
    268             m_disableHighPerformanceGPUTimer.stop();
    269         }
    270 
    271         if (!m_pixelFormatObj) {
    272             LOG(WebGL, "Turning on high-performance GPU.");
    273 
    274             CGLPixelFormatAttribute attributes[] = { kCGLPFAAccelerated, kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(32), static_cast<CGLPixelFormatAttribute>(0) };
    275             GLint numPixelFormats = 0;
    276             CGLChoosePixelFormat(attributes, &m_pixelFormatObj, &numPixelFormats);
    277         }
    278 
    279     } else if (m_pixelFormatObj) {
    280         // Don't immediately turn off the high-performance GPU. The user might be
    281         // swapping back and forth between tabs or windows, and we don't want to cause
    282         // churn if we can avoid it.
    283         if (!m_disableHighPerformanceGPUTimer.isActive()) {
    284             LOG(WebGL, "Set a timer to turn off high-performance GPU.");
    285             // FIXME: Expose this value as a Setting, which would require this class
    286             // to reference a frame, page or document.
    287             static const Seconds timeToKeepHighPerformanceGPUAlive { 10_s };
    288             m_disableHighPerformanceGPUTimer.startOneShot(timeToKeepHighPerformanceGPUAlive);
    289         }
    290     }
    291 #endif
    292 }
    293 
    294 void GraphicsContext3DManager::disableHighPerformanceGPUTimerFired()
    295 {
    296 #if PLATFORM(MAC)
    297     if (!m_contextsRequiringHighPerformance.size() && m_pixelFormatObj) {
    298         LOG(WebGL, "Turning off high-performance GPU.");
    299         CGLReleasePixelFormat(m_pixelFormatObj);
    300         m_pixelFormatObj = nullptr;
    301     }
    302 #endif
    303 }
    304 
    305 void GraphicsContext3DManager::recycleContextIfNecessary()
    306 {
    307     if (hasTooManyContexts()) {
    308         LOG(WebGL, "Manager recycled context (%p).", m_contexts.at(0));
    309         m_contexts.at(0)->recycleContext();
    310     }
    311 }
    312 
    31373// FIXME: This class is currently empty on Mac, but will get populated as
    31474// the restructuring in https://bugs.webkit.org/show_bug.cgi?id=66903 is done
     
    378138
    379139    // Make space for the incoming context if we're full.
    380     manager().recycleContextIfNecessary();
    381     if (manager().hasTooManyContexts())
     140    GraphicsContext3DManager::sharedManager().recycleContextIfNecessary();
     141    if (GraphicsContext3DManager::sharedManager().hasTooManyContexts())
    382142        return nullptr;
    383143
     
    387147        return nullptr;
    388148
    389     manager().addContext(context.get());
     149    GraphicsContext3DManager::sharedManager().addContext(context.get(), hostWindow);
    390150
    391151    return context;
     
    394154Ref<GraphicsContext3D> GraphicsContext3D::createShared(GraphicsContext3D& sharedContext)
    395155{
    396     auto context = adoptRef(*new GraphicsContext3D(sharedContext.getContextAttributes(), nullptr, sharedContext.m_renderStyle, &sharedContext));
    397 
    398     manager().addContext(context.ptr());
     156    auto hostWindow = GraphicsContext3DManager::sharedManager().hostWindowForContext(&sharedContext);
     157    auto context = adoptRef(*new GraphicsContext3D(sharedContext.getContextAttributes(), hostWindow, sharedContext.m_renderStyle, &sharedContext));
     158
     159    GraphicsContext3DManager::sharedManager().addContext(context.ptr(), hostWindow);
    399160
    400161    return context;
    401162}
    402163
    403 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
    404 static void identifyAndSetCurrentGPU(CGLPixelFormatObj pixelFormatObj, int numPixelFormats, CGOpenGLDisplayMask displayMaskOpenGL, PlatformGraphicsContext3D contextObj)
    405 {
    406     // 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.
    407     // CGLSetVirtualScreen can be used to tell OpenGL which GPU it should be using.
    408     // See code example at https://developer.apple.com/library/content/technotes/tn2229/_index.html#//apple_ref/doc/uid/DTS40008924-CH1-SUBSECTION7
    409    
    410     if (!displayMaskOpenGL || !contextObj)
    411         return;
    412 
    413     for (int virtualScreen = 0; virtualScreen < numPixelFormats; ++virtualScreen) {
    414         GLint displayMask = 0;
    415         CGLError error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask, &displayMask);
     164#if PLATFORM(MAC)
     165static 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.
     169    // CGLSetVirtualScreen can then be used to tell OpenGL which GPU it should be using.
     170
     171    if (!contextObj || !preferredRendererID)
     172        return;
     173
     174    GLint virtualScreenCount = 0;
     175    CGLError error = CGLDescribePixelFormat(pixelFormatObj, 0, kCGLPFAVirtualScreenCount, &virtualScreenCount);
     176    ASSERT(error == kCGLNoError);
     177
     178    for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen) {
     179        GLint rendererID = 0;
     180        error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFARendererID, &rendererID);
    416181        ASSERT(error == kCGLNoError);
    417182        if (error != kCGLNoError)
    418183            continue;
    419         if (displayMask & displayMaskOpenGL) {
     184        if (rendererID == preferredRendererID) {
    420185            error = CGLSetVirtualScreen(contextObj, virtualScreen);
    421186            ASSERT(error == kCGLNoError);
     187            LOG(WebGL, "Context (%p) set to GPU renderer (%d).", contextObj, rendererID);
    422188            break;
    423189        }
     
    494260    CGLSetParameter(m_contextObj, kCGLCPAbortOnGPURestartStatusBlacklisted, &abortOnBlacklist);
    495261   
    496 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
    497     if (auto displayMask = primaryOpenGLDisplayMask()) {
    498         if (hostWindow && hostWindow->displayID())
    499             displayMask = displayMaskForDisplay(hostWindow->displayID());
    500         identifyAndSetCurrentGPU(pixelFormatObj, numPixelFormats, displayMask, m_contextObj);
    501     }
     262#if PLATFORM(MAC)
     263    GLint rendererID = (hostWindow && hostWindow->displayID()) ? rendererIDForDisplay(hostWindow->displayID()) : primaryRendererID();
     264    identifyAndSetCurrentGPU(m_contextObj, pixelFormatObj, rendererID);
    502265#else
    503266    UNUSED_PARAM(hostWindow);
     
    602365GraphicsContext3D::~GraphicsContext3D()
    603366{
    604     manager().removeContext(this);
     367    GraphicsContext3DManager::sharedManager().removeContext(this);
    605368
    606369    if (m_contextObj) {
     
    772535    if (m_powerPreferenceUsedForCreation == GraphicsContext3DPowerPreference::HighPerformance) {
    773536        if (isVisible)
    774             manager().addContextRequiringHighPerformance(this);
     537            GraphicsContext3DManager::sharedManager().addContextRequiringHighPerformance(this);
    775538        else
    776             manager().removeContextRequiringHighPerformance(this);
     539            GraphicsContext3DManager::sharedManager().removeContextRequiringHighPerformance(this);
    777540    }
    778541}
     
    794557void GraphicsContext3D::simulateContextChanged()
    795558{
    796     manager().updateAllContexts();
     559    GraphicsContext3DManager::sharedManager().updateAllContexts();
    797560}
    798561
     
    818581}
    819582
     583#if PLATFORM(MAC)
     584void GraphicsContext3D::screenDidChange(PlatformDisplayID displayID)
     585{
     586    if (!m_contextObj)
     587        return;
     588
     589    identifyAndSetCurrentGPU(m_contextObj, CGLGetPixelFormat(m_contextObj), rendererIDForDisplay(displayID));
     590}
     591#endif
     592
    820593}
    821594
  • trunk/Source/WebCore/platform/mac/PlatformScreenMac.mm

    r232535 r234074  
    103103}
    104104
     105// FIXME: This function only returns 0 for now.
    105106static PlatformDisplayID& primaryScreenDisplayID()
    106107{
    107108    static PlatformDisplayID primaryScreenDisplayID = 0;
    108109    return primaryScreenDisplayID;
     110}
     111
     112static GLint rendererIDForDisplayMask(GLuint displayMask)
     113{
     114    GLint numRenderers;
     115    CGLRendererInfoObj rendererInfo;
     116    CGLError error = CGLQueryRendererInfo(displayMask, &rendererInfo, &numRenderers);
     117    ASSERT(error == kCGLNoError);
     118
     119    GLint rendererID;
     120    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPRendererID, &rendererID);
     121    ASSERT(error == kCGLNoError);
     122
     123    // The 0th renderer should not be the software renderer.
     124    GLint isAccelerated;
     125    error = CGLDescribeRenderer(rendererInfo, 0, kCGLRPAccelerated, &isAccelerated);
     126    ASSERT(error == kCGLNoError);
     127    ASSERT(isAccelerated);
     128
     129    return rendererID;
    109130}
    110131
     
    129150        bool screenIsMonochrome = CGDisplayUsesForceToGray();
    130151        uint32_t displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
    131 
    132         screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask });
     152        GLint rendererID = rendererIDForDisplayMask(displayMask);
     153
     154        screenProperties.screenDataMap.set(displayID, ScreenData { screenAvailableRect, screenRect, colorSpace, screenDepth, screenDepthPerComponent, screenSupportsExtendedColor, screenHasInvertedColors, screenIsMonochrome, displayMask, rendererID });
    133155
    134156        if (!screenProperties.primaryDisplayID)
     
    177199}
    178200
     201GLint rendererIDForDisplay(PlatformDisplayID displayID)
     202{
     203#if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
     204    if (!screenProperties().screenDataMap.isEmpty())
     205        return screenData(displayID).rendererID;
     206#else
     207    return rendererIDForDisplayMask(CGDisplayIDToOpenGLDisplayMask(displayID));
     208#endif
     209    ASSERT_NOT_REACHED();
     210    return 0;
     211}
     212
     213GLint primaryRendererID()
     214{
     215    return rendererIDForDisplay(screenProperties().primaryDisplayID);
     216}
     217
    179218static ScreenData getScreenProperties(Widget* widget)
    180219{
Note: See TracChangeset for help on using the changeset viewer.