Title: [286975] branches/safari-612-branch/Source/WebCore
Revision
286975
Author
alanc...@apple.com
Date
2021-12-13 12:56:57 -0800 (Mon, 13 Dec 2021)

Log Message

Cherry-pick r286932. rdar://problem/86385697

    Ensure that the scrolling thread always commits layer position changes to reduce scrolling stutters
    https://bugs.webkit.org/show_bug.cgi?id=234213

    Reviewed by Tim Horton.

    On a page where CA commits on the main thread take a long time (e.g. because of expensive
    painting), it's possible that the main thread has updated the scrolling layer position, and
    then the scrolling thread detects that the commit is taking a long time and attempts to
    trigger its own commit, but because the layer position property doesn't change, no commit
    occurs.

    Work around this by setting the layer position to 0,0 and back when we're on the scrolling
    thread. Only do this if the scroll position changed since the last display refresh to avoid
    triggering redundant commits.

    Ideally we'd traverse the scrolling tree and do this for every scrolling node, but scrolling
    trees can get large so for now just apply this to the root node.

    * page/scrolling/ScrollingTreeScrollingNode.cpp:
    (WebCore::ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh):
    * page/scrolling/ScrollingTreeScrollingNode.h:
    * page/scrolling/ThreadedScrollingTree.cpp:
    (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
    (WebCore::ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh):
    * page/scrolling/ThreadedScrollingTree.h:
    * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
    (WebCore::ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers):

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

Modified Paths

Diff

Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/ChangeLog	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog	2021-12-13 20:56:57 UTC (rev 286975)
@@ -1,5 +1,69 @@
 2021-12-13  Alan Coon  <alanc...@apple.com>
 
+        Cherry-pick r286932. rdar://problem/86385697
+
+    Ensure that the scrolling thread always commits layer position changes to reduce scrolling stutters
+    https://bugs.webkit.org/show_bug.cgi?id=234213
+    
+    Reviewed by Tim Horton.
+    
+    On a page where CA commits on the main thread take a long time (e.g. because of expensive
+    painting), it's possible that the main thread has updated the scrolling layer position, and
+    then the scrolling thread detects that the commit is taking a long time and attempts to
+    trigger its own commit, but because the layer position property doesn't change, no commit
+    occurs.
+    
+    Work around this by setting the layer position to 0,0 and back when we're on the scrolling
+    thread. Only do this if the scroll position changed since the last display refresh to avoid
+    triggering redundant commits.
+    
+    Ideally we'd traverse the scrolling tree and do this for every scrolling node, but scrolling
+    trees can get large so for now just apply this to the root node.
+    
+    * page/scrolling/ScrollingTreeScrollingNode.cpp:
+    (WebCore::ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh):
+    * page/scrolling/ScrollingTreeScrollingNode.h:
+    * page/scrolling/ThreadedScrollingTree.cpp:
+    (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
+    (WebCore::ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh):
+    * page/scrolling/ThreadedScrollingTree.h:
+    * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+    (WebCore::ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers):
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@286932 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-12-12  Simon Fraser  <simon.fra...@apple.com>
+
+            Ensure that the scrolling thread always commits layer position changes to reduce scrolling stutters
+            https://bugs.webkit.org/show_bug.cgi?id=234213
+
+            Reviewed by Tim Horton.
+
+            On a page where CA commits on the main thread take a long time (e.g. because of expensive
+            painting), it's possible that the main thread has updated the scrolling layer position, and
+            then the scrolling thread detects that the commit is taking a long time and attempts to
+            trigger its own commit, but because the layer position property doesn't change, no commit
+            occurs.
+
+            Work around this by setting the layer position to 0,0 and back when we're on the scrolling
+            thread. Only do this if the scroll position changed since the last display refresh to avoid
+            triggering redundant commits.
+
+            Ideally we'd traverse the scrolling tree and do this for every scrolling node, but scrolling
+            trees can get large so for now just apply this to the root node.
+
+            * page/scrolling/ScrollingTreeScrollingNode.cpp:
+            (WebCore::ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh):
+            * page/scrolling/ScrollingTreeScrollingNode.h:
+            * page/scrolling/ThreadedScrollingTree.cpp:
+            (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
+            (WebCore::ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh):
+            * page/scrolling/ThreadedScrollingTree.h:
+            * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+            (WebCore::ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers):
+
+2021-12-13  Alan Coon  <alanc...@apple.com>
+
         Cherry-pick r286858. rdar://problem/86423741
 
     Use simpler idioms for std::less and std::greater possible in modern C++

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2021-12-13 20:56:57 UTC (rev 286975)
@@ -273,6 +273,11 @@
     scrollingTree().scrollingTreeNodeDidScroll(*this, action);
 }
 
+void ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh()
+{
+    m_scrollPositionAtLastDisplayRefresh = m_currentScrollPosition;
+}
+
 bool ScrollingTreeScrollingNode::scrollPositionAndLayoutViewportMatch(const FloatPoint& position, std::optional<FloatRect>)
 {
     return position == m_currentScrollPosition;

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2021-12-13 20:56:57 UTC (rev 286975)
@@ -128,6 +128,9 @@
 
     virtual void repositionScrollingLayers() { }
     virtual void repositionRelatedLayers() { }
+    
+    void updateScrollPositionAtLastDisplayRefresh();
+    std::optional<FloatPoint> scrollPositionAtLastDisplayRefresh() { return m_scrollPositionAtLastDisplayRefresh; };
 
     void applyLayerPositions() override;
 
@@ -161,6 +164,7 @@
     std::optional<unsigned> m_currentHorizontalSnapPointIndex;
     std::optional<unsigned> m_currentVerticalSnapPointIndex;
     ScrollableAreaParameters m_scrollableAreaParameters;
+    std::optional<FloatPoint> m_scrollPositionAtLastDisplayRefresh;
 #if ENABLE(SCROLLING_THREAD)
     OptionSet<SynchronousScrollingReason> m_synchronousScrollingReasons;
 #endif

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-12-13 20:56:57 UTC (rev 286975)
@@ -406,6 +406,8 @@
     case SynchronizationState::Desynchronized:
         break;
     }
+    
+    storeScrollPositionsAtLastDisplayRefresh();
 }
 
 void ThreadedScrollingTree::displayDidRefresh(PlatformDisplayID displayID)
@@ -428,6 +430,14 @@
     });
 }
 
