Title: [285094] trunk/Source
Revision
285094
Author
[email protected]
Date
2021-10-31 08:18:55 -0700 (Sun, 31 Oct 2021)

Log Message

Scroll animations should run at 120Hz on 120Hz displays
https://bugs.webkit.org/show_bug.cgi?id=232534

Reviewed by Tim Horton.

Source/WebCore:

Scroll animations on the scrolling thread were driven by a 60Hz timer in
ScrollingTreeScrollingNodeDelegateMac. Replace that with a mechanism that drives them from
ThreadedScrollingTree::displayDidRefreshOnScrollingThread(), which is called at the maximum
display refresh frequency.

We leverage startAnimationCallback/stopAnimationCallback which update the HashSet of
animating nodes on scrolling tree, and iterate this set in the callback to service the
animations.

Change some ScrollingTree terminology from "AnimatedScroll" to "ScrollAnimation" to indicate
that they are about all kinds of scroll animations (e.g. rubberbanding), not just animated
scrolls.

A side effect of removing the ScrollingTreeScrollingNodeDelegateMac was that there was no
code path that triggered continual "displayDidRefresh" notifications (which originate in the
UI process). We need something to keep the displayDidRefresh notifications coming. To fix
this, have ScrollingCoordinatorMac call scheduleRenderingUpdate() when an animation starts,
and in each rendering update while there are active animations. This doesn't trigger
additional rendering updates; these will happen anyway as a side effect of scrolling tree
scrolls bouncing to the main thread. Also worth noting is that the scrolling thread will get
120Hz updates, even if we're only triggering main thread rendering updates, because of
existing WebPageProxy hasActiveAnimatedScroll state.

Exercised by existing tests.

* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::isScrollAnimationInProgressForNode):
(WebCore::ScrollingTree::setScrollAnimationInProgressForNode):
(WebCore::ScrollingTree::hasNodeWithActiveScrollAnimations):
(WebCore::ScrollingTree::nodesWithActiveScrollAnimations):
(WebCore::ScrollingTree::isAnimatedScrollInProgressForNode): Deleted.
(WebCore::ScrollingTree::setAnimatedScrollInProgressForNode): Deleted.
(WebCore::ScrollingTree::hasNodeWithActiveAnimatedScroll): Deleted.
* page/scrolling/ScrollingTree.h:
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::willStartAnimatedScroll):
(WebCore::ScrollingTreeScrollingNode::didStopAnimatedScroll):
(WebCore::ScrollingTreeScrollingNode::setScrollAnimationInProgress):
* page/scrolling/ScrollingTreeScrollingNode.h:
* page/scrolling/ScrollingTreeScrollingNodeDelegate.h:
* page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::scrollingThreadIsActive):
(WebCore::ThreadedScrollingTree::serviceScrollAnimations):
(WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
* page/scrolling/ThreadedScrollingTree.h:
* page/scrolling/mac/ScrollingCoordinatorMac.h:
* page/scrolling/mac/ScrollingCoordinatorMac.mm:
(WebCore::ScrollingCoordinatorMac::didCompleteRenderingUpdate):
(WebCore::ScrollingCoordinatorMac::hasNodeWithAnimatedScrollChanged):
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::startAnimatedScrollToPosition):
(WebCore::ScrollingTreeFrameScrollingNodeMac::serviceScrollAnimation):
(WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
* page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
* page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
(WebCore::ScrollingTreeOverflowScrollingNodeMac::serviceScrollAnimation):
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
(WebCore::ScrollingTreeScrollingNodeDelegateMac::createTimer):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::startAnimationCallback):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::stopAnimationCallback):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::serviceScrollAnimation):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::scrollControllerAnimationTimerFired): Deleted.
* page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp:
(WebCore::ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired):
(WebCore::ScrollingTreeScrollingNodeDelegateNicosia::serviceScrollAnimation):
* page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h:

Source/WebKit:

* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
* WebProcess/WebPage/mac/TiledCoreAnimationScrollingCoordinator.mm:
(WebKit::TiledCoreAnimationScrollingCoordinator::hasNodeWithAnimatedScrollChanged):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (285093 => 285094)


