- Revision
- 260557
- Author
- simon.fra...@apple.com
- Date
- 2020-04-22 22:19:34 -0700 (Wed, 22 Apr 2020)
Log Message
Make it possible to eagerly apply scrolling tree state from the main thread
https://bugs.webkit.org/show_bug.cgi?id=210883
Reviewed by Tim Horton.
Work towards fixing webkit.org/b/210884: at the beginning of Page::updateRendering(),
we are going to need to pull the current state of the scrolling tree back to the
main thread, so that JS-exposed scroll offsets match scrolling tree state.
To this end, expose a scrolling tree traversal function from ScrollingTree, which
takes the lock and then calls a visitor function for each node. For scrolling nodes,
the visitor gets the scroll position and optional layout viewport origin. These
match the data passed back currently via AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll().
The new code is not called yet.
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::synchronizeStateFromScrollingTree):
* page/scrolling/AsyncScrollingCoordinator.h:
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::synchronizeStateFromScrollingTree):
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::traverseScrollingTree):
(WebCore::ScrollingTree::traverseScrollingTreeRecursive):
* page/scrolling/ScrollingTree.h:
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::currentScrollPositionChanged): applyLayerPositions() calls these two
functions, so just call it instead.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (260556 => 260557)
--- trunk/Source/WebCore/ChangeLog 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/ChangeLog 2020-04-23 05:19:34 UTC (rev 260557)
@@ -1,3 +1,34 @@
+2020-04-22 Simon Fraser <simon.fra...@apple.com>
+
+ Make it possible to eagerly apply scrolling tree state from the main thread
+ https://bugs.webkit.org/show_bug.cgi?id=210883
+
+ Reviewed by Tim Horton.
+
+ Work towards fixing webkit.org/b/210884: at the beginning of Page::updateRendering(),
+ we are going to need to pull the current state of the scrolling tree back to the
+ main thread, so that JS-exposed scroll offsets match scrolling tree state.
+
+ To this end, expose a scrolling tree traversal function from ScrollingTree, which
+ takes the lock and then calls a visitor function for each node. For scrolling nodes,
+ the visitor gets the scroll position and optional layout viewport origin. These
+ match the data passed back currently via AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll().
+
+ The new code is not called yet.
+
+ * page/scrolling/AsyncScrollingCoordinator.cpp:
+ (WebCore::AsyncScrollingCoordinator::synchronizeStateFromScrollingTree):
+ * page/scrolling/AsyncScrollingCoordinator.h:
+ * page/scrolling/ScrollingCoordinator.h:
+ (WebCore::ScrollingCoordinator::synchronizeStateFromScrollingTree):
+ * page/scrolling/ScrollingTree.cpp:
+ (WebCore::ScrollingTree::traverseScrollingTree):
+ (WebCore::ScrollingTree::traverseScrollingTreeRecursive):
+ * page/scrolling/ScrollingTree.h:
+ * page/scrolling/ScrollingTreeScrollingNode.cpp:
+ (WebCore::ScrollingTreeScrollingNode::currentScrollPositionChanged): applyLayerPositions() calls these two
+ functions, so just call it instead.
+
2020-04-22 Commit Queue <commit-qu...@webkit.org>
Unreviewed, reverting r260535.
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2020-04-23 05:19:34 UTC (rev 260557)
@@ -275,6 +275,18 @@
m_scrollingTree->applyLayerPositions();
}
+void AsyncScrollingCoordinator::synchronizeStateFromScrollingTree()
+{
+ ASSERT(isMainThread());
+
+ m_scrollingTree->traverseScrollingTree([&](ScrollingNodeID nodeID, ScrollingNodeType, Optional<FloatPoint> scrollPosition, Optional<FloatPoint> layoutViewportOrigin) {
+ if (scrollPosition) {
+ LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::synchronizeStateFromScrollingTree - node " << nodeID << " scroll position " << scrollPosition);
+ updateScrollPositionAfterAsyncScroll(nodeID, scrollPosition.value(), layoutViewportOrigin, ScrollType::User, ScrollingLayerPositionAction::Set);
+ }
+ });
+}
+
void AsyncScrollingCoordinator::noteScrollingThreadSyncCompleteForNode(ScrollingNodeID nodeID)
{
#if PLATFORM(MAC)
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2020-04-23 05:19:34 UTC (rev 260557)
@@ -100,6 +100,7 @@
WEBCORE_EXPORT bool requestScrollPositionUpdate(ScrollableArea&, const IntPoint&, ScrollType, ScrollClamping) override;
WEBCORE_EXPORT void applyScrollingTreeLayerPositions() override;
+ WEBCORE_EXPORT void synchronizeStateFromScrollingTree() override;
WEBCORE_EXPORT ScrollingNodeID createNode(ScrollingNodeType, ScrollingNodeID newNodeID) override;
WEBCORE_EXPORT ScrollingNodeID insertNode(ScrollingNodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID, size_t childIndex) override;
Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2020-04-23 05:19:34 UTC (rev 260557)
@@ -111,6 +111,9 @@
// Traverses the scrolling tree, setting layer positions to represent the current scrolled state.
virtual void applyScrollingTreeLayerPositions() { }
+ // Takes scroll positions from the scrolling tree and applies them to ScrollableAreas.
+ virtual void synchronizeStateFromScrollingTree() { }
+
#if PLATFORM(COCOA)
// Dispatched by the scrolling tree during handleWheelEvent. This is required as long as scrollbars are painted on the main thread.
void handleWheelEventPhase(PlatformWheelEventPhase);
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp 2020-04-23 05:19:34 UTC (rev 260557)
@@ -148,6 +148,32 @@
return m_rootNode;
}
+void ScrollingTree::traverseScrollingTree(VisitorFunction&& visitorFunction)
+{
+ LockHolder locker(m_treeMutex);
+ if (!m_rootNode)
+ return;
+
+ auto function = WTFMove(visitorFunction);
+ traverseScrollingTreeRecursive(*m_rootNode, function);
+}
+
+void ScrollingTree::traverseScrollingTreeRecursive(ScrollingTreeNode& node, const VisitorFunction& visitorFunction)
+{
+ Optional<FloatPoint> scrollPosition;
+ if (is<ScrollingTreeScrollingNode>(node))
+ scrollPosition = downcast<ScrollingTreeScrollingNode>(node).currentScrollPosition();
+
+ Optional<FloatPoint> layoutViewportOrigin;
+ if (is<ScrollingTreeFrameScrollingNode>(node))
+ layoutViewportOrigin = downcast<ScrollingTreeFrameScrollingNode>(node).layoutViewport().location();
+
+ visitorFunction(node.scrollingNodeID(), node.nodeType(), scrollPosition, layoutViewportOrigin);
+
+ for (auto& child : node.children())
+ traverseScrollingTreeRecursive(child.get(), visitorFunction);
+}
+
void ScrollingTree::mainFrameViewportChangedViaDelegatedScrolling(const FloatPoint& scrollPosition, const FloatRect& layoutViewport, double)
{
LOG_WITH_STREAM(Scrolling, stream << "ScrollingTree::viewportChangedViaDelegatedScrolling - layoutViewport " << layoutViewport);
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h 2020-04-23 05:19:34 UTC (rev 260557)
@@ -87,6 +87,9 @@
WEBCORE_EXPORT ScrollingTreeNode* nodeForID(ScrollingNodeID) const;
+ using VisitorFunction = WTF::Function<void (ScrollingNodeID, ScrollingNodeType, Optional<FloatPoint> scrollPosition, Optional<FloatPoint> layoutViewportOrigin)>;
+ void traverseScrollingTree(VisitorFunction&&);
+
// Called after a scrolling tree node has handled a scroll and updated its layers.
// Updates FrameView/RenderLayer scrolling state and GraphicsLayers.
virtual void scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync) = 0;
@@ -184,8 +187,8 @@
virtual void propagateSynchronousScrollingReasons(const HashSet<ScrollingNodeID>&) { }
void applyLayerPositionsRecursive(ScrollingTreeNode&);
-
void notifyRelatedNodesRecursive(ScrollingTreeNode&);
+ void traverseScrollingTreeRecursive(ScrollingTreeNode&, const VisitorFunction&);
WEBCORE_EXPORT virtual RefPtr<ScrollingTreeNode> scrollingNodeForPoint(FloatPoint);
virtual void receivedWheelEvent(const PlatformWheelEvent&) { }
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (260556 => 260557)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2020-04-23 04:56:44 UTC (rev 260556)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2020-04-23 05:19:34 UTC (rev 260557)
@@ -245,8 +245,7 @@
void ScrollingTreeScrollingNode::currentScrollPositionChanged()
{
- repositionScrollingLayers();
- repositionRelatedLayers();
+ applyLayerPositions();
scrollingTree().notifyRelatedNodesAfterScrollPositionChange(*this);
scrollingTree().scrollingTreeNodeDidScroll(*this);