Title: [271533] trunk/Source
Revision
271533
Author
[email protected]
Date
2021-01-15 13:51:52 -0800 (Fri, 15 Jan 2021)

Log Message

[GPUProcess] Move DOM / Canvas rendering off the main thread in the GPUProcess
https://bugs.webkit.org/show_bug.cgi?id=220476

Reviewed by Simon Fraser.

Source/WebCore:

Make some caches thread-safe now that we do rendering off the main thread in
the GPUProcess.

No new tests, covered by existing tests.

* platform/graphics/ImageBuffer.h:
* platform/graphics/MediaPlayer.h:
* platform/graphics/ShadowBlur.cpp:
(WebCore::ScratchBuffer::ScratchBuffer):
(WebCore::ScratchBuffer::getScratchBuffer):
(WebCore::ScratchBuffer::setCachedShadowValues):
(WebCore::ScratchBuffer::setCachedInsetShadowValues):
(WebCore::ScratchBuffer::scheduleScratchBufferPurge):
(WebCore::ScratchBuffer::purgeTimerFired):
(WebCore::ScratchBuffer::clearScratchBuffer):
(WebCore::ScratchBuffer::singleton):
(WebCore::ScratchBuffer::lock):
(WebCore::ShadowBlur::drawRectShadowWithTiling):
(WebCore::ShadowBlur::drawInsetShadowWithTiling):
* platform/graphics/cg/ImageBufferUtilitiesCG.cpp:
(WebCore::utiFromImageBufferMIMEType):
* platform/graphics/cg/SubimageCacheWithTimer.cpp:
(WebCore::SubimageCacheWithTimer::SubimageCacheWithTimer):
(WebCore::SubimageCacheWithTimer::pruneCacheTimerFired):
(WebCore::SubimageCacheWithTimer::subimage):
(WebCore::SubimageCacheWithTimer::clearImageAndSubimages):
(WebCore::SubimageCacheWithTimer::clearAll):
(WebCore::SubimageCacheWithTimer::subimageCache):
* platform/graphics/cg/SubimageCacheWithTimer.h:
* platform/network/mac/UTIUtilities.mm:
(WebCore::UTIFromUnknownMIMEType):
(WebCore::UTIFromMIMETypeCachePolicy::createValueForKey):
(WebCore::UTIFromMIMETypeCachePolicy::createKeyForStorage):
(WebCore::cacheUTIFromMimeType):
(WebCore::UTIFromMIMEType):
* platform/text/cf/HyphenationCF.cpp:
* platform/text/hyphen/HyphenationLibHyphen.cpp:
https://bugs.webkit.org/show_bug.cgi?id=220476

Source/WebKit:

Move DOM / Canvas rendering off the main thread (and on a high-priority serial WorkQueue) in the
GPUProcess by making RemoteRenderingBackend a WorkQueueMessageReceiver. There is a serial WorkQueue
per RemoteRenderingBackend, which means each WebPage gets its own WorkQueue.

A/B testing shows this mostly perf-neutral (could be a slight progression on some hardware). I believe
this new architecture should also give us more optimization opportunities in the future. For example,
we may be able to more aggressively wait on the cross-process semaphore when waiting for new DisplayList
entries without worrying about blocking the main thread.

I have run layout tests in Debug on both macOS & iOS with the GPUProcess enabled and I believe I
have fixed all the crashes that were discovered.

* GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess):
(WebKit::GPUConnectionToWebProcess::didClose):
(WebKit::GPUConnectionToWebProcess::createRenderingBackend):
(WebKit::GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::RemoteRenderingBackendWrapper):
(WebKit::GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::~RemoteRenderingBackendWrapper):
* GPUProcess/GPUConnectionToWebProcess.h:
(WebKit::GPUConnectionToWebProcess::remoteMediaPlayerManagerProxy):
* GPUProcess/graphics/RemoteRenderingBackend.cpp:
(WebKit::RemoteRenderingBackend::create):
(WebKit::RemoteRenderingBackend::RemoteRenderingBackend):
(WebKit::RemoteRenderingBackend::~RemoteRenderingBackend):
(WebKit::RemoteRenderingBackend::disconnect):
(WebKit::RemoteRenderingBackend::messageSenderConnection const):
(WebKit::RemoteRenderingBackend::applyMediaItem):
(WebKit::RemoteRenderingBackend::createImageBuffer):
(WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):
(WebKit::RemoteRenderingBackend::getImageData):
(WebKit::RemoteRenderingBackend::getDataURLForImageBuffer):
(WebKit::RemoteRenderingBackend::getDataForImageBuffer):
(WebKit::RemoteRenderingBackend::getBGRADataForImageBuffer):
(WebKit::RemoteRenderingBackend::cacheNativeImage):
(WebKit::RemoteRenderingBackend::cacheFont):
(WebKit::RemoteRenderingBackend::deleteAllFonts):
(WebKit::RemoteRenderingBackend::releaseRemoteResource):
(WebKit::RemoteRenderingBackend::didCreateSharedDisplayListHandle):
* GPUProcess/graphics/RemoteRenderingBackend.h:
* GPUProcess/graphics/RemoteRenderingBackend.messages.in:
* GPUProcess/media/RemoteLegacyCDMProxy.cpp:
(WebKit::RemoteLegacyCDMProxy::cdmMediaPlayer const):
* GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp:
(WebKit::RemoteMediaPlayerManagerProxy::createMediaPlayer):
(WebKit::RemoteMediaPlayerManagerProxy::deleteMediaPlayer):
(WebKit::RemoteMediaPlayerManagerProxy::didReceivePlayerMessage):
(WebKit::RemoteMediaPlayerManagerProxy::didReceiveSyncPlayerMessage):
(WebKit::RemoteMediaPlayerManagerProxy::mediaPlayer):
* GPUProcess/media/RemoteMediaPlayerManagerProxy.h:
* Platform/SharedMemory.h:
* Shared/ShareableBitmap.cpp:
(WebKit::ShareableBitmap::ShareableBitmap):
(WebKit::ShareableBitmap::~ShareableBitmap):
* Shared/ShareableBitmap.h:
* Shared/cg/ShareableBitmapCG.cpp:
(WebKit::ShareableBitmap::createGraphicsContext):
(WebKit::ShareableBitmap::releaseBitmapContextData):
(WebKit::ShareableBitmap::releaseDataProviderData):

Source/WTF:

Add trait function that gets called TinyLRUCache to convert the key before storing
it. It is useful for clients that need to call isolatedCopy() on the key String before
storing it.

* wtf/TinyLRUCache.h:
(WTF::TinyLRUCachePolicy::createKeyForStorage):
(WTF::TinyLRUCache::get):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (271532 => 271533)


--- trunk/Source/WTF/ChangeLog	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WTF/ChangeLog	2021-01-15 21:51:52 UTC (rev 271533)
@@ -1,3 +1,18 @@
+2021-01-15  Chris Dumez  <[email protected]>
+
+        [GPUProcess] Move DOM / Canvas rendering off the main thread in the GPUProcess
+        https://bugs.webkit.org/show_bug.cgi?id=220476
+
+        Reviewed by Simon Fraser.
+
+        Add trait function that gets called TinyLRUCache to convert the key before storing
+        it. It is useful for clients that need to call isolatedCopy() on the key String before
+        storing it.
+
+        * wtf/TinyLRUCache.h:
+        (WTF::TinyLRUCachePolicy::createKeyForStorage):
+        (WTF::TinyLRUCache::get):
+
 2021-01-14  Alex Christensen  <[email protected]>
 
         Add dotless j and small N to unicode lookalike character list