--- trunk/Source/WebCore/ChangeLog	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/ChangeLog	2021-10-31 15:18:55 UTC (rev 285094)
@@ -1,3 +1,79 @@
+2021-10-31  Simon Fraser  <[email protected]>
+
+        Scroll animations should run at 120Hz on 120Hz displays
+        https://bugs.webkit.org/show_bug.cgi?id=232534
+
+        Reviewed by Tim Horton.
+
+        Scroll animations on the scrolling thread were driven by a 60Hz timer in
+        ScrollingTreeScrollingNodeDelegateMac. Replace that with a mechanism that drives them from
+        ThreadedScrollingTree::displayDidRefreshOnScrollingThread(), which is called at the maximum
+        display refresh frequency.
+
+        We leverage startAnimationCallback/stopAnimationCallback which update the HashSet of
+        animating nodes on scrolling tree, and iterate this set in the callback to service the
+        animations.
+        
+        Change some ScrollingTree terminology from "AnimatedScroll" to "ScrollAnimation" to indicate
+        that they are about all kinds of scroll animations (e.g. rubberbanding), not just animated
+        scrolls.
+
+        A side effect of removing the ScrollingTreeScrollingNodeDelegateMac was that there was no
+        code path that triggered continual "displayDidRefresh" notifications (which originate in the
+        UI process). We need something to keep the displayDidRefresh notifications coming. To fix
+        this, have ScrollingCoordinatorMac call scheduleRenderingUpdate() when an animation starts,
+        and in each rendering update while there are active animations. This doesn't trigger
+        additional rendering updates; these will happen anyway as a side effect of scrolling tree
+        scrolls bouncing to the main thread. Also worth noting is that the scrolling thread will get
+        120Hz updates, even if we're only triggering main thread rendering updates, because of
+        existing WebPageProxy hasActiveAnimatedScroll state.
+
+        Exercised by existing tests.
+
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::isScrollAnimationInProgressForNode):
+        (WebCore::ScrollingTree::setScrollAnimationInProgressForNode):
+        (WebCore::ScrollingTree::hasNodeWithActiveScrollAnimations):
+        (WebCore::ScrollingTree::nodesWithActiveScrollAnimations):
+        (WebCore::ScrollingTree::isAnimatedScrollInProgressForNode): Deleted.
+        (WebCore::ScrollingTree::setAnimatedScrollInProgressForNode): Deleted.
+        (WebCore::ScrollingTree::hasNodeWithActiveAnimatedScroll): Deleted.
+        * page/scrolling/ScrollingTree.h:
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::willStartAnimatedScroll):
+        (WebCore::ScrollingTreeScrollingNode::didStopAnimatedScroll):
+        (WebCore::ScrollingTreeScrollingNode::setScrollAnimationInProgress):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        * page/scrolling/ScrollingTreeScrollingNodeDelegate.h:
+        * page/scrolling/ThreadedScrollingTree.cpp:
+        (WebCore::ThreadedScrollingTree::scrollingThreadIsActive):
+        (WebCore::ThreadedScrollingTree::serviceScrollAnimations):
+        (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
+        * page/scrolling/ThreadedScrollingTree.h:
+        * page/scrolling/mac/ScrollingCoordinatorMac.h:
+        * page/scrolling/mac/ScrollingCoordinatorMac.mm:
+        (WebCore::ScrollingCoordinatorMac::didCompleteRenderingUpdate):
+        (WebCore::ScrollingCoordinatorMac::hasNodeWithAnimatedScrollChanged):
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::startAnimatedScrollToPosition):
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::serviceScrollAnimation):
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged):
+        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
+        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeOverflowScrollingNodeMac::serviceScrollAnimation):
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::createTimer):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::startAnimationCallback):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::stopAnimationCallback):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::serviceScrollAnimation):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::scrollControllerAnimationTimerFired): Deleted.
+        * page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp:
+        (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired):
+        (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::serviceScrollAnimation):
+        * page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h:
+
 2021-10-31  Alan Bujtas  <[email protected]>
 
         [LFC][IFC] Add unicode-bidi control characters

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2021-10-31 15:18:55 UTC (rev 285094)
@@ -583,16 +583,16 @@
         m_treeState.nodesWithActiveScrollSnap.remove(nodeID);
 }
 
