Title: [240698] trunk
Revision
240698
Author
[email protected]
Date
2019-01-29 17:55:52 -0800 (Tue, 29 Jan 2019)

Log Message

Add nodes to the scrolling tree in z-index order.
https://bugs.webkit.org/show_bug.cgi?id=192529
<rdar://problem/47402708>

Reviewed by Dean Jackson.
Source/WebCore:

We currently add nodes to the scrolling tree via RenderLayerBacking::updateGeometry() and some other places.
This is sub-optimal, because we don't readily know the scrolling ancestor at these times, so have to do RenderLayer
walks to find them.

With this change we update the scrolling tree during the RenderLayerCompositor::updateBackingAndHierarchy()
tree walk, storing state along the way so we always know our scrolling tree ancestor, and the sibling index
(which makes it so that the scrolling tree correctly reflects layer z-order).

The reattachSubframeScrollLayers() code path is removed, since we can now reliably parent frame nodes via FrameHosting
nodes in their parent document.

There is also some minor cleanup around RenderLayerBacking teardown; it used to be the case that cleanup in ~RenderLayerBacking
was hard because the backing was already disconnected from its owning RenderLayer, so I added RenderLayerBacking::willBeDestroyed()
to do work that requires that layer->backing() is still valid. This allows for fewer callsites for detachFromScrollingCoordinator().

updateScrollCoordinatedLayersAfterFlushIncludingSubframes() is now iOS-only because it's only relevant for iOS WK1,
and m_scrollCoordinatedLayers can be moved to LegacyWebKitScrollingLayerCoordinator.

Tests: scrollingcoordinator/scrolling-tree/overflow-in-fixed.html
       scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html

* page/scrolling/ScrollingStateTree.cpp:
(WebCore::ScrollingStateTree::insertNode):
* page/scrolling/ScrollingTreeNode.cpp:
(WebCore::ScrollingTreeNode::~ScrollingTreeNode):
* platform/Logging.cpp:
(WebCore::initializeLogChannelsIfNecessary):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::setParent):
(WebCore::RenderLayer::calculateClipRects const):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::~RenderLayerBacking):
(WebCore::RenderLayerBacking::willBeDestroyed):
(WebCore::RenderLayerBacking::updateGeometry):
(WebCore::RenderLayerBacking::updateBackgroundLayer):
(WebCore::RenderLayerBacking::coordinatedScrollingRoles const):
* rendering/RenderLayerBacking.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::flushPendingLayerChanges):
(WebCore::RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush):
(WebCore::RenderLayerCompositor::didChangePlatformLayerForLayer):
(WebCore::frameHostingNodeForFrame):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
(WebCore::RenderLayerCompositor::updateBackingAndHierarchy):
(WebCore::RenderLayerCompositor::updateBacking):
(WebCore::RenderLayerCompositor::layerWillBeRemoved):
(WebCore::RenderLayerCompositor::setIsInWindow):
(WebCore::RenderLayerCompositor::clearBackingForLayerIncludingDescendants):
(WebCore::RenderLayerCompositor::useCoordinatedScrollingForLayer const):
(WebCore::RenderLayerCompositor::removeFromScrollCoordinatedLayers):
(WebCore::RenderLayerCompositor::attachScrollingNode):
(WebCore::RenderLayerCompositor::detachScrollCoordinatedLayerWithRole):
(WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer):
(WebCore::RenderLayerCompositor::updateScrollingNodeForViewportConstrainedRole):
(WebCore::RenderLayerCompositor::updateScrollingNodeForScrollingRole):
(WebCore::RenderLayerCompositor::updateScrollingNodeForFrameHostingRole):
(WebCore::RenderLayerCompositor::willRemoveScrollingLayerWithBacking):
(WebCore::RenderLayerCompositor::didAddScrollingLayer):
(WebCore::LegacyWebKitScrollingLayerCoordinator::registerAllViewportConstrainedLayers):
(WebCore::LegacyWebKitScrollingLayerCoordinator::addScrollingLayer):
(WebCore::LegacyWebKitScrollingLayerCoordinator::removeScrollingLayer):
(WebCore::LegacyWebKitScrollingLayerCoordinator::removeLayer):
(WebCore::LegacyWebKitScrollingLayerCoordinator::addViewportConstrainedLayer):
(WebCore::LegacyWebKitScrollingLayerCoordinator::removeViewportConstrainedLayer):
(WebCore::RenderLayerCompositor::updateCustomLayersAfterFlush): Deleted.
(WebCore::RenderLayerCompositor::setCompositingParent): Deleted. This was always called with a null parentLayer, so was a no-op.
(WebCore::RenderLayerCompositor::removeCompositedChildren): Deleted.
(WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged): Deleted. The work happens via didChangePlatformLayerForLayer() now.
(WebCore::canCoordinateScrollingForLayer): Deleted.
(WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus): Deleted.
(WebCore::enclosingScrollingNodeID): Deleted.
(WebCore::scrollCoordinatedAncestorInParentOfFrame): Deleted.
(WebCore::RenderLayerCompositor::reattachSubframeScrollLayers): Deleted.
(WebCore::RenderLayerCompositor::updateScrollCoordinationForThisFrame): Deleted.
(WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Deleted.
* rendering/RenderLayerCompositor.h:

Source/WebKit:

FrameHosting nodes have layers, so need to update them.

* Platform/Logging.cpp:
(WebKit::initializeLogChannelsIfNecessary):
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::connectStateNodeLayers):

LayoutTests:

New testcases for z-order of sibling fixed layers, and the correct nesting of scrolling tree nodes
for a position:fixed which is also overflow:scroll.

* platform/ios-wk2/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt: Added.
* platform/ios-wk2/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt:
* platform/ios-wk2/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt: Added.
* platform/mac-wk2/TestExpectations:
* scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt: Added.
* scrollingcoordinator/scrolling-tree/overflow-in-fixed.html: Added.
* scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt:
* scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt: Added.
* scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (240697 => 240698)


--- trunk/LayoutTests/ChangeLog	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/LayoutTests/ChangeLog	2019-01-30 01:55:52 UTC (rev 240698)
@@ -1,3 +1,24 @@
+2019-01-29  Simon Fraser  <[email protected]>
+
+        Add nodes to the scrolling tree in z-index order.
+        https://bugs.webkit.org/show_bug.cgi?id=192529
+        <rdar://problem/47402708>
+
+        Reviewed by Dean Jackson.
+        
+        New testcases for z-order of sibling fixed layers, and the correct nesting of scrolling tree nodes
+        for a position:fixed which is also overflow:scroll.
+
+        * platform/ios-wk2/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt: Added.
+        * platform/ios-wk2/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt:
+        * platform/ios-wk2/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt: Added.
+        * platform/mac-wk2/TestExpectations:
+        * scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt: Added.
+        * scrollingcoordinator/scrolling-tree/overflow-in-fixed.html: Added.
+        * scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt:
+        * scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt: Added.
+        * scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html: Added.
+
 2019-01-29  Truitt Savell  <[email protected]>
 
         Updating expectations for two compositing/repaint/iframes/ tests

Modified: trunk/LayoutTests/platform/ios-wk2/TestExpectations (240697 => 240698)


--- trunk/LayoutTests/platform/ios-wk2/TestExpectations	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/LayoutTests/platform/ios-wk2/TestExpectations	2019-01-30 01:55:52 UTC (rev 240698)
@@ -1077,6 +1077,7 @@
 webkit.org/b/153049 perf/array-binary-search.html [ Pass Failure Timeout ]
 
 fast/scrolling/ios/scroll-events-back-forward-after-pageshow.html [ Pass Failure ]
+webkit.org/b/193997 fast/scrolling/ios/hit-testing-iframe.html [ ImageOnlyFailure ]
 
 webkit.org/b/157589 fast/text-autosizing/ios/text-autosizing-after-back.html [ Pass Timeout ]
 

Added: trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt (0 => 240698)


--- trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,36 @@
+Scrolling content
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (scrollable area parameters 
+    (horizontal scroll elasticity 1)
+    (vertical scroll elasticity 1)
+    (horizontal scrollbar mode 0)
+    (vertical scrollbar mode 0))
+  (visual viewport enabled 1)
+  (layout viewport at (0,0) size 800x600)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (0,0))
+  (behavior for fixed 0)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (8,13))
+      (children 1
+        (Overflow scrolling node
+          (scrollable area size 400 300)
+          (contents size 400 1000)
+          (scrollable area parameters 
+            (horizontal scroll elasticity 1)
+            (vertical scroll elasticity 1)
+            (horizontal scrollbar mode 0)
+            (vertical scrollbar mode 0))
+        )
+      )
+    )
+  )
+)
+
+

Modified: trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt (240697 => 240698)


--- trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -15,7 +15,16 @@
   (min layout viewport origin (0,0))
   (max layout viewport origin (0,0))
   (behavior for fixed 0)
-  (children 0
+  (children 1
+    (Overflow scrolling node
+      (scrollable area size 440 340)
+      (contents size 440 1040)
+      (scrollable area parameters 
+        (horizontal scroll elasticity 1)
+        (vertical scroll elasticity 1)
+        (horizontal scrollbar mode 0)
+        (vertical scrollbar mode 0))
+    )
   )
 )
 

Added: trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt (0 => 240698)


--- trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,35 @@
+FirstSecondThird
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (scrollable area parameters 
+    (horizontal scroll elasticity 1)
+    (vertical scroll elasticity 1)
+    (horizontal scrollbar mode 0)
+    (vertical scrollbar mode 0))
+  (visual viewport enabled 1)
+  (layout viewport at (0,0) size 800x600)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (0,0))
+  (behavior for fixed 0)
+  (children 3
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (100,100))
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (150,50))
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (8,13))
+    )
+  )
+)
+
+

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (240697 => 240698)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2019-01-30 01:55:52 UTC (rev 240698)
@@ -324,8 +324,6 @@
 
 webkit.org/b/148408 tiled-drawing/scrolling/root-overflow-with-mousewheel.html [ Pass Failure Timeout ]
 
-webkit.org/b/192529 fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html [ Pass Failure ]
-
 webkit.org/b/139820 fast/frames/lots-of-objects.html [ Pass Timeout ]
 webkit.org/b/139820 fast/frames/lots-of-iframes.html [ Pass Timeout ]
 

Added: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt (0 => 240698)


--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,36 @@
+Scrolling content
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (scrollable area parameters 
+    (horizontal scroll elasticity 2)
+    (vertical scroll elasticity 2)
+    (horizontal scrollbar mode 0)
+    (vertical scrollbar mode 0))
+  (visual viewport enabled 1)
+  (layout viewport at (0,0) size 800x600)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (0,0))
+  (behavior for fixed 0)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (8,13))
+      (children 1
+        (Overflow scrolling node
+          (scrollable area size 385 285)
+          (contents size 385 1000)
+          (scrollable area parameters 
+            (horizontal scroll elasticity 1)
+            (vertical scroll elasticity 1)
+            (horizontal scrollbar mode 0)
+            (vertical scrollbar mode 0))
+        )
+      )
+    )
+  )
+)
+
+

Added: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed.html (0 => 240698)


--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed.html	                        (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/overflow-in-fixed.html	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>
+        Check that overflow is nested inside fixed
+    </title>
+    <script>
+        if (window.testRunner)
+            testRunner.dumpAsText();
+
+        if (window.internals)
+            window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+        function doTest() {
+            if (window.internals)
+                document.getElementById('scrollingTree').innerText = window.internals.scrollingStateTreeAsText() + "\n";
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+
+        window.addEventListener('load', doTest, false);
+    </script>
+    <style>
+        .fixed {
+            position: fixed;
+            background-color: silver;
+            width: 400px;
+            height: 300px;
+            overflow: scroll;
+        }
+        
+        .scrolling-content {
+            height: 1000px;
+        }
+    </style>
+</head>
+<body>
+    <div class="fixed">
+        <div class="scrolling-content">Scrolling content</div>
+    </div>
+    <pre id="scrollingTree"></pre>
+</body>
+</html>

Modified: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt (240697 => 240698)


--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/reparent-across-compositing-layers-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -15,7 +15,16 @@
   (min layout viewport origin (0,0))
   (max layout viewport origin (0,0))
   (behavior for fixed 0)
-  (children 0
+  (children 1
+    (Overflow scrolling node
+      (scrollable area size 425 325)
+      (contents size 425 1040)
+      (scrollable area parameters 
+        (horizontal scroll elasticity 1)
+        (vertical scroll elasticity 1)
+        (horizontal scrollbar mode 0)
+        (vertical scrollbar mode 0))
+    )
   )
 )
 

Added: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt (0 => 240698)


--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order-expected.txt	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,35 @@
+FirstSecondThird
+
+(Frame scrolling node
+  (scrollable area size 800 600)
+  (contents size 800 600)
+  (scrollable area parameters 
+    (horizontal scroll elasticity 2)
+    (vertical scroll elasticity 2)
+    (horizontal scrollbar mode 0)
+    (vertical scrollbar mode 0))
+  (visual viewport enabled 1)
+  (layout viewport at (0,0) size 800x600)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (0,0))
+  (behavior for fixed 0)
+  (children 3
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (100,100))
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (150,50))
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout at (0,0) size 800x600)
+      (layer position at last layout (8,13))
+    )
+  )
+)
+
+

Added: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html (0 => 240698)


--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html	                        (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html	2019-01-30 01:55:52 UTC (rev 240698)
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Test that the scrolling tree is in z-order.</title>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function doTest() {
+            requestAnimationFrame(() => {
+                document.body.classList.add('changed');
+
+                if (window.internals)
+                    document.getElementById('scrollingTree').innerText = window.internals.scrollingStateTreeAsText() + "\n";
+
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            });
+        }
+
+        window.addEventListener('load', doTest, false);
+    </script>
+    <style>
+        .fixed {
+            position: fixed;
+            background-color: silver;
+            border: 1px solid black;
+            width: 200px;
+            height: 150px;            
+        }
+        
+        #second {
+            left: 100px;
+            top: 100px;
+        }
+
+        #third {
+            left: 150px;
+            top: 50px;
+        }
+        
+        .changed #first {
+            z-index: 2;
+        }
+
+        .changed #third {
+            z-index: 1;
+        }
+    </style>
+</head>
+<body>
+    <div class="fixed" id="first">First</div>
+    <div class="fixed" id="second">Second</div>
+    <div class="fixed" id="third">Third</div>
+    <pre id="scrollingTree"></pre>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (240697 => 240698)


--- trunk/Source/WebCore/ChangeLog	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/ChangeLog	2019-01-30 01:55:52 UTC (rev 240698)
@@ -1,3 +1,88 @@
+2019-01-29  Simon Fraser  <[email protected]>
+
+        Add nodes to the scrolling tree in z-index order.
+        https://bugs.webkit.org/show_bug.cgi?id=192529
+        <rdar://problem/47402708>
+
+        Reviewed by Dean Jackson.
+
+        We currently add nodes to the scrolling tree via RenderLayerBacking::updateGeometry() and some other places.
+        This is sub-optimal, because we don't readily know the scrolling ancestor at these times, so have to do RenderLayer
+        walks to find them.
+
+        With this change we update the scrolling tree during the RenderLayerCompositor::updateBackingAndHierarchy()
+        tree walk, storing state along the way so we always know our scrolling tree ancestor, and the sibling index
+        (which makes it so that the scrolling tree correctly reflects layer z-order).
+
+        The reattachSubframeScrollLayers() code path is removed, since we can now reliably parent frame nodes via FrameHosting
+        nodes in their parent document.
+
+        There is also some minor cleanup around RenderLayerBacking teardown; it used to be the case that cleanup in ~RenderLayerBacking
+        was hard because the backing was already disconnected from its owning RenderLayer, so I added RenderLayerBacking::willBeDestroyed()
+        to do work that requires that layer->backing() is still valid. This allows for fewer callsites for detachFromScrollingCoordinator().
+
+        updateScrollCoordinatedLayersAfterFlushIncludingSubframes() is now iOS-only because it's only relevant for iOS WK1,
+        and m_scrollCoordinatedLayers can be moved to LegacyWebKitScrollingLayerCoordinator.
+
+        Tests: scrollingcoordinator/scrolling-tree/overflow-in-fixed.html
+               scrollingcoordinator/scrolling-tree/scrolling-tree-is-z-order.html
+
+        * page/scrolling/ScrollingStateTree.cpp:
+        (WebCore::ScrollingStateTree::insertNode):
+        * page/scrolling/ScrollingTreeNode.cpp:
+        (WebCore::ScrollingTreeNode::~ScrollingTreeNode):
+        * platform/Logging.cpp:
+        (WebCore::initializeLogChannelsIfNecessary):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::setParent):
+        (WebCore::RenderLayer::calculateClipRects const):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::~RenderLayerBacking):
+        (WebCore::RenderLayerBacking::willBeDestroyed):
+        (WebCore::RenderLayerBacking::updateGeometry):
+        (WebCore::RenderLayerBacking::updateBackgroundLayer):
+        (WebCore::RenderLayerBacking::coordinatedScrollingRoles const):
+        * rendering/RenderLayerBacking.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::flushPendingLayerChanges):
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush):
+        (WebCore::RenderLayerCompositor::didChangePlatformLayerForLayer):
+        (WebCore::frameHostingNodeForFrame):
+        (WebCore::RenderLayerCompositor::updateCompositingLayers):
+        (WebCore::RenderLayerCompositor::updateBackingAndHierarchy):
+        (WebCore::RenderLayerCompositor::updateBacking):
+        (WebCore::RenderLayerCompositor::layerWillBeRemoved):
+        (WebCore::RenderLayerCompositor::setIsInWindow):
+        (WebCore::RenderLayerCompositor::clearBackingForLayerIncludingDescendants):
+        (WebCore::RenderLayerCompositor::useCoordinatedScrollingForLayer const):
+        (WebCore::RenderLayerCompositor::removeFromScrollCoordinatedLayers):
+        (WebCore::RenderLayerCompositor::attachScrollingNode):
+        (WebCore::RenderLayerCompositor::detachScrollCoordinatedLayerWithRole):
+        (WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer):
+        (WebCore::RenderLayerCompositor::updateScrollingNodeForViewportConstrainedRole):
+        (WebCore::RenderLayerCompositor::updateScrollingNodeForScrollingRole):
+        (WebCore::RenderLayerCompositor::updateScrollingNodeForFrameHostingRole):
+        (WebCore::RenderLayerCompositor::willRemoveScrollingLayerWithBacking):
+        (WebCore::RenderLayerCompositor::didAddScrollingLayer):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::registerAllViewportConstrainedLayers):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::addScrollingLayer):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::removeScrollingLayer):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::removeLayer):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::addViewportConstrainedLayer):
+        (WebCore::LegacyWebKitScrollingLayerCoordinator::removeViewportConstrainedLayer):
+        (WebCore::RenderLayerCompositor::updateCustomLayersAfterFlush): Deleted.
+        (WebCore::RenderLayerCompositor::setCompositingParent): Deleted. This was always called with a null parentLayer, so was a no-op.
+        (WebCore::RenderLayerCompositor::removeCompositedChildren): Deleted.
+        (WebCore::RenderLayerCompositor::fixedRootBackgroundLayerChanged): Deleted. The work happens via didChangePlatformLayerForLayer() now.
+        (WebCore::canCoordinateScrollingForLayer): Deleted.
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus): Deleted.
+        (WebCore::enclosingScrollingNodeID): Deleted.
+        (WebCore::scrollCoordinatedAncestorInParentOfFrame): Deleted.
+        (WebCore::RenderLayerCompositor::reattachSubframeScrollLayers): Deleted.
+        (WebCore::RenderLayerCompositor::updateScrollCoordinationForThisFrame): Deleted.
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer): Deleted.
+        * rendering/RenderLayerCompositor.h:
+
 2019-01-29  Brent Fulgham  <[email protected]>
 
         Make sure we have a frame before trying to access its loader 

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


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm	2019-01-30 01:55:52 UTC (rev 240698)
@@ -361,8 +361,8 @@
 void ScrollingTreeFrameScrollingNodeMac::adjustScrollPositionToBoundsIfNecessary()
 {
     FloatPoint currentScrollPosition = scrollPosition();
-    FloatPoint constainedPosition = currentScrollPosition.constrainedBetween(minimumScrollPosition(), maximumScrollPosition());
-    immediateScrollBy(constainedPosition - currentScrollPosition);
+    FloatPoint constrainedPosition = currentScrollPosition.constrainedBetween(minimumScrollPosition(), maximumScrollPosition());
+    immediateScrollBy(constrainedPosition - currentScrollPosition);
 }
 
 FloatPoint ScrollingTreeFrameScrollingNodeMac::scrollPosition() const