Modified: trunk/Source/WTF/wtf/TinyLRUCache.h (271532 => 271533)


--- trunk/Source/WTF/wtf/TinyLRUCache.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WTF/wtf/TinyLRUCache.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -35,6 +35,7 @@
     static bool isKeyNull(const KeyType&) { return false; }
     static ValueType createValueForNullKey() { return { }; }
     static ValueType createValueForKey(const KeyType&) { return { }; }
+    static KeyType createKeyForStorage(const KeyType& key) { return key; }
 };
 
 template<typename KeyType, typename ValueType, size_t capacity = 4, typename Policy = TinyLRUCachePolicy<KeyType, ValueType>>
@@ -66,7 +67,7 @@
         if (m_cache.size() == capacity)
             m_cache.remove(0);
 
-        m_cache.append(std::make_pair(key, Policy::createValueForKey(key)));
+        m_cache.append(std::make_pair(Policy::createKeyForStorage(key), Policy::createValueForKey(key)));
         return m_cache.last().second;
     }
 

Modified: trunk/Source/WebCore/ChangeLog (271532 => 271533)


--- trunk/Source/WebCore/ChangeLog	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/ChangeLog	2021-01-15 21:51:52 UTC (rev 271533)
@@ -1,3 +1,49 @@
+2021-01-15  Chris Dumez  <[email protected]>
+
+        [GPUProcess] Move DOM / Canvas rendering off the main thread in the GPUProcess
+        https://bugs.webkit.org/show_bug.cgi?id=220476
+
+        Reviewed by Simon Fraser.
+
+        Make some caches thread-safe now that we do rendering off the main thread in
+        the GPUProcess.
+
+        No new tests, covered by existing tests.
+
+        * platform/graphics/ImageBuffer.h:
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/ShadowBlur.cpp:
+        (WebCore::ScratchBuffer::ScratchBuffer):
+        (WebCore::ScratchBuffer::getScratchBuffer):
+        (WebCore::ScratchBuffer::setCachedShadowValues):
+        (WebCore::ScratchBuffer::setCachedInsetShadowValues):
+        (WebCore::ScratchBuffer::scheduleScratchBufferPurge):
+        (WebCore::ScratchBuffer::purgeTimerFired):
+        (WebCore::ScratchBuffer::clearScratchBuffer):
+        (WebCore::ScratchBuffer::singleton):
+        (WebCore::ScratchBuffer::lock):
+        (WebCore::ShadowBlur::drawRectShadowWithTiling):
+        (WebCore::ShadowBlur::drawInsetShadowWithTiling):
+        * platform/graphics/cg/ImageBufferUtilitiesCG.cpp:
+        (WebCore::utiFromImageBufferMIMEType):
+        * platform/graphics/cg/SubimageCacheWithTimer.cpp:
+        (WebCore::SubimageCacheWithTimer::SubimageCacheWithTimer):
+        (WebCore::SubimageCacheWithTimer::pruneCacheTimerFired):
+        (WebCore::SubimageCacheWithTimer::subimage):
+        (WebCore::SubimageCacheWithTimer::clearImageAndSubimages):
+        (WebCore::SubimageCacheWithTimer::clearAll):
+        (WebCore::SubimageCacheWithTimer::subimageCache):
+        * platform/graphics/cg/SubimageCacheWithTimer.h:
+        * platform/network/mac/UTIUtilities.mm:
+        (WebCore::UTIFromUnknownMIMEType):
+        (WebCore::UTIFromMIMETypeCachePolicy::createValueForKey):
+        (WebCore::UTIFromMIMETypeCachePolicy::createKeyForStorage):
+        (WebCore::cacheUTIFromMimeType):
+        (WebCore::UTIFromMIMEType):
+        * platform/text/cf/HyphenationCF.cpp:
+        * platform/text/hyphen/HyphenationLibHyphen.cpp:
+        https://bugs.webkit.org/show_bug.cgi?id=220476
+
 2021-01-15  Jer Noble  <[email protected]>
 
         Playback fails at marketwatch.com

Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -42,7 +42,7 @@
 struct ItemBufferHandle;
 }
 
