Title: [287117] branches/safari-612-branch/Source/WebCore
Revision
287117
Author
alanc...@apple.com
Date
2021-12-15 16:55:07 -0800 (Wed, 15 Dec 2021)

Log Message

Cherry-pick r287079. rdar://problem/85892959

    Twitter scroll stutter: ensure that CA backing store is always deallocated on the main thread
    https://bugs.webkit.org/show_bug.cgi?id=234328
    <rdar://85892959>

    Reviewed by Tim Horton.

    When scrolling pages like Twitter and Facebook we observed CoreAnimation commits on the
    scrolling thread taking longer than they should because CABackingStore objects were being
    released in those transactions.

    Work around this issue by extending the lifetime of CABackingStore objects if we detect that
    they might be entrained into a scrolling tree commit, by virtue of having overlapping main
    thread and scrolling thread commits.

    The logic is contained in PlatformCALayerContentsDelayedReleaser, which puts layer contents
    into a retaining vector when they are being cleared on the layer. They are released at the
    end of a main thread commit; if we detected overlapping commits, then we release on a
    dispatch to extend the lifetime slightly.

    The remaining changes are plumbing to get commit willBegin/didEnd messages to PlatformCALayerContentsDelayedReleaser
    for main and scrolling threads.

    * SourcesCocoa.txt:
    * WebCore.xcodeproj/project.pbxproj:
    * page/scrolling/ScrollingTree.h:
    * page/scrolling/ThreadedScrollingTree.h:
    * page/scrolling/mac/ScrollingCoordinatorMac.h:
    * page/scrolling/mac/ScrollingCoordinatorMac.mm:
    (WebCore::ScrollingCoordinatorMac::willStartPlatformRenderingUpdate):
    (WebCore::ScrollingCoordinatorMac::didCompletePlatformRenderingUpdate):
    * page/scrolling/mac/ScrollingTreeMac.h:
    * page/scrolling/mac/ScrollingTreeMac.mm:
    (ScrollingTreeMac::applyLayerPositionsInternal):
    (ScrollingTreeMac::registerForPlatformRenderingUpdateCallback):
    * platform/graphics/ca/GraphicsLayerCA.cpp:
    (WebCore::GraphicsLayerCA::updateContentsVisibility):
    (WebCore::GraphicsLayerCA::updateDrawsContent):
    * platform/graphics/ca/PlatformCALayer.cpp:
    (WebCore::PlatformCALayer::clearContents):
    * platform/graphics/ca/PlatformCALayer.h:
    * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
    * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
    (WebCore::PlatformCALayerCocoa::setBackingStoreAttached):
    (WebCore::PlatformCALayerCocoa::clearContents):
    * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h: Added.
    (WebCore::PlatformCALayerContentsDelayedReleaser::WTF_GUARDED_BY_LOCK):
    * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm: Added.
    (WebCore::PlatformCALayerContentsDelayedReleaser::singleton):
    (WebCore::PlatformCALayerContentsDelayedReleaser::takeLayerContents):
    (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitWillStart):
    (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitDidEnd):
    (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitWillStart):
    (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitDidEnd):
    (WebCore::PlatformCALayerContentsDelayedReleaser::updateSawOverlappingCommit):
    (WebCore::PlatformCALayerContentsDelayedReleaser::clearRetainedContents):

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287079 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Added Paths