Modified: trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm (240697 => 240698)


--- trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2019-01-30 01:55:52 UTC (rev 240698)
@@ -804,8 +804,8 @@
     m_scrollableArea.setConstrainsScrollingToContentEdge(true);
 
     ScrollPosition currentScrollPosition = m_scrollableArea.scrollPosition();
-    ScrollPosition constainedPosition = m_scrollableArea.constrainScrollPosition(currentScrollPosition);
-    immediateScrollBy(constainedPosition - currentScrollPosition);
+    ScrollPosition constrainedPosition = m_scrollableArea.constrainScrollPosition(currentScrollPosition);
+    immediateScrollBy(constrainedPosition - currentScrollPosition);
 
     m_scrollableArea.setConstrainsScrollingToContentEdge(currentlyConstrainsToContentEdge);
 }

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (240697 => 240698)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2019-01-30 01:55:52 UTC (rev 240698)
@@ -603,7 +603,7 @@
 
     if (m_parent && !renderer().renderTreeBeingDestroyed())
         compositor().layerWillBeRemoved(*m_parent, *this);
-    
+
     m_parent = parent;
 
     if (m_parent && !renderer().renderTreeBeingDestroyed())
@@ -5913,8 +5913,13 @@
 
 void RenderLayer::clearBacking(bool layerBeingDestroyed)
 {
-    if (m_backing && !renderer().renderTreeBeingDestroyed())
+    if (!m_backing)
+        return;
+
+    if (!renderer().renderTreeBeingDestroyed())
         compositor().layerBecameNonComposited(*this);
+    
+    m_backing->willBeDestroyed();
     m_backing = nullptr;
 
     if (!layerBeingDestroyed)

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (240697 => 240698)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2019-01-30 01:55:52 UTC (rev 240698)
@@ -236,6 +236,7 @@
 
 RenderLayerBacking::~RenderLayerBacking()
 {
+    // Note that m_owningLayer->backing() is null here.
     updateAncestorClippingLayer(false);
     updateChildClippingStrategy(false);
     updateDescendantClippingLayer(false);
@@ -244,10 +245,20 @@
     updateBackgroundLayer(false);
     updateMaskingLayer(false, false);
     updateScrollingLayers(false);
-    detachFromScrollingCoordinator({ ScrollCoordinationRole::Scrolling, ScrollCoordinationRole::ViewportConstrained, ScrollCoordinationRole::FrameHosting });
+    
+    ASSERT(!m_viewportConstrainedNodeID);
+    ASSERT(!m_scrollingNodeID);
+    ASSERT(!m_frameHostingNodeID);
+
     destroyGraphicsLayers();
 }
 
+void RenderLayerBacking::willBeDestroyed()
+{
+    ASSERT(m_owningLayer.backing() == this);
+    compositor().removeFromScrollCoordinatedLayers(m_owningLayer);
+}
+
 void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
 {
     if (layer && layer->type() == GraphicsLayer::Type::Normal && layer->tiledBacking())
@@ -1246,8 +1257,6 @@
 
     if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay())
         setContentsNeedDisplay();
-
-    compositor().updateScrollCoordinatedStatus(m_owningLayer, { RenderLayerCompositor::ScrollingNodeChangeFlags::Layer, RenderLayerCompositor::ScrollingNodeChangeFlags::LayerGeometry });
 }
 
 void RenderLayerBacking::updateAfterDescendants()
@@ -1643,12 +1652,8 @@
         }
     }
     
-    if (layerChanged) {
+    if (layerChanged)
         m_graphicsLayer->setNeedsDisplay();
-
-        if (m_backgroundLayerPaintsFixedRootBackground)
-            compositor().fixedRootBackgroundLayerChanged();
-    }
     
     return layerChanged;
 }
@@ -1767,6 +1772,23 @@
     return true;
 }
 
+OptionSet<ScrollCoordinationRole> RenderLayerBacking::coordinatedScrollingRoles() const
+{
+    auto& compositor = this->compositor();
+
+    OptionSet<ScrollCoordinationRole> coordinationRoles;
+    if (compositor.isViewportConstrainedFixedOrStickyLayer(m_owningLayer))
+        coordinationRoles.add(ScrollCoordinationRole::ViewportConstrained);
+
+    if (compositor.useCoordinatedScrollingForLayer(m_owningLayer))
+        coordinationRoles.add(ScrollCoordinationRole::Scrolling);
+
+    if (compositor.isLayerForIFrameWithScrollCoordinatedContents(m_owningLayer))
+        coordinationRoles.add(ScrollCoordinationRole::FrameHosting);
+
+    return coordinationRoles;
+}
+
 void RenderLayerBacking::detachFromScrollingCoordinator(OptionSet<ScrollCoordinationRole> roles)
 {
     if (!m_scrollingNodeID && !m_frameHostingNodeID && !m_viewportConstrainedNodeID)

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (240697 => 240698)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2019-01-30 01:55:52 UTC (rev 240698)
@@ -64,6 +64,9 @@
     void layerWillBeDestroyed();
 #endif
 
+    // Do cleanup while layer->backing() is still valid.
+    void willBeDestroyed();
+
     RenderLayer& owningLayer() const { return m_owningLayer; }
 
     void updateConfigurationAfterStyleChange();
@@ -100,13 +103,15 @@
 
     bool requiresBackgroundLayer() const { return m_requiresBackgroundLayer; }
     void setRequiresBackgroundLayer(bool);
-    
+
     bool hasScrollingLayer() const { return m_scrollingLayer != nullptr; }
     GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
     GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
 
+    OptionSet<ScrollCoordinationRole> coordinatedScrollingRoles() const;
+
     void detachFromScrollingCoordinator(OptionSet<ScrollCoordinationRole>);
-    
+
     ScrollingNodeID scrollingNodeIDForRole(ScrollCoordinationRole role) const
     {
         switch (role) {
@@ -119,7 +124,7 @@
         }
         return 0;
     }
-    
+
     void setScrollingNodeIDForRole(ScrollingNodeID nodeID, ScrollCoordinationRole role)
     {
         switch (role) {
@@ -135,7 +140,7 @@
             break;
         }
     }
-    
+
     ScrollingNodeID scrollingNodeIDForChildren() const
     {
         return m_frameHostingNodeID ? m_frameHostingNodeID : (m_scrollingNodeID ? m_scrollingNodeID : m_viewportConstrainedNodeID);

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (240697 => 240698)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2019-01-30 01:55:52 UTC (rev 240698)
@@ -105,6 +105,11 @@
 
 using namespace HTMLNames;
 
+struct ScrollingTreeState {
+    Optional<ScrollingNodeID> parentNodeID;
+    size_t nextChildIndex { 0 };
+};
+
 class OverlapMapContainer {
 public:
     void add(const LayoutRect& bounds)
@@ -491,9 +496,9 @@
         ASSERT(m_flushingLayers);
     }
 
+#if PLATFORM(IOS_FAMILY)
     updateScrollCoordinatedLayersAfterFlushIncludingSubframes();
 
-#if PLATFORM(IOS_FAMILY)
     if (isFlushRoot)
         page().chrome().client().didFlushCompositingLayers();
 #endif
@@ -502,6 +507,7 @@
     startLayerFlushTimerIfNeeded();
 }
 
+#if PLATFORM(IOS_FAMILY)
 void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlushIncludingSubframes()
 {
     updateScrollCoordinatedLayersAfterFlush();
@@ -518,38 +524,38 @@
 
 void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush()
 {
-    updateCustomLayersAfterFlush();
-
-    HashSet<RenderLayer*> layersNeedingUpdate;
-    std::swap(m_scrollCoordinatedLayersNeedingUpdate, layersNeedingUpdate);
-    
-    for (auto* layer : layersNeedingUpdate)
-        updateScrollCoordinatedStatus(*layer, ScrollingNodeChangeFlags::Layer);
-}
-
-void RenderLayerCompositor::updateCustomLayersAfterFlush()
-{
-#if PLATFORM(IOS_FAMILY)
     if (m_legacyScrollingLayerCoordinator) {
-        m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this, m_scrollCoordinatedLayers);
+        m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this);
         m_legacyScrollingLayerCoordinator->registerScrollingLayersNeedingUpdate();
     }
+}
 #endif