-class ImageBuffer : public RefCounted<ImageBuffer>, public CanMakeWeakPtr<ImageBuffer> {
+class ImageBuffer : public ThreadSafeRefCounted<ImageBuffer>, public CanMakeWeakPtr<ImageBuffer> {
 public:
     // Will return a null pointer on allocation failure.
     WEBCORE_EXPORT static RefPtr<ImageBuffer> create(const FloatSize&, RenderingMode, ShouldUseDisplayList, RenderingPurpose, float resolutionScale = 1, ColorSpace = ColorSpace::SRGB, PixelFormat = PixelFormat::BGRA8, const HostWindow* = nullptr);

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -51,6 +51,7 @@
 #include <wtf/HashSet.h>
 #include <wtf/Logger.h>
 #include <wtf/MediaTime.h>
+#include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/WallTime.h>
 #include <wtf/text/StringHash.h>
 
@@ -282,7 +283,7 @@
 #endif
 };
 
-class WEBCORE_EXPORT MediaPlayer : public MediaPlayerEnums, public RefCounted<MediaPlayer> {
+class WEBCORE_EXPORT MediaPlayer : public MediaPlayerEnums, public ThreadSafeRefCounted<MediaPlayer, WTF::DestructionThread::Main> {
     WTF_MAKE_NONCOPYABLE(MediaPlayer); WTF_MAKE_FAST_ALLOCATED;
 public:
     static Ref<MediaPlayer> create(MediaPlayerClient&);

Modified: trunk/Source/WebCore/platform/graphics/ShadowBlur.cpp (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/ShadowBlur.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/ShadowBlur.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -36,9 +36,11 @@
 #include "ImageBuffer.h"
 #include "ImageData.h"
 #include "Timer.h"
+#include <wtf/Lock.h>
 #include <wtf/MathExtras.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/RunLoop.h>
 #include <wtf/Scope.h>
 
 namespace WebCore {
@@ -61,23 +63,21 @@
     WTF_MAKE_FAST_ALLOCATED;
 public:
     ScratchBuffer()
-        : m_purgeTimer(*this, &ScratchBuffer::clearScratchBuffer)
-        , m_lastWasInset(false)
-#if ASSERT_ENABLED
-        , m_bufferInUse(false)
-#endif
+        : m_purgeTimer(RunLoop::main(), this, &ScratchBuffer::purgeTimerFired)
     {
     }
 
-    ImageBuffer* getScratchBuffer(const IntSize& size)
+    RefPtr<ImageBuffer> getScratchBuffer(const IntSize& size)
     {
-        ASSERT(!m_bufferInUse);
-#if ASSERT_ENABLED
-        m_bufferInUse = true;
-#endif
+        ASSERT(lock().isHeld());
+        auto releaseLayerImage = makeScopeExit([this] {
+            if (m_imageBuffer)
+                scheduleScratchBufferPurge();
+        });
+
         // We do not need to recreate the buffer if the current buffer is large enough.
         if (m_imageBuffer && m_imageBuffer->logicalSize().width() >= size.width() && m_imageBuffer->logicalSize().height() >= size.height())
-            return m_imageBuffer.get();
+            return m_imageBuffer;
 
         // Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests.
         IntSize roundedSize(roundUpToMultipleOf32(size.width()), roundUpToMultipleOf32(size.height()));
@@ -86,11 +86,12 @@
 
         // ShadowBlur is not used with accelerated drawing, so it's OK to make an unconditionally unaccelerated buffer.
         m_imageBuffer = ImageBuffer::create(roundedSize, RenderingMode::Unaccelerated, 1);
-        return m_imageBuffer.get();
+        return m_imageBuffer;
     }
 
     bool setCachedShadowValues(const FloatSize& radius, const Color& color, const FloatRect& shadowRect, const FloatRoundedRect::Radii& radii, const FloatSize& layerSize)
     {
+        ASSERT(lock().isHeld());
         if (!m_lastWasInset && m_lastRadius == radius && m_lastColor == color && m_lastShadowRect == shadowRect &&  m_lastRadii == radii && m_lastLayerSize == layerSize)
             return false;
 
@@ -106,6 +107,7 @@
 
     bool setCachedInsetShadowValues(const FloatSize& radius, const Color& color, const FloatRect& bounds, const FloatRect& shadowRect, const FloatRoundedRect::Radii& radii)
     {
+        ASSERT(lock().isHeld());
         if (m_lastWasInset && m_lastRadius == radius && m_lastColor == color && m_lastInsetBounds == bounds && shadowRect == m_lastShadowRect && radii == m_lastRadii)
             return false;
 
@@ -119,23 +121,27 @@
         return true;
     }
 
+    static ScratchBuffer& singleton();
+    static Lock& lock();
+
+private:
     void scheduleScratchBufferPurge()
     {
-#if ASSERT_ENABLED
-        m_bufferInUse = false;
-#endif
-        if (m_purgeTimer.isActive())
-            m_purgeTimer.stop();
-
+        ASSERT(lock().isHeld());
         const Seconds scratchBufferPurgeInterval { 2_s };
         m_purgeTimer.startOneShot(scratchBufferPurgeInterval);
     }
 
-    static ScratchBuffer& singleton();
+    void purgeTimerFired()
+    {
+        ASSERT(isMainThread());
+        if (auto locker = tryHoldLock(lock()))
+            clearScratchBuffer();
+    }
 
-private:
     void clearScratchBuffer()
     {
+        ASSERT(lock().isHeld());
         m_imageBuffer = nullptr;
         m_lastRadius = FloatSize();
         m_lastLayerSize = FloatSize();
@@ -142,7 +148,7 @@
     }
 
     RefPtr<ImageBuffer> m_imageBuffer;
-    Timer m_purgeTimer;
+    RunLoop::Timer<ScratchBuffer> m_purgeTimer;
 
     FloatRect m_lastInsetBounds;
     FloatRect m_lastShadowRect;
@@ -149,20 +155,23 @@
     FloatRoundedRect::Radii m_lastRadii;
     Color m_lastColor;
     FloatSize m_lastRadius;
-    bool m_lastWasInset;
+    bool m_lastWasInset { false };
     FloatSize m_lastLayerSize;
-
-#if ASSERT_ENABLED
-    bool m_bufferInUse;
-#endif
 };
 
 ScratchBuffer& ScratchBuffer::singleton()
 {
+    ASSERT(lock().isHeld());
     static NeverDestroyed<ScratchBuffer> scratchBuffer;
     return scratchBuffer;
 }
 
+Lock& ScratchBuffer::lock()
+{
+    static Lock lock;
+    return lock;
+}
+
 static float radiusToLegacyRadius(float radius)
 {
     return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius;
@@ -683,19 +692,24 @@
 
 void ShadowBlur::drawRectShadowWithTiling(const AffineTransform& transform, const FloatRoundedRect& shadowedRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectCallback& fillRect, const LayerImageProperties& layerImageProperties)
 {
+    RefPtr<ImageBuffer> layerImageBuffer;
 #if USE(CG)
-    auto* layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize);
-    auto releaseLayerImage = makeScopeExit([] {
-        ScratchBuffer::singleton().scheduleScratchBufferPurge();
-    });
+    auto locker = tryHoldLock(ScratchBuffer::lock());
+    if (locker) {
+        layerImageBuffer = ScratchBuffer::singleton().getScratchBuffer(templateSize);
+        if (!layerImageBuffer)
+            return;
+    }
 #else
     UNUSED_PARAM(layerImageProperties);
-    auto layerImageBuffer = ImageBuffer::create(templateSize, RenderingMode::Unaccelerated, 1);
-    auto* layerImage = layerImageBuffer.get();
 #endif
 
-    if (!layerImage)
-        return;
+    if (!layerImageBuffer) {
+        layerImageBuffer = ImageBuffer::create(templateSize, RenderingMode::Unaccelerated, 1);
+        if (!layerImageBuffer)
+            return;
+    }
+    auto* layerImage = layerImageBuffer.get();
 
     FloatRect templateShadow = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height());
 
@@ -702,7 +716,8 @@
     bool redrawNeeded = true;
 #if USE(CG)
     // Only redraw in the scratch buffer if its cached contents don't match our needs
-    redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), layerImageProperties.layerSize);
+    if (locker)
+        redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), layerImageProperties.layerSize);
 #endif
 
     if (redrawNeeded) {
@@ -737,18 +752,22 @@
 
 void ShadowBlur::drawInsetShadowWithTiling(const AffineTransform& transform, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectWithHoleCallback& fillRectWithHole)
 {
+    RefPtr<ImageBuffer> layerImageBuffer;
 #if USE(CG)
-    auto* layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize);
-    auto releaseLayerImage = makeScopeExit([] {
-        ScratchBuffer::singleton().scheduleScratchBufferPurge();
-    });
-#else
-    auto layerImageBuffer = ImageBuffer::create(templateSize, RenderingMode::Unaccelerated, 1);
-    auto* layerImage = layerImageBuffer.get();
+    auto locker = tryHoldLock(ScratchBuffer::lock());
+    if (locker) {
+        layerImageBuffer = ScratchBuffer::singleton().getScratchBuffer(templateSize);
+        if (!layerImageBuffer)
+            return;
+    }
 #endif
 
-    if (!layerImage)
-        return;
+    if (!layerImageBuffer) {
+        layerImageBuffer = ImageBuffer::create(templateSize, RenderingMode::Unaccelerated, 1);
+        if (!layerImageBuffer)
+            return;
+    }
+    auto* layerImage = layerImageBuffer.get();
 
     // Draw the rectangle with hole.
     FloatRect templateBounds(0, 0, templateSize.width(), templateSize.height());
@@ -757,7 +776,8 @@
     bool redrawNeeded = true;
 #if USE(CG)
     // Only redraw in the scratch buffer if its cached contents don't match our needs
-    redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii());
+    if (locker)
+        redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii());
 #endif
 
     if (redrawNeeded) {

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -69,13 +69,17 @@
 #if PLATFORM(MAC)
     return UTIFromMIMEType(mimeType).createCFString();
 #else
-    ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
-
     // FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found.
     // For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>.
-    static const CFStringRef kUTTypePNG = CFSTR("public.png");
-    static const CFStringRef kUTTypeGIF = CFSTR("com.compuserve.gif");
+    static CFStringRef kUTTypePNG;
+    static CFStringRef kUTTypeGIF;
 
+    static std::once_flag onceKey;
+    std::call_once(onceKey, [&] {
+        kUTTypePNG = CFSTR("public.png");
+        kUTTypeGIF = CFSTR("com.compuserve.gif");
+    });
+
     if (equalLettersIgnoringASCIICase(mimeType, "image/png"))
         return kUTTypePNG;
     if (equalLettersIgnoringASCIICase(mimeType, "image/jpeg"))

Modified: trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.cpp (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -83,12 +83,13 @@
 };
 
 SubimageCacheWithTimer::SubimageCacheWithTimer()
-    : m_timer(*this, &SubimageCacheWithTimer::pruneCacheTimerFired)
+    : m_timer(RunLoop::main(), this, &SubimageCacheWithTimer::pruneCacheTimerFired)
 {
 }
 
 void SubimageCacheWithTimer::pruneCacheTimerFired()
 {
+    auto locker = holdLock(m_lock);
     prune();
     if (m_cache.isEmpty()) {
         ASSERT(m_imageCounts.isEmpty());
@@ -115,6 +116,7 @@
 
 RetainPtr<CGImageRef> SubimageCacheWithTimer::subimage(CGImageRef image, const FloatRect& rect)
 {
+    auto locker = holdLock(m_lock);
     if (!m_timer.isActive())
         m_timer.startRepeating(subimageCachePruneDelay);
 
@@ -135,6 +137,7 @@
 
 void SubimageCacheWithTimer::clearImageAndSubimages(CGImageRef image)
 {
+    auto locker = holdLock(m_lock);
     if (m_imageCounts.contains(image)) {
         Vector<SubimageCacheEntry> toBeRemoved;
         for (const auto& entry : m_cache) {
@@ -151,6 +154,7 @@
 
 void SubimageCacheWithTimer::clearAll()
 {
+    auto locker = holdLock(m_lock);
     m_imageCounts.clear();
     m_cache.clear();
 }
@@ -157,8 +161,10 @@
 
 SubimageCacheWithTimer& SubimageCacheWithTimer::subimageCache()
 {
-    if (!s_cache)
+    static std::once_flag onceKey;
+    std::call_once(onceKey, [&] {
         s_cache = new SubimageCacheWithTimer;
+    });
     return *s_cache;
 }
 

Modified: trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h (271532 => 271533)


--- trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -32,7 +32,9 @@
 #include <wtf/HashCountedSet.h>
 #include <wtf/HashSet.h>
 #include <wtf/HashTraits.h>
+#include <wtf/Lock.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/RunLoop.h>
 
 #define CACHE_SUBIMAGES 1
 
@@ -95,9 +97,10 @@
     void prune();
     void clearAll();
 
+    Lock m_lock;
     HashCountedSet<CGImageRef> m_imageCounts;
     SubimageCacheHashSet m_cache;
-    Timer m_timer;
+    RunLoop::Timer<SubimageCacheWithTimer> m_timer;
 
     static SubimageCacheWithTimer& subimageCache();
     static bool subimageCacheExists();

Modified: trunk/Source/WebCore/platform/network/mac/UTIUtilities.mm (271532 => 271533)


--- trunk/Source/WebCore/platform/network/mac/UTIUtilities.mm	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/network/mac/UTIUtilities.mm	2021-01-15 21:51:52 UTC (rev 271533)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "UTIUtilities.h"
 
+#import <wtf/Lock.h>
 #import <wtf/MainThread.h>
 #import <wtf/TinyLRUCache.h>
 #import <wtf/text/StringHash.h>
@@ -84,57 +85,52 @@
     return emptyString();
 }
 
-static String UTIFromUnknownMIMEType(const String& mimeType)
+static CFStringRef UTIFromUnknownMIMEType(const String& mimeType)
 {
     static const auto map = makeNeverDestroyed([] {
-        struct TypeExtensionPair {
-            ASCIILiteral type;
-            ASCIILiteral uti;
-        };
-
-        static const TypeExtensionPair pairs[] = {
-            { "model/vnd.usdz+zip"_s, "com.pixar.universal-scene-description-mobile"_s },
-            { "model/usd"_s, "com.pixar.universal-scene-description-mobile"_s },
-            { "model/vnd.pixar.usd"_s, "com.pixar.universal-scene-description-mobile"_s },
-            { "model/vnd.reality"_s, "com.apple.reality"_s }
-        };
-
-        HashMap<String, String, ASCIICaseInsensitiveHash> map;
-        for (auto& pair : pairs)
-            map.add(pair.type, pair.uti);
+        HashMap<String, CFStringRef, ASCIICaseInsensitiveHash> map;
+        auto pixarMIMEType = CFSTR("com.pixar.universal-scene-description-mobile");
+        map.add("model/vnd.usdz+zip"_s, pixarMIMEType);
+        map.add("model/usd"_s, pixarMIMEType);
+        map.add("model/vnd.pixar.usd"_s, pixarMIMEType);
+        map.add("model/vnd.usdz+zip"_s, CFSTR("com.apple.reality"));
         return map;
     }());
 
+    static const CFStringRef emptyCFString = CFSTR("");
     auto mapEntry = map.get().find(mimeType);
     if (mapEntry == map.get().end())
-        return emptyString();
+        return emptyCFString;
 
     return mapEntry->value;
 }
 
-struct UTIFromMIMETypeCachePolicy : TinyLRUCachePolicy<String, String> {
+struct UTIFromMIMETypeCachePolicy : TinyLRUCachePolicy<String, RetainPtr<CFStringRef>> {
 public:
-    static String createValueForKey(const String& mimeType)
+    static RetainPtr<CFStringRef> createValueForKey(const String& mimeType)
     {
 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
         auto type = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), 0));
 ALLOW_DEPRECATED_DECLARATIONS_END
         if (type)
-            return type.get();
+            return type;
         return UTIFromUnknownMIMEType(mimeType);
     }
+
+    static String createKeyForStorage(const String& key) { return key.isolatedCopy(); }
 };
 
-static TinyLRUCache<String, String, 16, UTIFromMIMETypeCachePolicy>& cacheUTIFromMimeType()
+static TinyLRUCache<String, RetainPtr<CFStringRef>, 16, UTIFromMIMETypeCachePolicy>& cacheUTIFromMimeType()
 {
-    static NeverDestroyed<TinyLRUCache<String, String, 16, UTIFromMIMETypeCachePolicy>> cache;
+    static NeverDestroyed<TinyLRUCache<String, RetainPtr<CFStringRef>, 16, UTIFromMIMETypeCachePolicy>> cache;
     return cache;
 }
 
 String UTIFromMIMEType(const String& mimeType)
 {
-    ASSERT(isMainThread());
-    return cacheUTIFromMimeType().get(mimeType);
+    static Lock lock;
+    auto locker = holdLock(lock);
+    return cacheUTIFromMimeType().get(mimeType).get();
 }
 
 bool isDeclaredUTI(const String& UTI)

Modified: trunk/Source/WebCore/platform/text/cf/HyphenationCF.cpp (271532 => 271533)


--- trunk/Source/WebCore/platform/text/cf/HyphenationCF.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/text/cf/HyphenationCF.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -63,6 +63,8 @@
 
         return CFStringIsHyphenationAvailableForLocale(locale.get()) ? locale : nullptr;
     }
+
+    static AtomString createKeyForStorage(const AtomString& key) { return key; }
 };
 }
 

Modified: trunk/Source/WebCore/platform/text/hyphen/HyphenationLibHyphen.cpp (271532 => 271533)


--- trunk/Source/WebCore/platform/text/hyphen/HyphenationLibHyphen.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebCore/platform/text/hyphen/HyphenationLibHyphen.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -241,6 +241,8 @@
     {
         return WebCore::HyphenationDictionary::create(FileSystem::fileSystemRepresentation(dictionaryPath.string()));
     }
+
+    static AtomString createKeyForStorage(const AtomString& key) { return key; }
 };
 
 } // namespace WTF