Diff

Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/ChangeLog	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog	2021-12-16 00:55:07 UTC (rev 287117)
@@ -1,3 +1,123 @@
+2021-12-15  Alan Coon  <alanc...@apple.com>
+
+        Cherry-pick r287079. rdar://problem/85892959
+
+    Twitter scroll stutter: ensure that CA backing store is always deallocated on the main thread
+    https://bugs.webkit.org/show_bug.cgi?id=234328
+    <rdar://85892959>
+    
+    Reviewed by Tim Horton.
+    
+    When scrolling pages like Twitter and Facebook we observed CoreAnimation commits on the
+    scrolling thread taking longer than they should because CABackingStore objects were being
+    released in those transactions.
+    
+    Work around this issue by extending the lifetime of CABackingStore objects if we detect that
+    they might be entrained into a scrolling tree commit, by virtue of having overlapping main
+    thread and scrolling thread commits.
+    
+    The logic is contained in PlatformCALayerContentsDelayedReleaser, which puts layer contents
+    into a retaining vector when they are being cleared on the layer. They are released at the
+    end of a main thread commit; if we detected overlapping commits, then we release on a
+    dispatch to extend the lifetime slightly.
+    
+    The remaining changes are plumbing to get commit willBegin/didEnd messages to PlatformCALayerContentsDelayedReleaser
+    for main and scrolling threads.
+    
+    * SourcesCocoa.txt:
+    * WebCore.xcodeproj/project.pbxproj:
+    * page/scrolling/ScrollingTree.h:
+    * page/scrolling/ThreadedScrollingTree.h:
+    * page/scrolling/mac/ScrollingCoordinatorMac.h:
+    * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+    (WebCore::ScrollingCoordinatorMac::willStartPlatformRenderingUpdate):
+    (WebCore::ScrollingCoordinatorMac::didCompletePlatformRenderingUpdate):
+    * page/scrolling/mac/ScrollingTreeMac.h:
+    * page/scrolling/mac/ScrollingTreeMac.mm:
+    (ScrollingTreeMac::applyLayerPositionsInternal):
+    (ScrollingTreeMac::registerForPlatformRenderingUpdateCallback):
+    * platform/graphics/ca/GraphicsLayerCA.cpp:
+    (WebCore::GraphicsLayerCA::updateContentsVisibility):
+    (WebCore::GraphicsLayerCA::updateDrawsContent):
+    * platform/graphics/ca/PlatformCALayer.cpp:
+    (WebCore::PlatformCALayer::clearContents):
+    * platform/graphics/ca/PlatformCALayer.h:
+    * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
+    * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+    (WebCore::PlatformCALayerCocoa::setBackingStoreAttached):
+    (WebCore::PlatformCALayerCocoa::clearContents):
+    * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h: Added.
+    (WebCore::PlatformCALayerContentsDelayedReleaser::WTF_GUARDED_BY_LOCK):
+    * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm: Added.
+    (WebCore::PlatformCALayerContentsDelayedReleaser::singleton):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::takeLayerContents):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitWillStart):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitDidEnd):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitWillStart):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitDidEnd):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::updateSawOverlappingCommit):
+    (WebCore::PlatformCALayerContentsDelayedReleaser::clearRetainedContents):
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287079 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-12-15  Simon Fraser  <simon.fra...@apple.com>
+
+            Twitter scroll stutter: ensure that CA backing store is always deallocated on the main thread
+            https://bugs.webkit.org/show_bug.cgi?id=234328
+            <rdar://85892959>
+
+            Reviewed by Tim Horton.
+
+            When scrolling pages like Twitter and Facebook we observed CoreAnimation commits on the
+            scrolling thread taking longer than they should because CABackingStore objects were being
+            released in those transactions.
+
+            Work around this issue by extending the lifetime of CABackingStore objects if we detect that
+            they might be entrained into a scrolling tree commit, by virtue of having overlapping main
+            thread and scrolling thread commits.
+
+            The logic is contained in PlatformCALayerContentsDelayedReleaser, which puts layer contents
+            into a retaining vector when they are being cleared on the layer. They are released at the
+            end of a main thread commit; if we detected overlapping commits, then we release on a
+            dispatch to extend the lifetime slightly.
+
+            The remaining changes are plumbing to get commit willBegin/didEnd messages to PlatformCALayerContentsDelayedReleaser
+            for main and scrolling threads.
+
+            * SourcesCocoa.txt:
+            * WebCore.xcodeproj/project.pbxproj:
+            * page/scrolling/ScrollingTree.h:
+            * page/scrolling/ThreadedScrollingTree.h:
+            * page/scrolling/mac/ScrollingCoordinatorMac.h:
+            * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+            (WebCore::ScrollingCoordinatorMac::willStartPlatformRenderingUpdate):
+            (WebCore::ScrollingCoordinatorMac::didCompletePlatformRenderingUpdate):
+            * page/scrolling/mac/ScrollingTreeMac.h:
+            * page/scrolling/mac/ScrollingTreeMac.mm:
+            (ScrollingTreeMac::applyLayerPositionsInternal):
+            (ScrollingTreeMac::registerForPlatformRenderingUpdateCallback):
+            * platform/graphics/ca/GraphicsLayerCA.cpp:
+            (WebCore::GraphicsLayerCA::updateContentsVisibility):
+            (WebCore::GraphicsLayerCA::updateDrawsContent):
+            * platform/graphics/ca/PlatformCALayer.cpp:
+            (WebCore::PlatformCALayer::clearContents):
+            * platform/graphics/ca/PlatformCALayer.h:
+            * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
+            * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+            (WebCore::PlatformCALayerCocoa::setBackingStoreAttached):
+            (WebCore::PlatformCALayerCocoa::clearContents):
+            * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h: Added.
+            (WebCore::PlatformCALayerContentsDelayedReleaser::WTF_GUARDED_BY_LOCK):
+            * platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm: Added.
+            (WebCore::PlatformCALayerContentsDelayedReleaser::singleton):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::takeLayerContents):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitWillStart):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::mainThreadCommitDidEnd):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitWillStart):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitDidEnd):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::updateSawOverlappingCommit):
+            (WebCore::PlatformCALayerContentsDelayedReleaser::clearRetainedContents):
+
 2021-12-13  Alan Coon  <alanc...@apple.com>
 
         Cherry-pick r286907. rdar://problem/86307593