-}
 
-void RenderLayerCompositor::didChangePlatformLayerForLayer(RenderLayer& layer, const GraphicsLayer* graphicsLayer)
+void RenderLayerCompositor::didChangePlatformLayerForLayer(RenderLayer& layer, const GraphicsLayer*)
 {
-    if (m_scrollCoordinatedLayers.contains(&layer))
-        m_scrollCoordinatedLayersNeedingUpdate.add(&layer);
-
 #if PLATFORM(IOS_FAMILY)
     if (m_legacyScrollingLayerCoordinator)
         m_legacyScrollingLayerCoordinator->didChangePlatformLayerForLayer(layer);
 #endif
 
+    auto* scrollingCoordinator = this->scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return;
+
     auto* backing = layer.backing();
-    if (backing->backgroundLayerPaintsFixedRootBackground() && graphicsLayer == backing->backgroundLayer())
-        fixedRootBackgroundLayerChanged();
+    if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::ViewportConstrained))
+        scrollingCoordinator->setNodeLayers(nodeID, backing->graphicsLayer());
+
+    if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling)) {
+        // FIXME: would be nice to not have to special-case the root.
+        if (layer.isRenderViewLayer())
+            scrollingCoordinator->setNodeLayers(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
+        else
+            scrollingCoordinator->setNodeLayers(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer());
+    }
+
+    if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
+        scrollingCoordinator->setNodeLayers(nodeID, backing->graphicsLayer());
 }
 
 void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*)
@@ -615,6 +621,32 @@
     m_updateCompositingLayersTimer.stop();
 }
 
+static Optional<ScrollingNodeID> frameHostingNodeForFrame(Frame& frame)
+{
+    if (!frame.document() || !frame.view())
+        return { };
+
+    // Find the frame's enclosing layer in our render tree.
+    auto* ownerElement = frame.document()->ownerElement();
+    if (!ownerElement)
+        return { };
+
+    auto* frameRenderer = ownerElement->renderer();
+    if (!frameRenderer || !is<RenderWidget>(frameRenderer))
+        return { };
+
+    auto& widgetRenderer = downcast<RenderWidget>(*frameRenderer);
+    if (!widgetRenderer.hasLayer() || !widgetRenderer.layer()->isComposited()) {
+        LOG(Scrolling, "frameHostingNodeForFrame: frame renderer has no layer or is not composited.");
+        return { };
+    }
+
+    if (auto frameHostingNodeID = widgetRenderer.layer()->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
+        return frameHostingNodeID;
+
+    return { };
+}
+
 // Returns true on a successful update.
 bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
 {
@@ -714,8 +746,12 @@
 #endif
 
     if (updateRoot->hasDescendantNeedingUpdateBackingOrHierarchyTraversal() || updateRoot->needsUpdateBackingOrHierarchyTraversal()) {
+        ScrollingTreeState scrollingTreeState = { 0, 0 };
+        if (!m_renderView.frame().isMainFrame())
+            scrollingTreeState.parentNodeID = frameHostingNodeForFrame(m_renderView.frame());
+
         Vector<Ref<GraphicsLayer>> childList;
-        updateBackingAndHierarchy(*updateRoot, childList);
+        updateBackingAndHierarchy(*updateRoot, childList, scrollingTreeState);
 
         // Host the document layer in the RenderView's root layer.
         if (isFullUpdate) {
@@ -727,8 +763,6 @@
             else if (m_rootContentLayer)
                 m_rootContentLayer->setChildren(WTFMove(childList));
         }
-    
-        reattachSubframeScrollLayers();
     }
 
 #if !LOG_DISABLED
@@ -1101,7 +1135,7 @@
     overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
 }
 
-void RenderLayerCompositor::updateBackingAndHierarchy(RenderLayer& layer, Vector<Ref<GraphicsLayer>>& childLayersOfEnclosingLayer, OptionSet<UpdateLevel> updateLevel, int depth)
+void RenderLayerCompositor::updateBackingAndHierarchy(RenderLayer& layer, Vector<Ref<GraphicsLayer>>& childLayersOfEnclosingLayer, ScrollingTreeState& scrollingTreeState, OptionSet<UpdateLevel> updateLevel, int depth)
 {
     layer.updateDescendantDependentFlags();
     layer.updateLayerListsIfNeeded();
@@ -1110,6 +1144,8 @@
     if (layer.descendantsNeedUpdateBackingAndHierarchyTraversal())
         updateLevel.add(UpdateLevel::AllDescendants);
 
+    ScrollingTreeState stateForDescendants = scrollingTreeState;
+
     auto* layerBacking = layer.backing();
     if (layerBacking) {
         updateLevel.remove(UpdateLevel::CompositedChildren);
@@ -1145,6 +1181,11 @@
         if (!layer.parent())
             updateRootLayerPosition();
 
+        // FIXME: do based on dirty flags. Need to do this for changes of geometry, configuration and hierarchy.
+        // Need to be careful to do the right thing when a scroll-coordinated layer loses a scroll-coordinated ancestor.
+        stateForDescendants.parentNodeID = updateScrollCoordinationForLayer(layer, scrollingTreeState, layerBacking->coordinatedScrollingRoles(), { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
+        stateForDescendants.nextChildIndex = 0;
+
 #if !LOG_DISABLED
         logLayerInfo(layer, "updateBackingAndHierarchy", depth);
 #else
@@ -1162,7 +1203,7 @@
 
     bool requireDescendantTraversal = layer.hasDescendantNeedingUpdateBackingOrHierarchyTraversal()
         || (layer.hasCompositingDescendant() && (!layerBacking || layer.needsCompositingLayerConnection() || !updateLevel.isEmpty()));
-    
+
     bool requiresChildRebuild = layerBacking && layer.needsCompositingLayerConnection() && !layer.hasCompositingDescendant();
 
 #if !ASSERT_DISABLED
@@ -1179,15 +1220,15 @@
 
     if (requireDescendantTraversal) {
         for (auto* renderLayer : layer.negativeZOrderLayers())
-            updateBackingAndHierarchy(*renderLayer, childList, updateLevel, depth + 1);
+            updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
 
         appendForegroundLayerIfNecessary();
 
         for (auto* renderLayer : layer.normalFlowLayers())
-            updateBackingAndHierarchy(*renderLayer, childList, updateLevel, depth + 1);
+            updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
         
         for (auto* renderLayer : layer.positiveZOrderLayers())
-            updateBackingAndHierarchy(*renderLayer, childList, updateLevel, depth + 1);
+            updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
     } else if (requiresChildRebuild)
         appendForegroundLayerIfNecessary();
 
@@ -1498,7 +1539,6 @@
             layer.ensureBacking();
 
             if (layer.isRenderViewLayer() && useCoordinatedScrollingForLayer(layer)) {
-                updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
                 if (auto* scrollingCoordinator = this->scrollingCoordinator())
                     scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
 #if ENABLE(RUBBER_BANDING)
@@ -1535,8 +1575,6 @@
                 }
             }
 
-            removeFromScrollCoordinatedLayers(layer);
-
             layer.clearBacking();
             layerChanged = true;
 
@@ -1645,10 +1683,8 @@
     if (!child.isComposited() || parent.renderer().renderTreeBeingDestroyed())
         return;
 
-    removeFromScrollCoordinatedLayers(child);
     repaintInCompositedAncestor(child, child.backing()->compositedBounds()); // FIXME: do via dirty bits?
 
-    setCompositingParent(child, nullptr);
     child.setNeedsCompositingLayerConnection();
 }
 
@@ -1739,33 +1775,6 @@
         overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
 }
 
-void RenderLayerCompositor::setCompositingParent(RenderLayer& childLayer, RenderLayer* parentLayer)
-{
-    ASSERT(!parentLayer || childLayer.ancestorCompositingLayer() == parentLayer);
-    ASSERT(childLayer.isComposited());
-
-    // It's possible to be called with a parent that isn't yet composited when we're doing
-    // partial updates as required by painting or hit testing. Just bail in that case;
-    // we'll do a full layer update soon.
-    if (!parentLayer || !parentLayer->isComposited())
-        return;
-
-    if (parentLayer) {
-        auto* hostingLayer = parentLayer->backing()->parentForSublayers();
-        auto* hostedLayer = childLayer.backing()->childForSuperlayers();
-        
-        hostingLayer->addChild(*hostedLayer);
-    } else
-        childLayer.backing()->childForSuperlayers()->removeFromParent();
-}
-
-void RenderLayerCompositor::removeCompositedChildren(RenderLayer& layer)
-{
-    ASSERT(layer.isComposited());
-
-    layer.backing()->parentForSublayers()->removeAllChildren();
-}
-
 #if ENABLE(VIDEO)
 bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo& video) const
 {
@@ -1876,15 +1885,6 @@
     }
 }
 