Modified: trunk/Source/WebKit/ChangeLog (271532 => 271533)


--- trunk/Source/WebKit/ChangeLog	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/ChangeLog	2021-01-15 21:51:52 UTC (rev 271533)
@@ -1,3 +1,69 @@
+2021-01-15  Chris Dumez  <[email protected]>
+
+        [GPUProcess] Move DOM / Canvas rendering off the main thread in the GPUProcess
+        https://bugs.webkit.org/show_bug.cgi?id=220476
+
+        Reviewed by Simon Fraser.
+
+        Move DOM / Canvas rendering off the main thread (and on a high-priority serial WorkQueue) in the
+        GPUProcess by making RemoteRenderingBackend a WorkQueueMessageReceiver. There is a serial WorkQueue
+        per RemoteRenderingBackend, which means each WebPage gets its own WorkQueue.
+
+        A/B testing shows this mostly perf-neutral (could be a slight progression on some hardware). I believe
+        this new architecture should also give us more optimization opportunities in the future. For example,
+        we may be able to more aggressively wait on the cross-process semaphore when waiting for new DisplayList
+        entries without worrying about blocking the main thread.
+
+        I have run layout tests in Debug on both macOS & iOS with the GPUProcess enabled and I believe I
+        have fixed all the crashes that were discovered.
+
+        * GPUProcess/GPUConnectionToWebProcess.cpp:
+        (WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess):
+        (WebKit::GPUConnectionToWebProcess::didClose):
+        (WebKit::GPUConnectionToWebProcess::createRenderingBackend):
+        (WebKit::GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::RemoteRenderingBackendWrapper):
+        (WebKit::GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::~RemoteRenderingBackendWrapper):
+        * GPUProcess/GPUConnectionToWebProcess.h:
+        (WebKit::GPUConnectionToWebProcess::remoteMediaPlayerManagerProxy):
+        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
+        (WebKit::RemoteRenderingBackend::create):
+        (WebKit::RemoteRenderingBackend::RemoteRenderingBackend):
+        (WebKit::RemoteRenderingBackend::~RemoteRenderingBackend):
+        (WebKit::RemoteRenderingBackend::disconnect):
+        (WebKit::RemoteRenderingBackend::messageSenderConnection const):
+        (WebKit::RemoteRenderingBackend::applyMediaItem):
+        (WebKit::RemoteRenderingBackend::createImageBuffer):
+        (WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):
+        (WebKit::RemoteRenderingBackend::getImageData):
+        (WebKit::RemoteRenderingBackend::getDataURLForImageBuffer):
+        (WebKit::RemoteRenderingBackend::getDataForImageBuffer):
+        (WebKit::RemoteRenderingBackend::getBGRADataForImageBuffer):
+        (WebKit::RemoteRenderingBackend::cacheNativeImage):
+        (WebKit::RemoteRenderingBackend::cacheFont):
+        (WebKit::RemoteRenderingBackend::deleteAllFonts):
+        (WebKit::RemoteRenderingBackend::releaseRemoteResource):
+        (WebKit::RemoteRenderingBackend::didCreateSharedDisplayListHandle):
+        * GPUProcess/graphics/RemoteRenderingBackend.h:
+        * GPUProcess/graphics/RemoteRenderingBackend.messages.in:
+        * GPUProcess/media/RemoteLegacyCDMProxy.cpp:
+        (WebKit::RemoteLegacyCDMProxy::cdmMediaPlayer const):
+        * GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp:
+        (WebKit::RemoteMediaPlayerManagerProxy::createMediaPlayer):
+        (WebKit::RemoteMediaPlayerManagerProxy::deleteMediaPlayer):
+        (WebKit::RemoteMediaPlayerManagerProxy::didReceivePlayerMessage):
+        (WebKit::RemoteMediaPlayerManagerProxy::didReceiveSyncPlayerMessage):
+        (WebKit::RemoteMediaPlayerManagerProxy::mediaPlayer):
+        * GPUProcess/media/RemoteMediaPlayerManagerProxy.h:
+        * Platform/SharedMemory.h:
+        * Shared/ShareableBitmap.cpp:
+        (WebKit::ShareableBitmap::ShareableBitmap):
+        (WebKit::ShareableBitmap::~ShareableBitmap):
+        * Shared/ShareableBitmap.h:
+        * Shared/cg/ShareableBitmapCG.cpp:
+        (WebKit::ShareableBitmap::createGraphicsContext):
+        (WebKit::ShareableBitmap::releaseBitmapContextData):
+        (WebKit::ShareableBitmap::releaseDataProviderData):
+
 2021-01-15  Alex Christensen  <[email protected]>
 
         Remove non-inclusively named WKBrowsingContextGroup SPI

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -165,6 +165,7 @@
     : m_connection(IPC::Connection::createServerConnection(connectionIdentifier, *this))
     , m_gpuProcess(gpuProcess)
     , m_webProcessIdentifier(webProcessIdentifier)