Modified: branches/safari-612-branch/Source/WebCore/SourcesCocoa.txt (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/SourcesCocoa.txt	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/SourcesCocoa.txt	2021-12-16 00:55:07 UTC (rev 287117)
@@ -331,6 +331,7 @@
 platform/graphics/ca/cocoa/PlatformCAAnimationCocoa.mm
 platform/graphics/ca/cocoa/PlatformCAFiltersCocoa.mm
 platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm
+platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm
 platform/graphics/ca/cocoa/WebSystemBackdropLayer.mm
 platform/graphics/ca/cocoa/WebTiledBackingLayer.mm
 platform/graphics/ca/cocoa/WebVideoContainerLayer.mm

Modified: branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-16 00:55:07 UTC (rev 287117)
@@ -6291,6 +6291,8 @@
 		0FA0A0E523AEAA35000EEB94 /* dialog.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = dialog.css; sourceTree = "<group>"; };
 		0FA24D77162DF91900A3F4C0 /* GraphicsLayerUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsLayerUpdater.cpp; sourceTree = "<group>"; };
 		0FA24D78162DF91900A3F4C0 /* GraphicsLayerUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsLayerUpdater.h; sourceTree = "<group>"; };
+		0FA2B233276817540020C7C1 /* PlatformCALayerContentsDelayedReleaser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformCALayerContentsDelayedReleaser.h; sourceTree = "<group>"; };
+		0FA2B235276817550020C7C1 /* PlatformCALayerContentsDelayedReleaser.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformCALayerContentsDelayedReleaser.mm; sourceTree = "<group>"; };
 		0FB0689425243B90001E8E75 /* DisplayTextBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayTextBox.cpp; sourceTree = "<group>"; };
 		0FB0689625243B90001E8E75 /* DisplayTextBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayTextBox.h; sourceTree = "<group>"; };
 		0FB6252C18DE1B1500A07C05 /* GeometryUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeometryUtilities.cpp; sourceTree = "<group>"; };
@@ -20068,6 +20070,8 @@
 				0F13163F16ED0CDE0035CC04 /* PlatformCAFiltersCocoa.mm */,
 				2D70BA1218074DDF0001908A /* PlatformCALayerCocoa.h */,
 				4958782012A57DDF007238AC /* PlatformCALayerCocoa.mm */,
+				0FA2B233276817540020C7C1 /* PlatformCALayerContentsDelayedReleaser.h */,
+				0FA2B235276817550020C7C1 /* PlatformCALayerContentsDelayedReleaser.mm */,
 				31DEA4541B39F4D900F77178 /* WebSystemBackdropLayer.h */,
 				31DEA4531B39F4D900F77178 /* WebSystemBackdropLayer.mm */,
 				0F580FA11496939100FB5BD8 /* WebTiledBackingLayer.h */,

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTree.h (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTree.h	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTree.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -259,7 +259,7 @@
     void setGestureState(std::optional<WheelScrollGestureState>);
     std::optional<WheelScrollGestureState> gestureState();
 
-    void applyLayerPositionsInternal() WTF_REQUIRES_LOCK(m_treeLock);
+    WEBCORE_EXPORT virtual void applyLayerPositionsInternal() WTF_REQUIRES_LOCK(m_treeLock);
     void removeAllNodes() WTF_REQUIRES_LOCK(m_treeLock);
 
     Lock m_treeLock; // Protects the scrolling tree.

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -50,6 +50,7 @@
     void willStartRenderingUpdate() final;
     void didCompleteRenderingUpdate() final;
 
+    void willStartPlatformRenderingUpdate() final;
     void didCompletePlatformRenderingUpdate() final;
 
     void updateTiledScrollingIndicator();

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2021-12-16 00:55:07 UTC (rev 287117)
@@ -33,6 +33,7 @@
 #import "FrameView.h"
 #import "Logging.h"
 #import "Page.h"
+#import "PlatformCALayerContentsDelayedReleaser.h"
 #import "PlatformWheelEvent.h"
 #import "Region.h"
 #import "ScrollingStateTree.h"
@@ -135,9 +136,15 @@
     downcast<ThreadedScrollingTree>(scrollingTree())->didCompleteRenderingUpdate();
 }
 
+void ScrollingCoordinatorMac::willStartPlatformRenderingUpdate()
+{
+    PlatformCALayerContentsDelayedReleaser::singleton().mainThreadCommitWillStart();
+}
+
 void ScrollingCoordinatorMac::didCompletePlatformRenderingUpdate()
 {
     downcast<ThreadedScrollingTree>(scrollingTree())->didCompletePlatformRenderingUpdate();
+    PlatformCALayerContentsDelayedReleaser::singleton().mainThreadCommitDidEnd();
 }
 
 void ScrollingCoordinatorMac::updateTiledScrollingIndicator()

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.h (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.h	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -55,6 +55,9 @@
     void deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) final;
     void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) final;
 