-void RenderLayerCompositor::fixedRootBackgroundLayerChanged()
-{
-    if (m_renderView.renderTreeBeingDestroyed())
-        return;
-
-    if (m_renderView.layer()->isComposited())
-        updateScrollCoordinatedStatus(*m_renderView.layer(), ScrollingNodeChangeFlags::Layer);
-}
-
 String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
 {
     updateCompositingLayers(CompositingUpdateType::AfterLayout);
@@ -2035,7 +2035,7 @@
         attachRootLayer(attachment);
 #if PLATFORM(IOS_FAMILY)
         if (m_legacyScrollingLayerCoordinator) {
-            m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this, m_scrollCoordinatedLayers);
+            m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this);
             m_legacyScrollingLayerCoordinator->registerAllScrollingLayers();
         }
 #endif
@@ -2055,10 +2055,8 @@
 
 void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer& layer)
 {
-    if (layer.isComposited()) {
-        removeFromScrollCoordinatedLayers(layer);
+    if (layer.isComposited())
         layer.clearBacking();
-    }
 
     for (auto* childLayer = layer.firstChild(); childLayer; childLayer = childLayer->nextSibling())
         clearBackingForLayerIncludingDescendants(*childLayer);
@@ -2856,7 +2854,7 @@
 
     if (auto* scrollingCoordinator = this->scrollingCoordinator())
         return scrollingCoordinator->coordinatesScrollingForOverflowLayer(layer);
-    
+
     return false;
 }
 
@@ -3678,48 +3676,13 @@
         rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
 }
 
-static bool canCoordinateScrollingForLayer(const RenderLayer& layer)
-{
-    return (layer.isRenderViewLayer() || layer.parent()) && layer.isComposited();
-}
-
-void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer, OptionSet<ScrollingNodeChangeFlags> changes)
-{
-    OptionSet<ScrollCoordinationRole> coordinationRoles;
-    if (isViewportConstrainedFixedOrStickyLayer(layer))
-        coordinationRoles.add(ScrollCoordinationRole::ViewportConstrained);
-
-    if (useCoordinatedScrollingForLayer(layer))
-        coordinationRoles.add(ScrollCoordinationRole::Scrolling);
-
-    if (isLayerForIFrameWithScrollCoordinatedContents(layer)) {
-        // We never expect a RenderIFrame to have scrollable overflow.
-        ASSERT(!coordinationRoles.contains(ScrollCoordinationRole::Scrolling));
-        coordinationRoles.add(ScrollCoordinationRole::FrameHosting);
-    }
-
-    if (layer.isComposited())
-        layer.backing()->setIsScrollCoordinatedWithViewportConstrainedRole(coordinationRoles.contains(ScrollCoordinationRole::ViewportConstrained));
-
-    if (coordinationRoles && canCoordinateScrollingForLayer(layer)) {
-        if (m_scrollCoordinatedLayers.add(&layer).isNewEntry)
-            m_subframeScrollLayersNeedReattach = true;
-
-        updateScrollCoordinatedLayer(layer, coordinationRoles, changes);
-    } else
-        removeFromScrollCoordinatedLayers(layer);
-}
-
 void RenderLayerCompositor::removeFromScrollCoordinatedLayers(RenderLayer& layer)
 {
-    if (!m_scrollCoordinatedLayers.contains(&layer))
-        return;
+#if PLATFORM(IOS_FAMILY)
+    if (m_legacyScrollingLayerCoordinator)
+        m_legacyScrollingLayerCoordinator->removeLayer(layer);
+#endif
 
-    m_subframeScrollLayersNeedReattach = true;
-    
-    m_scrollCoordinatedLayers.remove(&layer);
-    m_scrollCoordinatedLayersNeedingUpdate.remove(&layer);
-
     detachScrollCoordinatedLayer(layer, { ScrollCoordinationRole::Scrolling, ScrollCoordinationRole::ViewportConstrained, ScrollCoordinationRole::FrameHosting });
 }
 
@@ -3780,72 +3743,6 @@
     return constraints;
 }
 
-static ScrollingNodeID enclosingScrollingNodeID(RenderLayer& layer, IncludeSelfOrNot includeSelf)
-{
-    auto* currLayer = includeSelf == IncludeSelf ? &layer : layer.parent();
-    while (currLayer) {
-        if (auto* backing = currLayer->backing()) {
-            if (ScrollingNodeID nodeID = backing->scrollingNodeIDForChildren())
-                return nodeID;
-        }
-        currLayer = currLayer->parent();
-    }
-
-    return 0;
-}
-
-static Optional<ScrollingNodeID> scrollCoordinatedAncestorInParentOfFrame(Frame& frame)
-{
-    if (!frame.document() || !frame.view())
-        return { };
-
-    // Find the frame's enclosing layer in our render tree.
-    auto* ownerElement = frame.document()->ownerElement();
-    auto* frameRenderer = ownerElement ? ownerElement->renderer() : nullptr;
-    if (!frameRenderer || !is<RenderWidget>(frameRenderer))
-        return { };
-
-    auto& widgetRenderer = downcast<RenderWidget>(*frameRenderer);
-    if (!widgetRenderer.hasLayer() || !widgetRenderer.layer()->isComposited()) {
-        LOG(Scrolling, "scrollCoordinatedAncestorInParentOfFrame: frame renderer has no layer or is not composited.");
-        return { };
-    }
-
-    if (auto frameHostingNodeID = widgetRenderer.layer()->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
-        return frameHostingNodeID;
-
-    return { };
-}
-
-void RenderLayerCompositor::reattachSubframeScrollLayers()
-{
-    if (!m_subframeScrollLayersNeedReattach)
-        return;
-    
-    m_subframeScrollLayersNeedReattach = false;
-
-    auto* scrollingCoordinator = this->scrollingCoordinator();
-
-    for (Frame* child = m_renderView.frameView().frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
-        if (!child->document() || !child->view())
-            continue;
-
-        // Ignore frames that are not scroll-coordinated.
-        auto* childFrameView = child->view();
-        ScrollingNodeID frameScrollingNodeID = childFrameView->scrollLayerID();
-        if (!frameScrollingNodeID)
-            continue;
-
-        auto parentNodeID = scrollCoordinatedAncestorInParentOfFrame(*child);
-        if (!parentNodeID) {
-            LOG(Scrolling, "RenderLayerCompositor %p reattachSubframeScrollLayers: failed to find scrolling node parent for frame with nodeID %" PRIu64 ".", this, frameScrollingNodeID);
-            continue;
-        }
-
-        scrollingCoordinator->insertNode(child->isMainFrame() ? ScrollingNodeType::MainFrame : ScrollingNodeType::Subframe, frameScrollingNodeID, parentNodeID.value());
-    }
-}
-
 static inline ScrollCoordinationRole scrollCoordinationRoleForNodeType(ScrollingNodeType nodeType)
 {
     switch (nodeType) {
@@ -3863,7 +3760,7 @@
     return ScrollCoordinationRole::Scrolling;
 }
 
-ScrollingNodeID RenderLayerCompositor::attachScrollingNode(RenderLayer& layer, ScrollingNodeType nodeType, Optional<ScrollingNodeID> parentNodeID)
+ScrollingNodeID RenderLayerCompositor::attachScrollingNode(RenderLayer& layer, ScrollingNodeType nodeType, ScrollingTreeState& treeState)
 {
     auto* scrollingCoordinator = this->scrollingCoordinator();
     auto* backing = layer.backing();
@@ -3872,24 +3769,29 @@
     if (!backing)
         return 0;
 
+    ASSERT(treeState.parentNodeID || nodeType == ScrollingNodeType::Subframe);
+    ASSERT_IMPLIES(nodeType == ScrollingNodeType::MainFrame, !treeState.parentNodeID.value());
+
     ScrollCoordinationRole role = scrollCoordinationRoleForNodeType(nodeType);
     ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(role);
     if (!nodeID)
         nodeID = scrollingCoordinator->uniqueScrollingNodeID();
 
-    LOG_WITH_STREAM(Scrolling, stream << "RenderLayerCompositor " << this << " attachScrollingNode " << nodeID << " type " << nodeType << " parent " << parentNodeID.valueOr(0));
+    LOG_WITH_STREAM(Scrolling, stream << "RenderLayerCompositor " << this << " attachScrollingNode " << nodeID << " (layer " << backing->graphicsLayer()->primaryLayerID() << ") type " << nodeType << " parent " << treeState.parentNodeID.valueOr(0));
 
-    if (nodeType == ScrollingNodeType::Subframe && !parentNodeID)
+    if (nodeType == ScrollingNodeType::Subframe && !treeState.parentNodeID)
         nodeID = scrollingCoordinator->createNode(nodeType, nodeID);
     else
-        nodeID = scrollingCoordinator->insertNode(nodeType, nodeID, parentNodeID.valueOr(0));
+        nodeID = scrollingCoordinator->insertNode(nodeType, nodeID, treeState.parentNodeID.valueOr(0), treeState.nextChildIndex);
 
+    ASSERT(nodeID);
     if (!nodeID)
         return 0;
-
+    
     backing->setScrollingNodeIDForRole(nodeID, role);
     m_scrollingNodeToLayerMap.add(nodeID, &layer);
-
+    
+    ++treeState.nextChildIndex;
     return nodeID;
 }
 
@@ -3929,148 +3831,177 @@
     backing->detachFromScrollingCoordinator(roles);
 }
 
-void RenderLayerCompositor::updateScrollCoordinationForThisFrame(Optional<ScrollingNodeID> parentNodeID, OptionSet<ScrollingNodeChangeFlags> changes)
+ScrollingNodeID RenderLayerCompositor::updateScrollCoordinationForLayer(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollCoordinationRole> roles, OptionSet<ScrollingNodeChangeFlags> changes)
 {
+    bool isViewportConstrained = roles.contains(ScrollCoordinationRole::ViewportConstrained);
+#if PLATFORM(IOS_FAMILY)
+    if (m_legacyScrollingLayerCoordinator) {
+        if (isViewportConstrained)
+            m_legacyScrollingLayerCoordinator->addViewportConstrainedLayer(layer);
+        else
+            m_legacyScrollingLayerCoordinator->removeViewportConstrainedLayer(layer);
+    }
+#endif
+
+    // GraphicsLayers need to know whether they are viewport-constrained.
+    layer.backing()->setIsScrollCoordinatedWithViewportConstrainedRole(isViewportConstrained);
+
+    if (!hasCoordinatedScrolling()) {
+        // If this frame isn't coordinated, it cannot contain any scrolling tree nodes.
+        return 0;
+    }
+
+    auto newNodeID = treeState.parentNodeID.valueOr(0);
+
+    ScrollingTreeState viewportConstrainedChildTreeState;
+    ScrollingTreeState* currentTreeState = &treeState;
+
+    // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling/frame hosting.
+    if (roles.contains(ScrollCoordinationRole::ViewportConstrained)) {
+        newNodeID = updateScrollingNodeForViewportConstrainedRole(layer, *currentTreeState, changes);
+        // ViewportConstrained nodes are the parent of same-layer scrolling nodes, so adjust the ScrollingTreeState.
+        viewportConstrainedChildTreeState.parentNodeID = newNodeID;
+        currentTreeState = &viewportConstrainedChildTreeState;
+    } else
+        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::ViewportConstrained);
+
+    if (roles.contains(ScrollCoordinationRole::Scrolling))
+        newNodeID = updateScrollingNodeForScrollingRole(layer, *currentTreeState, changes);
+    else
+        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::Scrolling);
+
+    if (roles.contains(ScrollCoordinationRole::FrameHosting))
+        newNodeID = updateScrollingNodeForFrameHostingRole(layer, *currentTreeState, changes);
+    else
+        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::FrameHosting);
+
+    return newNodeID;
+}
+
+ScrollingNodeID RenderLayerCompositor::updateScrollingNodeForViewportConstrainedRole(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes)
+{
     auto* scrollingCoordinator = this->scrollingCoordinator();
-    FrameView& frameView = m_renderView.frameView();
-    ASSERT(scrollingCoordinator->coordinatesScrollingForFrameView(frameView));
 
-    ScrollingNodeID nodeID = attachScrollingNode(*m_renderView.layer(), m_renderView.frame().isMainFrame() ? ScrollingNodeType::MainFrame : ScrollingNodeType::Subframe, parentNodeID);
+    auto nodeType = ScrollingNodeType::Fixed;
+    if (layer.renderer().style().position() == PositionType::Sticky)
+        nodeType = ScrollingNodeType::Sticky;
+    else
+        ASSERT(layer.renderer().isFixedPositioned());
 
+    auto newNodeID = attachScrollingNode(layer, nodeType, treeState);
+    if (!newNodeID) {
+        ASSERT_NOT_REACHED();
+        return treeState.parentNodeID.valueOr(0);
+    }
+
+    LOG_WITH_STREAM(Compositing, stream << "Registering ViewportConstrained " << nodeType << " node " << newNodeID << " (layer " << layer.backing()->graphicsLayer()->primaryLayerID() << ") as child of " << treeState.parentNodeID.valueOr(0));
+
     if (changes & ScrollingNodeChangeFlags::Layer)
-        scrollingCoordinator->setNodeLayers(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
+        scrollingCoordinator->setNodeLayers(newNodeID, layer.backing()->graphicsLayer());
 
     if (changes & ScrollingNodeChangeFlags::LayerGeometry) {
-        ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
-        // FIXME(https://webkit.org/b/172917): Pass parentRelativeScrollableRect?
-        scrollingGeometry.scrollOrigin = frameView.scrollOrigin();
-        scrollingGeometry.scrollableAreaSize = frameView.visibleContentRect().size();
-        scrollingGeometry.contentSize = frameView.totalContentsSize();
-        scrollingGeometry.reachableContentSize = frameView.totalContentsSize();
-#if ENABLE(CSS_SCROLL_SNAP)
-        frameView.updateSnapOffsets();
-        scrollingCoordinator->updateScrollSnapPropertiesWithFrameView(frameView);
-#endif
-        scrollingCoordinator->setScrollingNodeGeometry(nodeID, scrollingGeometry);
+        switch (nodeType) {
+        case ScrollingNodeType::Fixed:
+            scrollingCoordinator->setViewportConstraintedNodeGeometry(newNodeID, computeFixedViewportConstraints(layer));
+            break;
+        case ScrollingNodeType::Sticky:
+            scrollingCoordinator->setViewportConstraintedNodeGeometry(newNodeID, computeStickyViewportConstraints(layer));
+            break;
+        case ScrollingNodeType::MainFrame:
+        case ScrollingNodeType::Subframe:
+        case ScrollingNodeType::FrameHosting:
+        case ScrollingNodeType::Overflow:
+            break;
+        }
     }
+
+    return newNodeID;
 }
 
-void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, OptionSet<ScrollCoordinationRole> roles, OptionSet<ScrollingNodeChangeFlags> changes)
+ScrollingNodeID RenderLayerCompositor::updateScrollingNodeForScrollingRole(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes)
 {
-    bool isRenderViewLayer = layer.isRenderViewLayer();
-
-    ASSERT(m_scrollCoordinatedLayers.contains(&layer));
-    ASSERT(layer.isComposited());
-
     auto* scrollingCoordinator = this->scrollingCoordinator();
-    if (!scrollingCoordinator || !scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView()))
-        return;
 