+    , m_remoteMediaPlayerManagerProxy(makeUnique<RemoteMediaPlayerManagerProxy>(*this))
     , m_sessionID(sessionID)
 #if PLATFORM(COCOA) && USE(LIBWEBRTC)
     , m_libWebRTCCodecsProxy(LibWebRTCCodecsProxy::create(*this))
@@ -202,8 +203,12 @@
     }
 #endif
 
+    // RemoteRenderingBackend objects ref their GPUConnectionToWebProcess so we need to make sure
+    // to break the reference cycle by destroying them.
+    m_remoteRenderingBackendMap.clear();
+
     gpuProcess().connectionToWebProcessClosed(connection);
-    gpuProcess().removeGPUConnectionToWebProcess(*this);
+    gpuProcess().removeGPUConnectionToWebProcess(*this); // May destroy |this|.
 }
 
 Logger& GPUConnectionToWebProcess::logger()
@@ -240,14 +245,6 @@
     return *m_remoteMediaResourceManager;
 }
 
-RemoteMediaPlayerManagerProxy& GPUConnectionToWebProcess::remoteMediaPlayerManagerProxy()
-{
-    if (!m_remoteMediaPlayerManagerProxy)
-        m_remoteMediaPlayerManagerProxy = makeUnique<RemoteMediaPlayerManagerProxy>(*this);
-
-    return *m_remoteMediaPlayerManagerProxy;
-}
-
 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
 UserMediaCaptureManagerProxy& GPUConnectionToWebProcess::userMediaCaptureManagerProxy()
 {
@@ -292,7 +289,7 @@
 void GPUConnectionToWebProcess::createRenderingBackend(RemoteRenderingBackendCreationParameters&& parameters)
 {
     auto addResult = m_remoteRenderingBackendMap.ensure(parameters.identifier, [&]() {
-        return RemoteRenderingBackend::create(*this, WTFMove(parameters));
+        return makeUnique<RemoteRenderingBackendWrapper>(RemoteRenderingBackend::create(*this, WTFMove(parameters)));
     });
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
 }
@@ -303,6 +300,16 @@
     ASSERT_UNUSED(found, found);
 }
 
+GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::RemoteRenderingBackendWrapper(Ref<RemoteRenderingBackend>&& remoteRenderingBackend)
+    : m_remoteRenderingBackend(WTFMove(remoteRenderingBackend))
+{
+}
+
+GPUConnectionToWebProcess::RemoteRenderingBackendWrapper::~RemoteRenderingBackendWrapper()
+{
+    m_remoteRenderingBackend->disconnect();
+}
+
 #if ENABLE(WEBGL)
 void GPUConnectionToWebProcess::createGraphicsContextGL(WebCore::GraphicsContextGLAttributes attributes, GraphicsContextGLIdentifier graphicsContextGLIdentifier)
 {

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -38,7 +38,7 @@
 #include <WebCore/ProcessIdentifier.h>
 #include <pal/SessionID.h>
 #include <wtf/Logger.h>
-#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
 
 #if ENABLE(WEBGL)
 #include "GraphicsContextGLIdentifier.h"
@@ -68,7 +68,7 @@
 struct RemoteRenderingBackendCreationParameters;
 
 class GPUConnectionToWebProcess
-    : public RefCounted<GPUConnectionToWebProcess>
+    : public ThreadSafeRefCounted<GPUConnectionToWebProcess, WTF::DestructionThread::Main>
     , public WebCore::NowPlayingManager::Client
     , IPC::Connection::Client {
 public:
@@ -106,7 +106,7 @@
 #if ENABLE(GPU_PROCESS)
     RemoteMediaEngineConfigurationFactoryProxy& mediaEngineConfigurationFactoryProxy();
 #endif
-    RemoteMediaPlayerManagerProxy& remoteMediaPlayerManagerProxy();
+    RemoteMediaPlayerManagerProxy& remoteMediaPlayerManagerProxy() { return *m_remoteMediaPlayerManagerProxy; }
 
 #if USE(AUDIO_SESSION)
     RemoteAudioSessionProxyManager& audioSessionManager();
@@ -192,7 +192,17 @@
     bool m_allowsDisplayCapture { false };
 #endif
 
-    using RemoteRenderingBackendMap = HashMap<RenderingBackendIdentifier, std::unique_ptr<RemoteRenderingBackend>>;
+    class RemoteRenderingBackendWrapper {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        RemoteRenderingBackendWrapper(Ref<RemoteRenderingBackend>&&);
+        ~RemoteRenderingBackendWrapper();
+
+    private:
+        Ref<RemoteRenderingBackend> m_remoteRenderingBackend;
+    };
+
+    using RemoteRenderingBackendMap = HashMap<RenderingBackendIdentifier, std::unique_ptr<RemoteRenderingBackendWrapper>>;
     RemoteRenderingBackendMap m_remoteRenderingBackendMap;
 #if ENABLE(WEBGL)
     using RemoteGraphicsContextGLMap = HashMap<GraphicsContextGLIdentifier, std::unique_ptr<RemoteGraphicsContextGL>>;

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -38,6 +38,7 @@
 #include "RemoteRenderingBackendProxyMessages.h"
 #include <wtf/CheckedArithmetic.h>
 #include <wtf/SystemTracing.h>
+#include <wtf/WorkQueue.h>
 
 #if PLATFORM(COCOA)
 #include <wtf/cocoa/MachSemaphore.h>
@@ -46,38 +47,41 @@
 namespace WebKit {
 using namespace WebCore;
 
-std::unique_ptr<RemoteRenderingBackend> RemoteRenderingBackend::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& parameters)
+Ref<RemoteRenderingBackend> RemoteRenderingBackend::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& parameters)
 {
-    return std::unique_ptr<RemoteRenderingBackend>(new RemoteRenderingBackend(gpuConnectionToWebProcess, WTFMove(parameters)));
+    return adoptRef(*new RemoteRenderingBackend(gpuConnectionToWebProcess, WTFMove(parameters)));
 }
 
 RemoteRenderingBackend::RemoteRenderingBackend(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& parameters)
-    : m_gpuConnectionToWebProcess(makeWeakPtr(gpuConnectionToWebProcess))
+    : m_workQueue(WorkQueue::create("RemoteRenderingBackend work queue", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
+    , m_gpuConnectionToWebProcess(gpuConnectionToWebProcess)
     , m_renderingBackendIdentifier(parameters.identifier)
 #if PLATFORM(COCOA)
     , m_resumeDisplayListSemaphore(makeUnique<MachSemaphore>(WTFMove(parameters.sendRightForResumeDisplayListSemaphore)))
 #endif
 {
-    if (auto* gpuConnectionToWebProcess = m_gpuConnectionToWebProcess.get())
-        gpuConnectionToWebProcess->messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this);
+    ASSERT(RunLoop::isMain());
+    gpuConnectionToWebProcess.connection().addWorkQueueMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), m_workQueue, this, m_renderingBackendIdentifier.toUInt64());
 }
 
 RemoteRenderingBackend::~RemoteRenderingBackend()
 {
-    if (auto* gpuConnectionToWebProcess = m_gpuConnectionToWebProcess.get())
-        gpuConnectionToWebProcess->messageReceiverMap().removeMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
+    // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue.
+    m_workQueue->dispatch([remoteResourceCache = WTFMove(m_remoteResourceCache)] { });
 }
 