+    void registerForPlatformRenderingUpdateCallback();
+    void applyLayerPositionsInternal() final WTF_REQUIRES_LOCK(m_treeLock);
+
     void lockLayersForHitTesting() final WTF_ACQUIRES_LOCK(m_layerHitTestMutex);
     void unlockLayersForHitTesting() final WTF_RELEASES_LOCK(m_layerHitTestMutex);
 

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeMac.mm	2021-12-16 00:55:07 UTC (rev 287117)
@@ -28,6 +28,7 @@
 
 #import "Logging.h"
 #import "PlatformCALayer.h"
+#import "PlatformCALayerContentsDelayedReleaser.h"
 #import "ScrollingTreeFixedNode.h"
 #import "ScrollingTreeFrameHostingNode.h"
 #import "ScrollingTreeFrameScrollingNodeMac.h"
@@ -38,6 +39,7 @@
 #import "WebCoreCALayerExtras.h"
 #import "WebLayer.h"
 #import "WheelEventTestMonitor.h"
+#import <pal/spi/cocoa/QuartzCoreSPI.h>
 #import <wtf/text/TextStream.h>
 
 #if ENABLE(ASYNC_SCROLLING) && ENABLE(SCROLLING_THREAD)
@@ -240,6 +242,25 @@
     m_layerHitTestMutex.unlock();
 }
 