-    if (!m_renderView.frame().isMainFrame()) {
-        auto parentDocumentHostingNodeID = scrollCoordinatedAncestorInParentOfFrame(m_renderView.frame());
-        updateScrollCoordinationForThisFrame(parentDocumentHostingNodeID, changes);
-        if (!(roles.contains(ScrollCoordinationRole::ViewportConstrained)) && isRenderViewLayer)
-            return;
-    }
+    ScrollingNodeID newNodeID = 0;
 
-    ScrollingNodeID parentNodeID = enclosingScrollingNodeID(layer, ExcludeSelf);
-    if (!parentNodeID && !isRenderViewLayer)
-        return;
+    if (layer.isRenderViewLayer()) {
+        FrameView& frameView = m_renderView.frameView();
+        ASSERT(scrollingCoordinator->coordinatesScrollingForFrameView(frameView));
 
-    auto* backing = layer.backing();
+        newNodeID = attachScrollingNode(*m_renderView.layer(), m_renderView.frame().isMainFrame() ? ScrollingNodeType::MainFrame : ScrollingNodeType::Subframe, treeState);
 
-    // Always call this even if the backing is already attached because the parent may have changed.
-    // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling.
-    if (roles.contains(ScrollCoordinationRole::ViewportConstrained)) {
-        ScrollingNodeType nodeType = ScrollingNodeType::MainFrame;
-        if (layer.renderer().isFixedPositioned())
-            nodeType = ScrollingNodeType::Fixed;
-        else if (layer.renderer().style().position() == PositionType::Sticky)
-            nodeType = ScrollingNodeType::Sticky;
-        else
+        if (!newNodeID) {
             ASSERT_NOT_REACHED();
+            return treeState.parentNodeID.valueOr(0);
+        }
 
-        ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
-        if (!nodeID)
-            return;
-            
-        LOG_WITH_STREAM(Compositing, stream << "Registering ViewportConstrained " << nodeType << " node " << nodeID << " (layer " << backing->graphicsLayer()->primaryLayerID() << ") as child of " << parentNodeID);
-
         if (changes & ScrollingNodeChangeFlags::Layer)
-            scrollingCoordinator->setNodeLayers(nodeID, backing->graphicsLayer());
+            scrollingCoordinator->setNodeLayers(newNodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
 
         if (changes & ScrollingNodeChangeFlags::LayerGeometry) {
-            switch (nodeType) {
-            case ScrollingNodeType::Fixed:
-                scrollingCoordinator->setViewportConstraintedNodeGeometry(nodeID, computeFixedViewportConstraints(layer));
-                break;
-            case ScrollingNodeType::Sticky:
-                scrollingCoordinator->setViewportConstraintedNodeGeometry(nodeID, computeStickyViewportConstraints(layer));
-                break;
-            case ScrollingNodeType::MainFrame:
-            case ScrollingNodeType::Subframe:
-            case ScrollingNodeType::FrameHosting:
-            case ScrollingNodeType::Overflow:
-                break;
-            }
+            ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
+            // FIXME(https://webkit.org/b/172917): Pass parentRelativeScrollableRect?
+            scrollingGeometry.scrollOrigin = frameView.scrollOrigin();
+            scrollingGeometry.scrollableAreaSize = frameView.visibleContentRect().size();
+            scrollingGeometry.contentSize = frameView.totalContentsSize();
+            scrollingGeometry.reachableContentSize = frameView.totalContentsSize();
+#if ENABLE(CSS_SCROLL_SNAP)
+            frameView.updateSnapOffsets();
+            scrollingCoordinator->updateScrollSnapPropertiesWithFrameView(frameView);
+#endif
+            scrollingCoordinator->setScrollingNodeGeometry(newNodeID, scrollingGeometry);
         }
+    } else {
+        newNodeID = attachScrollingNode(layer, ScrollingNodeType::Overflow, treeState);
+        if (!newNodeID) {
+            ASSERT_NOT_REACHED();
+            return treeState.parentNodeID.valueOr(0);
+        }
         
-        parentNodeID = nodeID;
-    } else
-        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::ViewportConstrained);
-        
-    if (roles.contains(ScrollCoordinationRole::Scrolling)) {
-        if (isRenderViewLayer)
-            updateScrollCoordinationForThisFrame(parentNodeID, changes);
-        else {
-            ScrollingNodeType nodeType = ScrollingNodeType::Overflow;
-            ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
-            if (!nodeID)
-                return;
+        if (changes & ScrollingNodeChangeFlags::Layer)
+            scrollingCoordinator->setNodeLayers(newNodeID, layer.backing()->scrollingLayer(), layer.backing()->scrollingContentsLayer());
 
-            if (changes & ScrollingNodeChangeFlags::Layer)
-                scrollingCoordinator->setNodeLayers(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer());
-
-            if (changes & ScrollingNodeChangeFlags::LayerGeometry) {
-                ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
-                // FIXME(https://webkit.org/b/172917): Pass parentRelativeScrollableRect?
-                scrollingGeometry.scrollOrigin = layer.scrollOrigin();
-                scrollingGeometry.scrollPosition = layer.scrollPosition();
-                scrollingGeometry.scrollableAreaSize = layer.visibleSize();
-                scrollingGeometry.contentSize = layer.contentsSize();
-                scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
+        if (changes & ScrollingNodeChangeFlags::LayerGeometry) {
+            ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
+            // FIXME(https://webkit.org/b/172917): Pass parentRelativeScrollableRect?
+            scrollingGeometry.scrollOrigin = layer.scrollOrigin();
+            scrollingGeometry.scrollPosition = layer.scrollPosition();
+            scrollingGeometry.scrollableAreaSize = layer.visibleSize();
+            scrollingGeometry.contentSize = layer.contentsSize();
+            scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
 #if ENABLE(CSS_SCROLL_SNAP)
-                if (const Vector<LayoutUnit>* offsets = layer.horizontalSnapOffsets())
-                    scrollingGeometry.horizontalSnapOffsets = *offsets;
-                if (const Vector<LayoutUnit>* offsets = layer.verticalSnapOffsets())
-                    scrollingGeometry.verticalSnapOffsets = *offsets;
-                if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.horizontalSnapOffsetRanges())
-                    scrollingGeometry.horizontalSnapOffsetRanges = *ranges;
-                if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.verticalSnapOffsetRanges())
-                    scrollingGeometry.verticalSnapOffsetRanges = *ranges;
-                scrollingGeometry.currentHorizontalSnapPointIndex = layer.currentHorizontalSnapPointIndex();
-                scrollingGeometry.currentVerticalSnapPointIndex = layer.currentVerticalSnapPointIndex();
+            if (const Vector<LayoutUnit>* offsets = layer.horizontalSnapOffsets())
+                scrollingGeometry.horizontalSnapOffsets = *offsets;
+            if (const Vector<LayoutUnit>* offsets = layer.verticalSnapOffsets())
+                scrollingGeometry.verticalSnapOffsets = *offsets;
+            if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.horizontalSnapOffsetRanges())
+                scrollingGeometry.horizontalSnapOffsetRanges = *ranges;
+            if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.verticalSnapOffsetRanges())
+                scrollingGeometry.verticalSnapOffsetRanges = *ranges;
+            scrollingGeometry.currentHorizontalSnapPointIndex = layer.currentHorizontalSnapPointIndex();
+            scrollingGeometry.currentVerticalSnapPointIndex = layer.currentVerticalSnapPointIndex();
 #endif
+            scrollingCoordinator->setScrollingNodeGeometry(newNodeID, scrollingGeometry);
+        }
+    }
 