-GPUConnectionToWebProcess* RemoteRenderingBackend::gpuConnectionToWebProcess() const
+void RemoteRenderingBackend::disconnect()
 {
-    return m_gpuConnectionToWebProcess.get();
+    ASSERT(RunLoop::isMain());
+
+    // The RemoteRenderingBackend destructor won't be called until disconnect() is called and we unregister ourselves as a WorkQueueMessageReceiver because
+    // the IPC::Connection refs its WorkQueueMessageReceivers.
+    m_gpuConnectionToWebProcess->connection().removeWorkQueueMessageReceiver(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
 }
 
 IPC::Connection* RemoteRenderingBackend::messageSenderConnection() const
 {
-    if (auto* gpuConnectionToWebProcess = m_gpuConnectionToWebProcess.get())
-        return &gpuConnectionToWebProcess->connection();
-    return nullptr;
+    return &m_gpuConnectionToWebProcess->connection();
 }
 
 uint64_t RemoteRenderingBackend::messageSenderDestinationID() const
@@ -87,19 +91,13 @@
 
 bool RemoteRenderingBackend::applyMediaItem(DisplayList::ItemHandle item, GraphicsContext& context)
 {
+    ASSERT(!RunLoop::isMain());
+
     if (!item.is<DisplayList::PaintFrameForMedia>())
         return false;
 
     auto& mediaItem = item.get<DisplayList::PaintFrameForMedia>();
-    auto process = gpuConnectionToWebProcess();
-    if (!process)
-        return false;
-
-    auto playerProxy = process->remoteMediaPlayerManagerProxy().getProxy(mediaItem.identifier());
-    if (!playerProxy)
-        return false;
-
-    auto player = playerProxy->mediaPlayer();
+    auto player = m_gpuConnectionToWebProcess->remoteMediaPlayerManagerProxy().mediaPlayer(mediaItem.identifier());
     if (!player)
         return false;
 
@@ -119,6 +117,7 @@
 
 void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, ColorSpace colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier renderingResourceIdentifier)
 {
+    ASSERT(!RunLoop::isMain());
     ASSERT(renderingMode == RenderingMode::Accelerated || renderingMode == RenderingMode::Unaccelerated);
 
     RefPtr<ImageBuffer> imageBuffer;
@@ -269,6 +268,8 @@
 
 void RemoteRenderingBackend::wakeUpAndApplyDisplayList(const GPUProcessWakeupMessageArguments& arguments)
 {
+    ASSERT(!RunLoop::isMain());
+
     TraceScope tracingScope(WakeUpAndApplyDisplayListStart, WakeUpAndApplyDisplayListEnd);
     auto destinationImageBuffer = makeRefPtr(m_remoteResourceCache.cachedImageBuffer(arguments.destinationImageBufferIdentifier));
     if (UNLIKELY(!destinationImageBuffer)) {
@@ -323,6 +324,8 @@
 
 void RemoteRenderingBackend::getImageData(AlphaPremultiplication outputFormat, IntRect srcRect, RenderingResourceIdentifier renderingResourceIdentifier, CompletionHandler<void(IPC::ImageDataReference&&)>&& completionHandler)
 {
+    ASSERT(!RunLoop::isMain());
+
     RefPtr<ImageData> imageData;
     if (auto imageBuffer = m_remoteResourceCache.cachedImageBuffer(renderingResourceIdentifier))
         imageData = imageBuffer->getImageData(outputFormat, srcRect);
@@ -331,6 +334,8 @@
 
 void RemoteRenderingBackend::getDataURLForImageBuffer(const String& mimeType, Optional<double> quality, WebCore::PreserveResolution preserveResolution, WebCore::RenderingResourceIdentifier renderingResourceIdentifier, CompletionHandler<void(String&&)>&& completionHandler)
 {
+    ASSERT(!RunLoop::isMain());
+
     String urlString;
     if (auto imageBuffer = m_remoteResourceCache.cachedImageBuffer(renderingResourceIdentifier))
         urlString = imageBuffer->toDataURL(mimeType, quality, preserveResolution);
@@ -339,6 +344,8 @@
 
 void RemoteRenderingBackend::getDataForImageBuffer(const String& mimeType, Optional<double> quality, WebCore::RenderingResourceIdentifier renderingResourceIdentifier, CompletionHandler<void(Vector<uint8_t>&&)>&& completionHandler)
 {
+    ASSERT(!RunLoop::isMain());
+
     Vector<uint8_t> data;
     if (auto imageBuffer = m_remoteResourceCache.cachedImageBuffer(renderingResourceIdentifier))
         data = "" quality);
@@ -347,6 +354,8 @@
 
 void RemoteRenderingBackend::getBGRADataForImageBuffer(WebCore::RenderingResourceIdentifier renderingResourceIdentifier, CompletionHandler<void(Vector<uint8_t>&&)>&& completionHandler)
 {
+    ASSERT(!RunLoop::isMain());
+
     Vector<uint8_t> data;
     if (auto imageBuffer = m_remoteResourceCache.cachedImageBuffer(renderingResourceIdentifier))
         data = ""
@@ -355,6 +364,8 @@
 
 void RemoteRenderingBackend::cacheNativeImage(const ShareableBitmap::Handle& handle, RenderingResourceIdentifier renderingResourceIdentifier)
 {
+    ASSERT(!RunLoop::isMain());
+
     auto bitmap = ShareableBitmap::create(handle);
     if (!bitmap)
         return;
@@ -371,6 +382,8 @@
 
 void RemoteRenderingBackend::cacheFont(Ref<Font>&& font)
 {
+    ASSERT(!RunLoop::isMain());
+
     auto identifier = font->renderingResourceIdentifier();
     m_remoteResourceCache.cacheFont(WTFMove(font));
     if (m_pendingWakeupInfo && m_pendingWakeupInfo->shouldPerformWakeup(identifier))
@@ -379,16 +392,20 @@
 
 void RemoteRenderingBackend::deleteAllFonts()
 {
+    ASSERT(!RunLoop::isMain());
     m_remoteResourceCache.deleteAllFonts();
 }
 
 void RemoteRenderingBackend::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier)
 {
+    ASSERT(!RunLoop::isMain());
     m_remoteResourceCache.releaseRemoteResource(renderingResourceIdentifier);
 }
 
 void RemoteRenderingBackend::didCreateSharedDisplayListHandle(DisplayList::ItemBufferIdentifier identifier, const SharedMemory::IPCHandle& handle, RenderingResourceIdentifier destinationBufferIdentifier)
 {
+    ASSERT(!RunLoop::isMain());
+
     if (UNLIKELY(m_sharedDisplayListHandles.contains(identifier))) {
         // FIXME: Add a message check to terminate the web process.
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -65,14 +65,13 @@
 struct RemoteRenderingBackendCreationParameters;
 
 class RemoteRenderingBackend
-    : public IPC::MessageSender
-    , private IPC::MessageReceiver
+    : private IPC::MessageSender
+    , public IPC::Connection::WorkQueueMessageReceiver
     , public WebCore::DisplayList::ItemBufferReadingClient {
 public:
-    static std::unique_ptr<RemoteRenderingBackend> create(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&);
+    static Ref<RemoteRenderingBackend> create(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&);
     virtual ~RemoteRenderingBackend();
 
-    GPUConnectionToWebProcess* gpuConnectionToWebProcess() const;
     RemoteResourceCache& remoteResourceCache() { return m_remoteResourceCache; }
 
     // Rendering operations.
@@ -84,6 +83,8 @@
 
     void setNextItemBufferToRead(WebCore::DisplayList::ItemBufferIdentifier, WebCore::RenderingResourceIdentifier destination);
 
+    void disconnect();
+
 private:
     RemoteRenderingBackend(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&);
 
@@ -141,8 +142,9 @@
         }
     };
 
+    Ref<WorkQueue> m_workQueue;
     RemoteResourceCache m_remoteResourceCache;
-    WeakPtr<GPUConnectionToWebProcess> m_gpuConnectionToWebProcess;
+    Ref<GPUConnectionToWebProcess> m_gpuConnectionToWebProcess;
     RenderingBackendIdentifier m_renderingBackendIdentifier;
     HashMap<WebCore::DisplayList::ItemBufferIdentifier, RefPtr<DisplayListReaderHandle>> m_sharedDisplayListHandles;
     Optional<PendingWakeupInformation> m_pendingWakeupInfo;

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in	2021-01-15 21:51:52 UTC (rev 271533)
@@ -22,7 +22,7 @@
 
 #if ENABLE(GPU_PROCESS)
 
-messages -> RemoteRenderingBackend NotRefCounted {
+messages -> RemoteRenderingBackend {
     CreateImageBuffer(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::ColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat, WebCore::RenderingResourceIdentifier renderingResourceIdentifier)
     WakeUpAndApplyDisplayList(struct WebKit::GPUProcessWakeupMessageArguments arguments)
     GetImageData(enum:uint8_t WebCore::AlphaPremultiplication outputFormat, WebCore::IntRect srcRect, WebCore::RenderingResourceIdentifier renderingResourceIdentifier) -> (IPC::ImageDataReference imageData) Synchronous

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMProxy.cpp (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMProxy.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteLegacyCDMProxy.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -87,11 +87,7 @@
     if (!m_playerId || !m_factory)
         return nullptr;
 
-    auto proxy = m_factory->gpuConnectionToWebProcess().remoteMediaPlayerManagerProxy().getProxy(m_playerId);
-    if (!proxy)
-        return nullptr;
-
-    return proxy->mediaPlayer();
+    return m_factory->gpuConnectionToWebProcess().remoteMediaPlayerManagerProxy().mediaPlayer(m_playerId);
 }
 
 }

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -61,6 +61,9 @@
 
 void RemoteMediaPlayerManagerProxy::createMediaPlayer(MediaPlayerIdentifier identifier, MediaPlayerEnums::MediaEngineIdentifier engineIdentifier, RemoteMediaPlayerProxyConfiguration&& proxyConfiguration, CompletionHandler<void(RemoteMediaPlayerConfiguration&)>&& completionHandler)
 {
+    ASSERT(RunLoop::isMain());
+
+    auto locker = holdLock(m_proxiesLock);
     ASSERT(!m_proxies.contains(identifier));
 
     RemoteMediaPlayerConfiguration playerConfiguration;
@@ -74,6 +77,8 @@
 
 void RemoteMediaPlayerManagerProxy::deleteMediaPlayer(MediaPlayerIdentifier identifier)
 {
+    ASSERT(RunLoop::isMain());
+    auto locker = holdLock(m_proxiesLock);
     if (auto proxy = m_proxies.take(identifier))
         proxy->invalidate();
 }
@@ -168,6 +173,7 @@
 
 void RemoteMediaPlayerManagerProxy::didReceivePlayerMessage(IPC::Connection& connection, IPC::Decoder& decoder)
 {
+    ASSERT(RunLoop::isMain());
     if (auto* player = m_proxies.get(makeObjectIdentifier<MediaPlayerIdentifierType>(decoder.destinationID())))
         player->didReceiveMessage(connection, decoder);
 }
@@ -174,15 +180,18 @@
 
 void RemoteMediaPlayerManagerProxy::didReceiveSyncPlayerMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& encoder)
 {
+    ASSERT(RunLoop::isMain());
     if (auto* player = m_proxies.get(makeObjectIdentifier<MediaPlayerIdentifierType>(decoder.destinationID())))
         player->didReceiveSyncMessage(connection, decoder, encoder);
 }
 
-RemoteMediaPlayerProxy* RemoteMediaPlayerManagerProxy::getProxy(const MediaPlayerIdentifier& identifier)
+// May get called on a background thread.
+RefPtr<MediaPlayer> RemoteMediaPlayerManagerProxy::mediaPlayer(const MediaPlayerIdentifier& identifier)
 {
+    auto locker = holdLock(m_proxiesLock);
     auto results = m_proxies.find(identifier);
     if (results != m_proxies.end())
-        return results->value.get();
+        return results->value->mediaPlayer();
     return nullptr;
 }
 

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h (271532 => 271533)


--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerManagerProxy.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -33,6 +33,7 @@
 #include "TrackPrivateRemoteIdentifier.h"
 #include <WebCore/MediaPlayer.h>
 #include <WebCore/MediaPlayerIdentifier.h>
+#include <wtf/Lock.h>
 #include <wtf/LoggerHelper.h>
 
 namespace WebKit {
@@ -68,7 +69,7 @@
     WTFLogChannel& logChannel() const final;
 #endif
 
-    RemoteMediaPlayerProxy* getProxy(const WebCore::MediaPlayerIdentifier&);
+    RefPtr<WebCore::MediaPlayer> mediaPlayer(const WebCore::MediaPlayerIdentifier&);
 
 private:
     // IPC::MessageReceiver
@@ -86,6 +87,7 @@
     void clearMediaCacheForOrigins(WebCore::MediaPlayerEnums::MediaEngineIdentifier, const String&&, Vector<WebCore::SecurityOriginData>&&);
     void supportsKeySystem(WebCore::MediaPlayerEnums::MediaEngineIdentifier, const String&&, const String&&, CompletionHandler<void(bool)>&&);
 
+    Lock m_proxiesLock;
     HashMap<WebCore::MediaPlayerIdentifier, std::unique_ptr<RemoteMediaPlayerProxy>> m_proxies;
     GPUConnectionToWebProcess& m_gpuConnectionToWebProcess;
 

Modified: trunk/Source/WebKit/Platform/SharedMemory.h (271532 => 271533)


--- trunk/Source/WebKit/Platform/SharedMemory.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/Platform/SharedMemory.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -28,7 +28,7 @@
 
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
-#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
 
 #if USE(UNIX_DOMAIN_SOCKETS)
 #include "Attachment.h"
@@ -56,7 +56,7 @@
 
 namespace WebKit {
 
-class SharedMemory : public RefCounted<SharedMemory> {
+class SharedMemory : public ThreadSafeRefCounted<SharedMemory> {
 public:
     enum class Protection {
         ReadOnly,

Modified: trunk/Source/WebKit/Shared/ShareableBitmap.cpp (271532 => 271533)


--- trunk/Source/WebKit/Shared/ShareableBitmap.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/Shared/ShareableBitmap.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -172,7 +172,6 @@
     , m_configuration(configuration)
     , m_data(data)
 {
-    ASSERT(RunLoop::isMain());
 }
 
 ShareableBitmap::ShareableBitmap(const IntSize& size, Configuration configuration, RefPtr<SharedMemory> sharedMemory)
@@ -181,8 +180,6 @@
     , m_sharedMemory(sharedMemory)
     , m_data(nullptr)
 {
-    ASSERT(RunLoop::isMain());
-
 #if USE(DIRECT2D)
     createSharedResource();
 #endif
@@ -190,8 +187,6 @@
 
 ShareableBitmap::~ShareableBitmap()
 {
-    ASSERT(RunLoop::isMain());
-
     if (!isBackedBySharedMemory())
         ShareableBitmapMalloc::free(m_data);
 #if USE(DIRECT2D)

Modified: trunk/Source/WebKit/Shared/ShareableBitmap.h (271532 => 271533)


--- trunk/Source/WebKit/Shared/ShareableBitmap.h	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/Shared/ShareableBitmap.h	2021-01-15 21:51:52 UTC (rev 271533)
@@ -28,8 +28,8 @@
 #include "SharedMemory.h"
 #include <WebCore/IntRect.h>
 #include <WebCore/PlatformImage.h>
-#include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
 
 #if USE(CG)
 #include "ColorSpaceData.h"
@@ -52,7 +52,7 @@
 
 namespace WebKit {
     
-class ShareableBitmap : public RefCounted<ShareableBitmap> {
+class ShareableBitmap : public ThreadSafeRefCounted<ShareableBitmap> {
 public:
     struct Configuration {
         bool isOpaque { false };

Modified: trunk/Source/WebKit/Shared/cg/ShareableBitmapCG.cpp (271532 => 271533)


--- trunk/Source/WebKit/Shared/cg/ShareableBitmapCG.cpp	2021-01-15 20:57:16 UTC (rev 271532)
+++ trunk/Source/WebKit/Shared/cg/ShareableBitmapCG.cpp	2021-01-15 21:51:52 UTC (rev 271533)
@@ -171,13 +171,6 @@
 
 void ShareableBitmap::releaseBitmapContextData(void* typelessBitmap, void* typelessData)
 {
-    if (!RunLoop::isMain()) {
-        RunLoop::main().dispatch([typelessBitmap, typelessData] {
-            releaseBitmapContextData(typelessBitmap, typelessData);
-        });
-        return;
-    }
-
     ShareableBitmap* bitmap = static_cast<ShareableBitmap*>(typelessBitmap);
     ASSERT_UNUSED(typelessData, bitmap->data() == typelessData);
     bitmap->deref(); // Balanced by ref in createGraphicsContext.
@@ -185,13 +178,6 @@
 
 void ShareableBitmap::releaseDataProviderData(void* typelessBitmap, const void* typelessData, size_t)
 {
-    if (!RunLoop::isMain()) {
-        RunLoop::main().dispatch([typelessBitmap, typelessData] {
-            releaseDataProviderData(typelessBitmap, typelessData, 0);
-        });
-        return;
-    }
-
     ShareableBitmap* bitmap = static_cast<ShareableBitmap*>(typelessBitmap);
     ASSERT_UNUSED(typelessData, bitmap->data() == typelessData);
     bitmap->deref(); // Balanced by ref in createCGImage.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to