-bool ScrollingTree::isAnimatedScrollInProgressForNode(ScrollingNodeID nodeID)
+bool ScrollingTree::isScrollAnimationInProgressForNode(ScrollingNodeID nodeID)
 {
     if (!nodeID)
         return false;
 
     Locker locker { m_treeStateLock };
-    return m_treeState.nodesWithActiveAnimatedScrolls.contains(nodeID);
+    return m_treeState.nodesWithActiveScrollAnimations.contains(nodeID);
 }
 
-void ScrollingTree::setAnimatedScrollInProgressForNode(ScrollingNodeID nodeID, bool isAnimatedScrollInProgress)
+void ScrollingTree::setScrollAnimationInProgressForNode(ScrollingNodeID nodeID, bool isScrollAnimationInProgress)
 {
     if (!nodeID)
         return;
@@ -599,24 +599,30 @@
 
     Locker locker { m_treeStateLock };
     
-    bool hadAnyAnimatedScrollingNodes = !m_treeState.nodesWithActiveAnimatedScrolls.isEmpty();
+    bool hadAnyAnimatedScrollingNodes = !m_treeState.nodesWithActiveScrollAnimations.isEmpty();
     
-    if (isAnimatedScrollInProgress)
-        m_treeState.nodesWithActiveAnimatedScrolls.add(nodeID);
+    if (isScrollAnimationInProgress)
+        m_treeState.nodesWithActiveScrollAnimations.add(nodeID);
     else
-        m_treeState.nodesWithActiveAnimatedScrolls.remove(nodeID);
+        m_treeState.nodesWithActiveScrollAnimations.remove(nodeID);
 
-    bool hasAnyAnimatedScrollingNodes = !m_treeState.nodesWithActiveAnimatedScrolls.isEmpty();
+    bool hasAnyAnimatedScrollingNodes = !m_treeState.nodesWithActiveScrollAnimations.isEmpty();
     if (hasAnyAnimatedScrollingNodes != hadAnyAnimatedScrollingNodes)
         hasNodeWithAnimatedScrollChanged(hasAnyAnimatedScrollingNodes);
 }
 
-bool ScrollingTree::hasNodeWithActiveAnimatedScroll()
+bool ScrollingTree::hasNodeWithActiveScrollAnimations()
 {
     Locker locker { m_treeStateLock };
-    return !m_treeState.nodesWithActiveAnimatedScrolls.isEmpty();
+    return !m_treeState.nodesWithActiveScrollAnimations.isEmpty();
 }
 
+HashSet<ScrollingNodeID> ScrollingTree::nodesWithActiveScrollAnimations()
+{
+    Locker locker { m_treeStateLock };
+    return m_treeState.nodesWithActiveScrollAnimations;
+}
+
 void ScrollingTree::setMainFramePinnedState(RectEdges<bool> edgePinningState)
 {
     Locker locker { m_swipeStateLock };

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -113,9 +113,11 @@
     bool isScrollSnapInProgressForNode(ScrollingNodeID);
     void setNodeScrollSnapInProgress(ScrollingNodeID, bool);
 
-    bool isAnimatedScrollInProgressForNode(ScrollingNodeID);
-    void setAnimatedScrollInProgressForNode(ScrollingNodeID, bool);
+    bool isScrollAnimationInProgressForNode(ScrollingNodeID);
+    void setScrollAnimationInProgressForNode(ScrollingNodeID, bool);
 
+    bool hasNodeWithActiveScrollAnimations();
+
     virtual void invalidate() { }
     WEBCORE_EXPORT void commitTreeState(std::unique_ptr<ScrollingStateTree>&&);
     
@@ -247,8 +249,9 @@
     virtual void hasNodeWithAnimatedScrollChanged(bool /* hasNodeWithAnimatedScroll */) { }
 
     bool hasProcessedWheelEventsRecently();
-    bool hasNodeWithActiveAnimatedScroll();
 
+    HashSet<ScrollingNodeID> nodesWithActiveScrollAnimations();
+
     Lock m_treeLock; // Protects the scrolling tree.
 
 private:
@@ -292,7 +295,7 @@
         HashSet<ScrollingNodeID> nodesWithActiveRubberBanding;
         HashSet<ScrollingNodeID> nodesWithActiveScrollSnap;
         HashSet<ScrollingNodeID> nodesWithActiveUserScrolls;
-        HashSet<ScrollingNodeID> nodesWithActiveAnimatedScrolls;
+        HashSet<ScrollingNodeID> nodesWithActiveScrollAnimations;
     };
     
     Lock m_treeStateLock;

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2021-10-31 15:18:55 UTC (rev 285094)
@@ -225,13 +225,21 @@
     scrollingTree().setNodeScrollSnapInProgress(scrollingNodeID(), isSnapping);
 }
 