-                LOG(Compositing, "Registering Scrolling scrolling node %" PRIu64 " (layer %" PRIu64 ") as child of %" PRIu64, nodeID, backing->graphicsLayer()->primaryLayerID(), parentNodeID);
+    return newNodeID;
+}
 
-                scrollingCoordinator->setScrollingNodeGeometry(nodeID, scrollingGeometry);
-            }
-        }
-    } else
-        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::Scrolling);
+ScrollingNodeID RenderLayerCompositor::updateScrollingNodeForFrameHostingRole(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes)
+{
+    auto* scrollingCoordinator = this->scrollingCoordinator();
 
-    if (roles.contains(ScrollCoordinationRole::FrameHosting)) {
-        ScrollingNodeID nodeID = attachScrollingNode(layer, ScrollingNodeType::FrameHosting, parentNodeID);
-        if (!nodeID)
-            return;
+    auto newNodeID = attachScrollingNode(layer, ScrollingNodeType::FrameHosting, treeState);
+    if (!newNodeID) {
+        ASSERT_NOT_REACHED();
+        return treeState.parentNodeID.valueOr(0);
+    }
 
-        if (changes & ScrollingNodeChangeFlags::Layer)
-            scrollingCoordinator->setNodeLayers(nodeID, backing->graphicsLayer());
+    if (changes & ScrollingNodeChangeFlags::Layer)
+        scrollingCoordinator->setNodeLayers(newNodeID, layer.backing()->graphicsLayer());
 
-        LOG(Compositing, "Registering Scrolling scrolling node %" PRIu64 " (layer %" PRIu64 ") as child of %" PRIu64, nodeID, backing->graphicsLayer()->primaryLayerID(), parentNodeID);
-    } else
-        detachScrollCoordinatedLayer(layer, ScrollCoordinationRole::FrameHosting);
+    return newNodeID;
 }
 
 ScrollableArea* RenderLayerCompositor::scrollableAreaForScrollLayerID(ScrollingNodeID nodeID) const
@@ -4083,10 +4014,8 @@
 
 void RenderLayerCompositor::willRemoveScrollingLayerWithBacking(RenderLayer& layer, RenderLayerBacking& backing)
 {
-    if (scrollingCoordinator()) {
-        backing.detachFromScrollingCoordinator(ScrollCoordinationRole::Scrolling);
+    if (scrollingCoordinator())
         return;
-    }
 
 #if PLATFORM(IOS_FAMILY)
     ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
@@ -4094,12 +4023,13 @@
         m_legacyScrollingLayerCoordinator->removeScrollingLayer(layer, backing);
 #else
     UNUSED_PARAM(layer);
+    UNUSED_PARAM(backing);
 #endif
 }
 
+// FIXME: This should really be called from the updateBackingAndHierarchy.
 void RenderLayerCompositor::didAddScrollingLayer(RenderLayer& layer)
 {
-    updateScrollCoordinatedStatus(layer, { ScrollingNodeChangeFlags::Layer, ScrollingNodeChangeFlags::LayerGeometry });
     if (scrollingCoordinator())
         return;
 
@@ -4107,6 +4037,8 @@
     ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
     if (m_legacyScrollingLayerCoordinator)
         m_legacyScrollingLayerCoordinator->addScrollingLayer(layer);
+#else
+    UNUSED_PARAM(layer);
 #endif
 }
 
@@ -4227,15 +4159,15 @@
 typedef HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>> LayerMap;
 typedef HashMap<PlatformLayer*, PlatformLayer*> StickyContainerMap;
 
