⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286975 in webkit


Ignore:
Timestamp:
Dec 13, 2021, 12:56:57 PM (5 years ago)
Author:
Alan Coon
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

Location:
branches/safari-612-branch/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-612-branch/Source/WebCore/ChangeLog

    r286974 r286975  
     12021-12-13  Alan Coon  <alancoon@apple.com>
     2
     3        Cherry-pick r286932. rdar://problem/86385697
     4
     5    Ensure that the scrolling thread always commits layer position changes to reduce scrolling stutters
     6    https://bugs.webkit.org/show_bug.cgi?id=234213
     7   
     8    Reviewed by Tim Horton.
     9   
     10    On a page where CA commits on the main thread take a long time (e.g. because of expensive
     11    painting), it's possible that the main thread has updated the scrolling layer position, and
     12    then the scrolling thread detects that the commit is taking a long time and attempts to
     13    trigger its own commit, but because the layer position property doesn't change, no commit
     14    occurs.
     15   
     16    Work around this by setting the layer position to 0,0 and back when we're on the scrolling
     17    thread. Only do this if the scroll position changed since the last display refresh to avoid
     18    triggering redundant commits.
     19   
     20    Ideally we'd traverse the scrolling tree and do this for every scrolling node, but scrolling
     21    trees can get large so for now just apply this to the root node.
     22   
     23    * page/scrolling/ScrollingTreeScrollingNode.cpp:
     24    (WebCore::ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh):
     25    * page/scrolling/ScrollingTreeScrollingNode.h:
     26    * page/scrolling/ThreadedScrollingTree.cpp:
     27    (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
     28    (WebCore::ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh):
     29    * page/scrolling/ThreadedScrollingTree.h:
     30    * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     31    (WebCore::ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers):
     32   
     33    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@286932 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     34
     35    2021-12-12  Simon Fraser  <simon.fraser@apple.com>
     36
     37            Ensure that the scrolling thread always commits layer position changes to reduce scrolling stutters
     38            https://bugs.webkit.org/show_bug.cgi?id=234213
     39
     40            Reviewed by Tim Horton.
     41
     42            On a page where CA commits on the main thread take a long time (e.g. because of expensive
     43            painting), it's possible that the main thread has updated the scrolling layer position, and
     44            then the scrolling thread detects that the commit is taking a long time and attempts to
     45            trigger its own commit, but because the layer position property doesn't change, no commit
     46            occurs.
     47
     48            Work around this by setting the layer position to 0,0 and back when we're on the scrolling
     49            thread. Only do this if the scroll position changed since the last display refresh to avoid
     50            triggering redundant commits.
     51
     52            Ideally we'd traverse the scrolling tree and do this for every scrolling node, but scrolling
     53            trees can get large so for now just apply this to the root node.
     54
     55            * page/scrolling/ScrollingTreeScrollingNode.cpp:
     56            (WebCore::ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh):
     57            * page/scrolling/ScrollingTreeScrollingNode.h:
     58            * page/scrolling/ThreadedScrollingTree.cpp:
     59            (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
     60            (WebCore::ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh):
     61            * page/scrolling/ThreadedScrollingTree.h:
     62            * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
     63            (WebCore::ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers):
     64
    1652021-12-13  Alan Coon  <alancoon@apple.com>
    266
  • branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r286692 r286975  
    274274}
    275275
     276void ScrollingTreeScrollingNode::updateScrollPositionAtLastDisplayRefresh()
     277{
     278    m_scrollPositionAtLastDisplayRefresh = m_currentScrollPosition;
     279}
     280
    276281bool ScrollingTreeScrollingNode::scrollPositionAndLayoutViewportMatch(const FloatPoint& position, std::optional<FloatRect>)
    277282{
  • branches/safari-612-branch/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h

    r286692 r286975  
    129129    virtual void repositionScrollingLayers() { }
    130130    virtual void repositionRelatedLayers() { }
     131   
     132    void updateScrollPositionAtLastDisplayRefresh();
     133    std::optional<FloatPoint> scrollPositionAtLastDisplayRefresh() { return m_scrollPositionAtLastDisplayRefresh; };
    131134
    132135    void applyLayerPositions() override;
     
    162165    std::optional<unsigned> m_currentVerticalSnapPointIndex;
    163166    ScrollableAreaParameters m_scrollableAreaParameters;
     167    std::optional<FloatPoint> m_scrollPositionAtLastDisplayRefresh;
    164168#if ENABLE(SCROLLING_THREAD)
    165169    OptionSet<SynchronousScrollingReason> m_synchronousScrollingReasons;
  • branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp

    r286688 r286975  
    407407        break;
    408408    }
     409   
     410    storeScrollPositionsAtLastDisplayRefresh();
    409411}
    410412
     
    429431}
    430432
     433void ThreadedScrollingTree::storeScrollPositionsAtLastDisplayRefresh()
     434{
     435    // 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;
     436    // ScrollingTreeFrameScrollingNodeMac::repositionScrollingLayers() uses the state to know whether it should force a commit.
     437    if (auto* rootNode = this->rootNode())
     438        rootNode->updateScrollPositionAtLastDisplayRefresh();
     439}
     440
    431441} // namespace WebCore
    432442
  • branches/safari-612-branch/Source/WebCore/page/scrolling/ThreadedScrollingTree.h

    r286687 r286975  
    9595    void delayedRenderingUpdateDetectionTimerFired();
    9696
     97    void storeScrollPositionsAtLastDisplayRefresh() WTF_REQUIRES_LOCK(m_treeLock);
     98   
    9799    Seconds frameDuration();
    98100    Seconds maxAllowableRenderingUpdateDurationForSynchronization();
  • branches/safari-612-branch/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm

    r279218 r286975  
    3636#import "ScrollingCoordinator.h"
    3737#import "ScrollingStateTree.h"
     38#import "ScrollingThread.h"
    3839#import "ScrollingTree.h"
    3940#import "TileController.h"
     
    167168{
    168169    BEGIN_BLOCK_OBJC_EXCEPTIONS
     170
     171    auto* layer = static_cast<CALayer*>(scrolledContentsLayer());
     172    if (ScrollingThread::isCurrentThread()) {
     173        // If we're committing on the scrolling thread, it means that ThreadedScrollingTree is in "desynchronized" mode.
     174        // The main thread may already have set the same layer position, but here we need to trigger a scrolling thread commit to
     175        // ensure that the scroll happens even when the main thread commit is taking a long time. So make sure the layer property changes
     176        // when there has been a scroll position change.
     177        if (scrollPositionAtLastDisplayRefresh() && scrollPositionAtLastDisplayRefresh().value() != currentScrollPosition())
     178            layer.position = CGPointZero;
     179    }
     180
    169181    // We use scroll position here because the root content layer is offset to account for scrollOrigin (see FrameView::positionForRootContentLayer).
    170     static_cast<CALayer*>(scrolledContentsLayer()).position = -currentScrollPosition();
     182    layer.position = -currentScrollPosition();
    171183    END_BLOCK_OBJC_EXCEPTIONS
    172184}
Note: See TracChangeset for help on using the changeset viewer.