+void ScrollingTreeScrollingNode::willStartAnimatedScroll()
+{
+}
+
 void ScrollingTreeScrollingNode::didStopAnimatedScroll()
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeScrollingNode " << scrollingNodeID() << " didStopAnimatedScroll");
     scrollingTree().scrollingTreeNodeDidStopAnimatedScroll(*this);
-    scrollingTree().setAnimatedScrollInProgressForNode(scrollingNodeID(), false);
 }
 
+void ScrollingTreeScrollingNode::setScrollAnimationInProgress(bool animationInProgress)
+{
+    scrollingTree().setScrollAnimationInProgressForNode(scrollingNodeID(), animationInProgress);
+}
+
 void ScrollingTreeScrollingNode::handleScrollPositionRequest(const RequestedScrollData& requestedScrollData)
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeScrollingNode " << scrollingNodeID() << " handleScrollPositionRequest() - position " << requestedScrollData.scrollPosition << " animated " << (requestedScrollData.animated == ScrollIsAnimated::Yes));
@@ -260,11 +268,6 @@
     return scrollPosition;
 }
 
-void ScrollingTreeScrollingNode::willStartAnimatedScroll()
-{
-    scrollingTree().setAnimatedScrollInProgressForNode(scrollingNodeID(), true);
-}
-
 void ScrollingTreeScrollingNode::scrollBy(const FloatSize& delta, ScrollClamping clamp)
 {
     scrollTo(currentScrollPosition() + delta, ScrollType::User, clamp);

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -75,6 +75,8 @@
     bool isScrollSnapInProgress() const;
     void setScrollSnapInProgress(bool);
 
+    virtual void serviceScrollAnimation() { }
+
     // These are imperative; they adjust the scrolling layers.
     void scrollTo(const FloatPoint&, ScrollType = ScrollType::User, ScrollClamping = ScrollClamping::Clamped);
     void scrollBy(const FloatSize&, ScrollClamping = ScrollClamping::Clamped);
@@ -130,6 +132,8 @@
 
     void willStartAnimatedScroll();
     void didStopAnimatedScroll();
+    
+    void setScrollAnimationInProgress(bool);
 
     virtual void currentScrollPositionChanged(ScrollType, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync);
     virtual void updateViewportForCurrentScrollPosition(std::optional<FloatRect> = { }) { }

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -42,6 +42,8 @@
     virtual bool startAnimatedScrollToPosition(FloatPoint) = 0;
     virtual void stopAnimatedScroll() = 0;
 
+    virtual void serviceScrollAnimation() = 0;
+
 protected:
     WEBCORE_EXPORT ScrollingTree& scrollingTree() const;
     WEBCORE_EXPORT FloatPoint lastCommittedScrollPosition() const;

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-10-31 15:18:55 UTC (rev 285094)
@@ -330,7 +330,7 @@
 
 bool ThreadedScrollingTree::scrollingThreadIsActive()
 {
-    return hasProcessedWheelEventsRecently() || hasNodeWithActiveAnimatedScroll();
+    return hasProcessedWheelEventsRecently() || hasNodeWithActiveScrollAnimations();
 }
 
 void ThreadedScrollingTree::willStartRenderingUpdate()
@@ -372,6 +372,19 @@
     });
 }
 