+void ScrollingTreeMac::applyLayerPositionsInternal()
+{
+    if (ScrollingThread::isCurrentThread())
+        registerForPlatformRenderingUpdateCallback();
+
+    ThreadedScrollingTree::applyLayerPositionsInternal();
+}
+
+void ScrollingTreeMac::registerForPlatformRenderingUpdateCallback()
+{
+    [CATransaction addCommitHandler:[] {
+        PlatformCALayerContentsDelayedReleaser::singleton().scrollingThreadCommitWillStart();
+    } forPhase:kCATransactionPhasePreLayout];
+
+    [CATransaction addCommitHandler:[] {
+        PlatformCALayerContentsDelayedReleaser::singleton().scrollingThreadCommitDidEnd();
+    } forPhase:kCATransactionPhasePostCommit];
+}
+
 void ScrollingTreeMac::setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&& monitor)
 {
     m_wheelEventTestMonitor = WTFMove(monitor);

Modified: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2021-12-16 00:55:07 UTC (rev 287117)
@@ -2278,7 +2278,7 @@
         if (m_backdropLayer)
             m_backdropLayer->setHidden(false);
     } else {
-        m_layer->setContents(nullptr);
+        m_layer->clearContents();
 
         if (m_layerClones) {
             for (auto& layer : m_layerClones->primaryLayerClones.values())
@@ -2593,7 +2593,7 @@
         m_layer->setNeedsDisplay();
         m_hasEverPainted = false;
     } else {
-        m_layer->setContents(nullptr);
+        m_layer->clearContents();
         if (m_layerClones) {
             for (auto& layer : m_layerClones->primaryLayerClones.values())
                 layer->setContents(nullptr);

Modified: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.cpp (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.cpp	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.cpp	2021-12-16 00:55:07 UTC (rev 287117)
@@ -199,6 +199,11 @@
     return *sharedPool;
 }
 
+void PlatformCALayer::clearContents()
+{
+    setContents(nullptr);
+}
+
 void PlatformCALayer::dumpAdditionalProperties(TextStream&, OptionSet<PlatformLayerTreeAsTextFlags>)
 {
 }

Modified: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.h (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.h	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/PlatformCALayer.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -189,6 +189,7 @@
     virtual bool hasContents() const = 0;
     virtual CFTypeRef contents() const = 0;
     virtual void setContents(CFTypeRef) = 0;
+    virtual void clearContents();
 
     virtual void setContentsRect(const FloatRect&) = 0;
 

Modified: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -120,6 +120,7 @@
     bool hasContents() const override;
     CFTypeRef contents() const override;
     void setContents(CFTypeRef) override;
+    void clearContents() override;
 
     void setContentsRect(const FloatRect&) override;
 

Modified: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm (287116 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm	2021-12-16 00:52:57 UTC (rev 287116)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm	2021-12-16 00:55:07 UTC (rev 287117)
@@ -35,6 +35,7 @@
 #import "Model.h"
 #import "PlatformCAAnimationCocoa.h"
 #import "PlatformCAFilters.h"
+#import "PlatformCALayerContentsDelayedReleaser.h"
 #import "ScrollbarThemeMac.h"
 #import "TileController.h"
 #import "TiledBacking.h"
@@ -684,7 +685,7 @@
     if (attached)
         setNeedsDisplay();
     else
-        setContents(nullptr);
+        clearContents();
 }
 
 bool PlatformCALayerCocoa::backingStoreAttached() const
@@ -790,6 +791,15 @@
     return (__bridge CFTypeRef)[m_layer contents];
 }
 
+void PlatformCALayerCocoa::clearContents()
+{
+#if PLATFORM(MAC)
+    PlatformCALayerContentsDelayedReleaser::singleton().takeLayerContents(*this);
+#else
+    setContents(nullptr);
+#endif
+}
+
 void PlatformCALayerCocoa::setContents(CFTypeRef value)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS

Added: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h (0 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h	                        (rev 0)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.h	2021-12-16 00:55:07 UTC (rev 287117)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(MAC)
+
+#include <wtf/Lock.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WebCore {
+
+class PlatformCALayer;
+
+// This class exists to work around rdar://85892959, where CABackingStore objects would get released on the ScrollingThread
+// during scrolling commits, which can take long enough to cause scrolling frame drops.
+class PlatformCALayerContentsDelayedReleaser : ThreadSafeRefCounted<PlatformCALayerContentsDelayedReleaser> {
+    WTF_MAKE_NONCOPYABLE(PlatformCALayerContentsDelayedReleaser);
+public:
+    static PlatformCALayerContentsDelayedReleaser& singleton();
+
+    void takeLayerContents(PlatformCALayer&);
+    
+    void mainThreadCommitWillStart();
+    void mainThreadCommitDidEnd();
+
+    void scrollingThreadCommitWillStart();
+    void scrollingThreadCommitDidEnd();
+
+private:
+    friend LazyNeverDestroyed<PlatformCALayerContentsDelayedReleaser>;
+    
+    PlatformCALayerContentsDelayedReleaser();
+
+    void updateSawOverlappingCommit() WTF_REQUIRES_LOCK(m_lock);
+    void clearRetainedContents();
+
+    Vector<RetainPtr<CFTypeRef>> m_retainedContents;
+
+    Lock m_lock;
+    unsigned m_inMainThreadCommitEntryCount WTF_GUARDED_BY_LOCK(m_lock) { 0 };
+    unsigned m_scrollingThreadCommitEntryCount WTF_GUARDED_BY_LOCK(m_lock) { 0 };
+    bool m_hadOverlappingCommit WTF_GUARDED_BY_LOCK(m_lock) { false };
+};
+
+} // namespace WebCore
+
+#endif // PLATFORM(MAC)

Added: branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm (0 => 287117)


--- branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm	                        (rev 0)
+++ branches/safari-612-branch/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerContentsDelayedReleaser.mm	2021-12-16 00:55:07 UTC (rev 287117)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "config.h"
+#import "PlatformCALayerContentsDelayedReleaser.h"
+
+#if PLATFORM(MAC)
+
+#import "PlatformCALayer.h"
+#import <wtf/RunLoop.h>
+
+namespace WebCore {
+
+PlatformCALayerContentsDelayedReleaser& PlatformCALayerContentsDelayedReleaser::singleton()
+{
+    static LazyNeverDestroyed<PlatformCALayerContentsDelayedReleaser> delayedReleaser;
+    static std::once_flag onceFlag;
+    std::call_once(onceFlag, [] {
+        delayedReleaser.construct();
+    });
+
+    return delayedReleaser;
+}
+
+PlatformCALayerContentsDelayedReleaser::PlatformCALayerContentsDelayedReleaser() = default;
+
+void PlatformCALayerContentsDelayedReleaser::takeLayerContents(PlatformCALayer& layer)
+{
+    ASSERT(isMainThread());
+
+    auto retainedContents = RetainPtr { layer.contents() };
+    if (retainedContents)
+        m_retainedContents.append(WTFMove(retainedContents));
+    layer.setContents(nullptr);
+}
+
+void PlatformCALayerContentsDelayedReleaser::mainThreadCommitWillStart()
+{
+    Locker locker { m_lock };
+    ++m_inMainThreadCommitEntryCount;
+    updateSawOverlappingCommit();
+}
+
+void PlatformCALayerContentsDelayedReleaser::mainThreadCommitDidEnd()
+{
+    bool bothCommitsDone;
+    bool hadOverlappingCommit;
+    {
+        Locker locker { m_lock };
+        ASSERT(m_inMainThreadCommitEntryCount);
+        --m_inMainThreadCommitEntryCount;
+        bothCommitsDone = !m_scrollingThreadCommitEntryCount && !m_inMainThreadCommitEntryCount;
+        hadOverlappingCommit = m_hadOverlappingCommit;
+    }
+
+    if (bothCommitsDone) {
+        if (hadOverlappingCommit && m_retainedContents.size()) {
+            RunLoop::main().dispatch([] {
+                PlatformCALayerContentsDelayedReleaser::singleton().clearRetainedContents();
+            });
+            return;
+        }
+
+        clearRetainedContents();
+    }
+}
+
+void PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitWillStart()
+{
+    ASSERT(!isMainThread());
+    Locker locker { m_lock };
+    ++m_scrollingThreadCommitEntryCount;
+    updateSawOverlappingCommit();
+}
+
+void PlatformCALayerContentsDelayedReleaser::scrollingThreadCommitDidEnd()
+{
+    ASSERT(!isMainThread());
+    Locker locker { m_lock };
+
+    ASSERT(m_scrollingThreadCommitEntryCount);
+    --m_scrollingThreadCommitEntryCount;
+    if (!m_scrollingThreadCommitEntryCount && !m_inMainThreadCommitEntryCount) {
+        if (m_hadOverlappingCommit) {
+            // m_retainedContents might be empty (it's not protected by the lock so we can't check it here),
+            // so this might be a pointless dispatch, but m_hadOverlappingCommit is rare.
+            RunLoop::main().dispatch([] {
+                PlatformCALayerContentsDelayedReleaser::singleton().clearRetainedContents();
+            });
+        }
+    }
+}
+
+void PlatformCALayerContentsDelayedReleaser::updateSawOverlappingCommit()
+{
+    m_hadOverlappingCommit |= (m_inMainThreadCommitEntryCount && m_scrollingThreadCommitEntryCount);
+}
+
+void PlatformCALayerContentsDelayedReleaser::clearRetainedContents()
+{
+    ASSERT(isMainThread());
+    m_retainedContents.clear();
+}
+
+} // namespace WebCore
+
+#endif
+
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to