+void ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh()
+{
+    // Ideally this would be a tree walk for every scrolling node, but scrolling trees can get big so for now just do this for the root;
+    // ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers() uses the state to know whether it should force a commit.
+    if (auto* rootNode = this->rootNode())
+        rootNode->updateScrollPositionAtLastDisplayRefresh();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(ASYNC_SCROLLING) && ENABLE(SCROLLING_THREAD)

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.h (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-12-13 20:56:57 UTC (rev 286975)
@@ -94,6 +94,8 @@
     void scheduleDelayedRenderingUpdateDetectionTimer(Seconds) WTF_REQUIRES_LOCK(m_treeLock);
     void delayedRenderingUpdateDetectionTimerFired();
 
+    void storeScrollPositionsAtLastDisplayRefresh() WTF_REQUIRES_LOCK(m_treeLock);
+    
     Seconds frameDuration();
     Seconds maxAllowableRenderingUpdateDurationForSynchronization();
 

Modified: branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (286974 => 286975)


--- branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2021-12-13 20:56:53 UTC (rev 286974)
+++ branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2021-12-13 20:56:57 UTC (rev 286975)
@@ -35,6 +35,7 @@
 #import "ScrollableArea.h"
 #import "ScrollingCoordinator.h"
 #import "ScrollingStateTree.h"
+#import "ScrollingThread.h"
 #import "ScrollingTree.h"
 #import "TileController.h"
 #import "WebCoreCALayerExtras.h"
@@ -166,8 +167,19 @@
 void ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers()
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS
+
+    auto* layer = static_cast<CALayer*>(scrolledContentsLayer());
+    if (ScrollingThread::isCurrentThread()) {
+        // If we're committing on the scrolling thread, it means that ThreadedScrollingTree is in "desynchronized" mode.
+        // The main thread may already have set the same layer position, but here we need to trigger a scrolling thread commit to
+        // ensure that the scroll happens even when the main thread commit is taking a long time. So make sure the layer property changes
+        // when there has been a scroll position change.
+        if (scrollPositionAtLastDisplayRefresh() && scrollPositionAtLastDisplayRefresh().value() != currentScrollPosition())
+            layer.position = CGPointZero;
+    }
+
     // We use scroll position here because the root content layer is offset to account for scrollOrigin (see FrameView::positionForRootContentLayer).
-    static_cast<CALayer*>(scrolledContentsLayer()).position = -currentScrollPosition();
+    layer.position = -currentScrollPosition();
     END_BLOCK_OBJC_EXCEPTIONS
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to