+void ThreadedScrollingTree::serviceScrollAnimations()
+{
+    ASSERT(ScrollingThread::isCurrentThread());
+
+    for (auto nodeID : nodesWithActiveScrollAnimations()) {
+        RefPtr targetNode = nodeForID(nodeID);
+        if (!is<ScrollingTreeScrollingNode>(targetNode))
+            continue;
+
+        downcast<ScrollingTreeScrollingNode>(*targetNode).serviceScrollAnimation();
+    }
+}
+
 // This code allows the main thread about half a frame to complete its rendering udpate. If the main thread
 // is responsive (i.e. managing to render every frame), then we expect to get a didCompleteRenderingUpdate()
 // within 8ms of willStartRenderingUpdate(). We time this via m_stateCondition, which blocks the scrolling
@@ -445,6 +458,8 @@
     ASSERT(ScrollingThread::isCurrentThread());
 
     Locker locker { m_treeLock };
+    
+    serviceScrollAnimations();
 
     if (m_state != SynchronizationState::Idle && canUpdateLayersOnScrollingThread())
         applyLayerPositionsInternal();

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -102,6 +102,8 @@
     void delayedRenderingUpdateDetectionTimerFired();
 
     void hasNodeWithAnimatedScrollChanged(bool) final;
+    
+    void serviceScrollAnimations() WTF_REQUIRES_LOCK(m_treeLock);
 
     Seconds maxAllowableRenderingUpdateDurationForSynchronization();
     

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -44,6 +44,9 @@
     bool handleWheelEventForScrolling(const PlatformWheelEvent&, ScrollingNodeID, std::optional<WheelScrollGestureState>) final;
     void wheelEventWasProcessedByMainThread(const PlatformWheelEvent&, std::optional<WheelScrollGestureState>) final;
 
+protected:
+    void hasNodeWithAnimatedScrollChanged(bool) override;
+
 private:
     void scheduleTreeStateCommit() final;
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm	2021-10-31 15:18:55 UTC (rev 285094)
@@ -133,8 +133,23 @@
 void ScrollingCoordinatorMac::didCompleteRenderingUpdate()
 {
     downcast<ThreadedScrollingTree>(scrollingTree())->didCompleteRenderingUpdate();
+
+    // When scroll animations are running on the scrolling thread, we need something to continually tickle the
+    // DisplayRefreshMonitor so that ThreadedScrollingTree::displayDidRefresh() will get called to service those animations.
+    // We can achieve this by scheduling a rendering update; this won't cause extra work, since scrolling thread scrolls
+    // will end up triggering these anyway.
+    if (scrollingTree()->hasNodeWithActiveScrollAnimations())
+        scheduleRenderingUpdate();
 }
 
+void ScrollingCoordinatorMac::hasNodeWithAnimatedScrollChanged(bool hasAnimatingNode)
+{
+    // This is necessary to trigger a rendering update, after which the code in
+    // ScrollingCoordinatorMac::didCompleteRenderingUpdate() triggers the rest.
+    if (hasAnimatingNode)
+        scheduleRenderingUpdate();
+}
+
 void ScrollingCoordinatorMac::updateTiledScrollingIndicator()
 {
     FrameView* frameView = m_page->mainFrame().view();

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -68,6 +68,7 @@
 
     bool startAnimatedScrollToPosition(FloatPoint) final;
     void stopAnimatedScroll() final;
+    void serviceScrollAnimation() final;
 
     FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const final;
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2021-10-31 15:18:55 UTC (rev 285094)
@@ -127,10 +127,7 @@
 
 bool ScrollingTreeFrameScrollingNodeMac::startAnimatedScrollToPosition(FloatPoint destinationPosition)
 {
-    bool started = m_delegate.startAnimatedScrollToPosition(destinationPosition);
-    if (started)
-        willStartAnimatedScroll();
-    return started;
+    return m_delegate.startAnimatedScrollToPosition(destinationPosition);
 }
 
 void ScrollingTreeFrameScrollingNodeMac::stopAnimatedScroll()
@@ -138,6 +135,11 @@
     m_delegate.stopAnimatedScroll();
 }
 