-void LegacyWebKitScrollingLayerCoordinator::registerAllViewportConstrainedLayers(RenderLayerCompositor& compositor, const HashSet<RenderLayer*>& layers)
+void LegacyWebKitScrollingLayerCoordinator::registerAllViewportConstrainedLayers(RenderLayerCompositor& compositor)
 {
-    if (!m_coordinateViewportConstainedLayers)
+    if (!m_coordinateViewportConstrainedLayers)
         return;
 
     LayerMap layerMap;
     StickyContainerMap stickyContainerMap;
 
-    for (auto* layer : layers) {
+    for (auto* layer : m_viewportConstrainedLayers) {
         ASSERT(layer->isComposited());
 
         std::unique_ptr<ViewportConstraints> constraints;
@@ -4259,7 +4191,7 @@
 
 void LegacyWebKitScrollingLayerCoordinator::unregisterAllViewportConstrainedLayers()
 {
-    if (!m_coordinateViewportConstainedLayers)
+    if (!m_coordinateViewportConstrainedLayers)
         return;
 
     LayerMap layerMap;
@@ -4312,18 +4244,37 @@
 void LegacyWebKitScrollingLayerCoordinator::addScrollingLayer(RenderLayer& layer)
 {
     m_scrollingLayers.add(&layer);
+    m_scrollingLayersNeedingUpdate.add(&layer);
 }
 
 void LegacyWebKitScrollingLayerCoordinator::removeScrollingLayer(RenderLayer& layer, RenderLayerBacking& backing)
 {
     m_scrollingLayersNeedingUpdate.remove(&layer);
-    m_scrollingLayers.remove(&layer);
+    if (m_scrollingLayers.remove(&layer)) {
+        auto* scrollingLayer = backing.scrollingLayer()->platformLayer();
+        auto* contentsLayer = backing.scrollingContentsLayer()->platformLayer();
+        m_chromeClient.removeScrollingLayer(layer.renderer().element(), scrollingLayer, contentsLayer);
+    }
+}
 
-    auto* scrollingLayer = backing.scrollingLayer()->platformLayer();
-    auto* contentsLayer = backing.scrollingContentsLayer()->platformLayer();
-    m_chromeClient.removeScrollingLayer(layer.renderer().element(), scrollingLayer, contentsLayer);
+void LegacyWebKitScrollingLayerCoordinator::removeLayer(RenderLayer& layer)
+{
+    removeScrollingLayer(layer, *layer.backing());
+
+    // We'll put the new set of layers to the client via registerAllViewportConstrainedLayers() at flush time.
+    m_viewportConstrainedLayers.remove(&layer);
 }
 
+void LegacyWebKitScrollingLayerCoordinator::addViewportConstrainedLayer(RenderLayer& layer)
+{
+    m_viewportConstrainedLayers.add(&layer);
+}
+
+void LegacyWebKitScrollingLayerCoordinator::removeViewportConstrainedLayer(RenderLayer& layer)
+{
+    m_viewportConstrainedLayers.remove(&layer);
+}
+
 void LegacyWebKitScrollingLayerCoordinator::didChangePlatformLayerForLayer(RenderLayer& layer)
 {
     if (m_scrollingLayers.contains(&layer))

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (240697 => 240698)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2019-01-30 01:55:52 UTC (rev 240698)
@@ -92,13 +92,13 @@
 #if PLATFORM(IOS_FAMILY)
 class LegacyWebKitScrollingLayerCoordinator {
 public:
-    LegacyWebKitScrollingLayerCoordinator(ChromeClient& chromeClient, bool coordinateViewportConstainedLayers)
+    LegacyWebKitScrollingLayerCoordinator(ChromeClient& chromeClient, bool coordinateViewportConstrainedLayers)
         : m_chromeClient(chromeClient)
-        , m_coordinateViewportConstainedLayers(coordinateViewportConstainedLayers)
+        , m_coordinateViewportConstrainedLayers(coordinateViewportConstrainedLayers)
     {
     }
 
-    void registerAllViewportConstrainedLayers(RenderLayerCompositor&, const HashSet<RenderLayer*>&);
+    void registerAllViewportConstrainedLayers(RenderLayerCompositor&);
     void unregisterAllViewportConstrainedLayers();
     
     void registerAllScrollingLayers();
@@ -108,15 +108,23 @@
     void addScrollingLayer(RenderLayer&);
     void removeScrollingLayer(RenderLayer&, RenderLayerBacking&);
 
+    void addViewportConstrainedLayer(RenderLayer&);
+    void removeViewportConstrainedLayer(RenderLayer&);
+
     void didChangePlatformLayerForLayer(RenderLayer&);
 
+    void removeLayer(RenderLayer&);
+
 private:
     void updateScrollingLayer(RenderLayer&);
 
     ChromeClient& m_chromeClient;
+
     HashSet<RenderLayer*> m_scrollingLayers;
+    HashSet<RenderLayer*> m_viewportConstrainedLayers;
+
     HashSet<RenderLayer*> m_scrollingLayersNeedingUpdate;
-    const bool m_coordinateViewportConstainedLayers;
+    const bool m_coordinateViewportConstrainedLayers;
 };
 #endif
 
@@ -282,8 +290,6 @@
     void frameViewDidLayout();
     void rootLayerConfigurationChanged();
 
-    void fixedRootBackgroundLayerChanged();
-
     String layerTreeAsText(LayerTreeFlags);
 
     float deviceScaleFactor() const override;
@@ -315,19 +321,15 @@
     GraphicsLayer* updateLayerForFooter(bool wantsLayer);
 #endif
 
+    // FIXME: make the coordinated/async terminology consistent.
+    bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer&) const;
+    bool useCoordinatedScrollingForLayer(const RenderLayer&) const;
+    bool isLayerForIFrameWithScrollCoordinatedContents(const RenderLayer&) const;
+
     ScrollableArea* scrollableAreaForScrollLayerID(ScrollingNodeID) const;
 
-    enum class ScrollingNodeChangeFlags {
-        Layer           = 1 << 0,
-        LayerGeometry   = 1 << 1,
-    };
-
-    void updateScrollCoordinatedStatus(RenderLayer&, OptionSet<ScrollingNodeChangeFlags>);
     void removeFromScrollCoordinatedLayers(RenderLayer&);
 
-    bool useCoordinatedScrollingForLayer(const RenderLayer&) const;
-    bool isLayerForIFrameWithScrollCoordinatedContents(const RenderLayer&) const;
-
     void willRemoveScrollingLayerWithBacking(RenderLayer&, RenderLayerBacking&);
     void didAddScrollingLayer(RenderLayer&);
 
@@ -412,11 +414,8 @@
         CompositedChildren      = 1 << 1,
     };
     // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer.
-    void updateBackingAndHierarchy(RenderLayer&, Vector<Ref<GraphicsLayer>>& childGraphicsLayersOfEnclosingLayer, OptionSet<UpdateLevel> = { }, int depth = 0);
+    void updateBackingAndHierarchy(RenderLayer&, Vector<Ref<GraphicsLayer>>& childGraphicsLayersOfEnclosingLayer, struct ScrollingTreeState&, OptionSet<UpdateLevel> = { }, int depth = 0);
 
-    void setCompositingParent(RenderLayer& childLayer, RenderLayer* parentLayer);
-    void removeCompositedChildren(RenderLayer&);
-
     bool layerHas3DContent(const RenderLayer&) const;
     bool isRunningTransformAnimation(RenderLayerModelObject&) const;
 
@@ -441,8 +440,10 @@
 
     void notifyIFramesOfCompositingChange();
 
+#if PLATFORM(IOS_FAMILY)
     void updateScrollCoordinatedLayersAfterFlushIncludingSubframes();
     void updateScrollCoordinatedLayersAfterFlush();
+#endif
 
     FloatRect visibleRectForLayerFlushing() const;
     
@@ -475,14 +476,23 @@
 
     static bool styleChangeMayAffectIndirectCompositingReasons(const RenderStyle& oldStyle, const RenderStyle& newStyle);
 
-    void updateCustomLayersAfterFlush();
+    enum class ScrollingNodeChangeFlags {
+        Layer           = 1 << 0,
+        LayerGeometry   = 1 << 1,
+    };
 
-    void updateScrollCoordinationForThisFrame(Optional<ScrollingNodeID>, OptionSet<ScrollingNodeChangeFlags>);
-    ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, Optional<ScrollingNodeID> parentNodeID);
-    void updateScrollCoordinatedLayer(RenderLayer&, OptionSet<ScrollCoordinationRole>, OptionSet<ScrollingNodeChangeFlags>);
+    ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, struct ScrollingTreeState&);
+
+    // Returns the ScrollingNodeID which acts as the parent for children.
+    ScrollingNodeID updateScrollCoordinationForLayer(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollCoordinationRole>, OptionSet<ScrollingNodeChangeFlags>);
+
+    // These return the ScrollingNodeID which acts as the parent for children.
+    ScrollingNodeID updateScrollingNodeForViewportConstrainedRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>);
+    ScrollingNodeID updateScrollingNodeForScrollingRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>);
+    ScrollingNodeID updateScrollingNodeForFrameHostingRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>);
+
     void detachScrollCoordinatedLayer(RenderLayer&, OptionSet<ScrollCoordinationRole>);
     void detachScrollCoordinatedLayerWithRole(RenderLayer&, ScrollingCoordinator&, ScrollCoordinationRole);
-    void reattachSubframeScrollLayers();
     
     FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer&) const;
     StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer&) const;
@@ -501,8 +511,7 @@
 
     // FIXME: make the coordinated/async terminology consistent.
     bool isAsyncScrollableStickyLayer(const RenderLayer&, const RenderLayer** enclosingAcceleratedOverflowLayer = nullptr) const;
-    bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer&) const;
-    
+
     bool shouldCompositeOverflowControls() const;
 
     void scheduleLayerFlushNow();
@@ -539,7 +548,6 @@
     bool m_shouldFlushOnReattach { false };
     bool m_forceCompositingMode { false };
     bool m_inPostLayoutUpdate { false }; // true when it's OK to trust layout information (e.g. layer sizes and positions)
-    bool m_subframeScrollLayersNeedReattach { false };
 
     bool m_isTrackingRepaints { false }; // Used for testing.
 
@@ -554,9 +562,6 @@
     RefPtr<GraphicsLayer> m_clipLayer;
     RefPtr<GraphicsLayer> m_scrollLayer;
 
-    HashSet<RenderLayer*> m_scrollCoordinatedLayers;
-    HashSet<RenderLayer*> m_scrollCoordinatedLayersNeedingUpdate;
-
     // Enclosing layer for overflow controls and the clipping layer
     RefPtr<GraphicsLayer> m_overflowControlsHostLayer;
 

Modified: trunk/Source/WebKit/ChangeLog (240697 => 240698)


--- trunk/Source/WebKit/ChangeLog	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebKit/ChangeLog	2019-01-30 01:55:52 UTC (rev 240698)
@@ -1,3 +1,18 @@
+2019-01-29  Simon Fraser  <[email protected]>
+
+        Add nodes to the scrolling tree in z-index order.
+        https://bugs.webkit.org/show_bug.cgi?id=192529
+        <rdar://problem/47402708>
+
+        Reviewed by Dean Jackson.
+
+        FrameHosting nodes have layers, so need to update them.
+
+        * Platform/Logging.cpp:
+        (WebKit::initializeLogChannelsIfNecessary):
+        * UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+        (WebKit::RemoteScrollingCoordinatorProxy::connectStateNodeLayers):
+
 2019-01-29  Alex Christensen  <[email protected]>
 
         Change NetworkConnectionToWebProcess* to NetworkConnectionToWebProcess& where possible

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm (240697 => 240698)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm	2019-01-30 01:42:44 UTC (rev 240697)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm	2019-01-30 01:55:52 UTC (rev 240698)
@@ -84,11 +84,10 @@
         }
         case ScrollingNodeType::Fixed:
         case ScrollingNodeType::Sticky:
+        case ScrollingNodeType::FrameHosting:
             if (currNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))
                 currNode->setLayer(layerTreeHost.layerForID(currNode->layer()));
             break;
-        case ScrollingNodeType::FrameHosting:
-            break;
         }
     }
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to