+void ScrollingTreeFrameScrollingNodeMac::serviceScrollAnimation()
+{
+    m_delegate.serviceScrollAnimation();
+}
+
 void ScrollingTreeFrameScrollingNodeMac::willDoProgrammaticScroll(const FloatPoint& targetScrollPosition)
 {
     m_delegate.willDoProgrammaticScroll(targetScrollPosition);
@@ -151,7 +153,7 @@
 
 void ScrollingTreeFrameScrollingNodeMac::currentScrollPositionChanged(ScrollType scrollType, ScrollingLayerPositionAction action)
 {
-    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeFrameScrollingNodeMac " << scrollingNodeID() << " currentScrollPositionChanged to " << currentScrollPosition() << " min: " << minimumScrollPosition() << " max: " << maximumScrollPosition() << " sync: " << hasSynchronousScrollingReasons() << " is animating: " << scrollingTree().isAnimatedScrollInProgressForNode(scrollingNodeID()));
+    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeFrameScrollingNodeMac " << scrollingNodeID() << " currentScrollPositionChanged to " << currentScrollPosition() << " min: " << minimumScrollPosition() << " max: " << maximumScrollPosition() << " sync: " << hasSynchronousScrollingReasons() << " is animating: " << scrollingTree().isScrollAnimationInProgressForNode(scrollingNodeID()));
 
     m_delegate.currentScrollPositionChanged();
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -54,6 +54,7 @@
 
     void repositionScrollingLayers() override;
     void repositionRelatedLayers() override;
+    void serviceScrollAnimation() override;
 
     WheelEventHandlingResult handleWheelEvent(const PlatformWheelEvent&, EventTargeting) override;
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm	2021-10-31 15:18:55 UTC (rev 285094)
@@ -87,6 +87,11 @@
     m_delegate.stopAnimatedScroll();
 }
 
+void ScrollingTreeOverflowScrollingNodeMac::serviceScrollAnimation()
+{
+    m_delegate.serviceScrollAnimation();
+}
+
 void ScrollingTreeOverflowScrollingNodeMac::willDoProgrammaticScroll(const FloatPoint& targetScrollPosition)
 {
     m_delegate.willDoProgrammaticScroll(targetScrollPosition);

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -55,6 +55,8 @@
     bool startAnimatedScrollToPosition(FloatPoint) final;
     void stopAnimatedScroll() final;
 
+    void serviceScrollAnimation() final;
+
     void willDoProgrammaticScroll(const FloatPoint&);
     void currentScrollPositionChanged();
 
@@ -92,7 +94,6 @@
     void adjustScrollPositionToBoundsIfNecessary() final;
 
     bool scrollPositionIsNotRubberbandingEdge(const FloatPoint&) const;
-    void scrollControllerAnimationTimerFired();
 
     FloatPoint scrollOffset() const final;
     float pageScaleFactor() const final;
@@ -111,8 +112,6 @@
     RetainPtr<NSScrollerImp> m_verticalScrollerImp;
     RetainPtr<NSScrollerImp> m_horizontalScrollerImp;
 
-    std::unique_ptr<RunLoop::Timer<ScrollingTreeScrollingNodeDelegateMac>> m_scrollControllerAnimationTimer;
-
     bool m_inMomentumPhase { false };
 };
 

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-10-31 15:18:55 UTC (rev 285094)
@@ -188,6 +188,7 @@
 
 std::unique_ptr<ScrollingEffectsControllerTimer> ScrollingTreeScrollingNodeDelegateMac::createTimer(Function<void()>&& function)
 {
+    // This is only used for a scroll snap timer.
     return WTF::makeUnique<ScrollingEffectsControllerTimer>(RunLoop::current(), [function = WTFMove(function), protectedNode = Ref { scrollingNode() }] {
         Locker locker { protectedNode->scrollingTree().treeLock() };
         function();
@@ -196,22 +197,15 @@
 
 void ScrollingTreeScrollingNodeDelegateMac::startAnimationCallback(ScrollingEffectsController&)
 {
-    if (!m_scrollControllerAnimationTimer)
-        m_scrollControllerAnimationTimer = WTF::makeUnique<RunLoop::Timer<ScrollingTreeScrollingNodeDelegateMac>>(RunLoop::current(), this, &ScrollingTreeScrollingNodeDelegateMac::scrollControllerAnimationTimerFired);
-
-    if (m_scrollControllerAnimationTimer->isActive())
-        return;
-
-    m_scrollControllerAnimationTimer->startRepeating(1_s / 60.);
+    scrollingNode().setScrollAnimationInProgress(true);
 }
 
 void ScrollingTreeScrollingNodeDelegateMac::stopAnimationCallback(ScrollingEffectsController&)
 {
-    if (m_scrollControllerAnimationTimer)
-        m_scrollControllerAnimationTimer->stop();
+    scrollingNode().setScrollAnimationInProgress(false);
 }
 
-void ScrollingTreeScrollingNodeDelegateMac::scrollControllerAnimationTimerFired()
+void ScrollingTreeScrollingNodeDelegateMac::serviceScrollAnimation()
 {
     m_scrollController.animationCallback(MonotonicTime::now());
 }

Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp	2021-10-31 15:18:55 UTC (rev 285094)
@@ -87,11 +87,6 @@
     return WheelEventHandlingResult::handled();
 }
 
-void ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired()
-{
-    m_scrollController.animationCallback(MonotonicTime::now());
-}
-
 std::unique_ptr<ScrollingEffectsControllerTimer> ScrollingTreeScrollingNodeDelegateNicosia::createTimer(Function<void()>&& function)
 {
     return makeUnique<ScrollingEffectsControllerTimer>(RunLoop::current(), [function = WTFMove(function), protectedNode = Ref { scrollingNode() }] {
@@ -124,6 +119,16 @@
         m_animationTimer->stop();
 }
 
+void ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired()
+{
+    m_scrollController.animationCallback(MonotonicTime::now());
+}
+
+void ScrollingTreeScrollingNodeDelegateNicosia::serviceScrollAnimation()
+{
+    // FIXME: Instead of using m_animationTimer, drive animations via ThreadedScrollingTree::serviceScrollAnimations().
+}
+
 bool ScrollingTreeScrollingNodeDelegateNicosia::allowsHorizontalScrolling() const
 {
     return ScrollingTreeScrollingNodeDelegate::allowsHorizontalScrolling();

Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h (285093 => 285094)


--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -52,6 +52,8 @@
     bool startAnimatedScrollToPosition(FloatPoint) final;
     void stopAnimatedScroll() final;
 
+    void serviceScrollAnimation() final;
+
 private:
     void animationTimerFired();
 

Modified: trunk/Source/WebKit/ChangeLog (285093 => 285094)


--- trunk/Source/WebKit/ChangeLog	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebKit/ChangeLog	2021-10-31 15:18:55 UTC (rev 285094)
@@ -1,3 +1,14 @@
+2021-10-31  Simon Fraser  <[email protected]>
+
+        Scroll animations should run at 120Hz on 120Hz displays
+        https://bugs.webkit.org/show_bug.cgi?id=232534
+
+        Reviewed by Tim Horton.
+
+        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationScrollingCoordinator.mm:
+        (WebKit::TiledCoreAnimationScrollingCoordinator::hasNodeWithAnimatedScrollChanged):
+
 2021-10-30  Myles C. Maxfield  <[email protected]>
 
         Migrate the first few callers from ImageBuffer::truncatedLogicalSize() to ImageBuffer::logicalSize()

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h (285093 => 285094)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h	2021-10-31 15:18:55 UTC (rev 285094)
@@ -81,6 +81,8 @@
     bool startAnimatedScrollToPosition(WebCore::FloatPoint) final;
     void stopAnimatedScroll() final;
 
+    void serviceScrollAnimation() final { }
+
 private:
     RetainPtr<CALayer> m_scrollLayer;
     RetainPtr<CALayer> m_scrolledContentsLayer;

Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationScrollingCoordinator.mm (285093 => 285094)


--- trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationScrollingCoordinator.mm	2021-10-31 14:25:44 UTC (rev 285093)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationScrollingCoordinator.mm	2021-10-31 15:18:55 UTC (rev 285094)
@@ -48,6 +48,8 @@
 
 void TiledCoreAnimationScrollingCoordinator::hasNodeWithAnimatedScrollChanged(bool haveAnimatedScrollingNodes)
 {
+    ScrollingCoordinatorMac::hasNodeWithAnimatedScrollChanged(haveAnimatedScrollingNodes);
+
     if (!m_page)
         return;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to