[iOS WK2] Avoid lots of compositing backing store for offscreen position:fixed descen...
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Jul 2019 22:49:39 +0000 (22:49 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Jul 2019 22:49:39 +0000 (22:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=199819
rdar://problem/51977416

Reviewed by Zalan Bujtas.

Source/WebCore:

There was code to ensure that position:fixed layers and their descendants don't have their
backing store detached (thrown away to save memory when offscreen), since that can trigger
flashing when async scrolling moves layers in and out of the visual viewport.

However, some pages have many descendant layers of positon:fixed which entrain backing
store, because, for example, they have a stack of translated-offscreen menu elements inside
a fixed header, and those elements may composite because of overflow:scroll.

To avoid using too much memory on such pages, allow backing store detachment for fixed
layers that are outside the layout viewport. Add a flag to RenderLayer that's set for layers
which are fixed, or descendants of fixed, and consult that flag in
updateAllowsBackingStoreDetaching(). The logic there is similar to
RenderLayerCompositor::requiresCompositingForPosition().

I considered allowing all position:fixed to composite (since this patch would keep most of
the memory saving), but historically we've avoided compositing out-of-viewport
position:fixed because it's quite common to have them with negative z-index, and compositing
those has significant compositing knock-on effects.

GraphicsLayer flushing no longer needs to track the viewport-constrained status of layers,
so remove that code.

This patch removes backing-store pinning for sticky layers.
scrolling/ios/reconcile-layer-position-recursive.html then revealed a bug in
ScrollingStateStickyNode::reconcileLayerPositionForViewportRect(), which was assuming that
the sticky element was scrolled by the page, causing a bad layer position to get sync'd onto
the layer. Fixed by copying code from ScrollingTreeStickyNode that is smarter about
computing layer positions.

This patch fixes jetsams on kmart.com.au in iOS 13 beta.

Test: compositing/layer-creation/fixed-position-descendants-out-of-view.html

* page/scrolling/ScrollingStateStickyNode.cpp:
(WebCore::ScrollingStateStickyNode::computeLayerPosition const):
(WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):
* page/scrolling/ScrollingStateStickyNode.h:
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setAllowsBackingStoreDetaching):
(WebCore::GraphicsLayer::allowsBackingStoreDetaching const):
(WebCore::GraphicsLayer::setIsViewportConstrained): Deleted.
(WebCore::GraphicsLayer::isViewportConstrained const): Deleted.
(WebCore::GraphicsLayer::setCanDetachBackingStore): Deleted.
(WebCore::GraphicsLayer::canDetachBackingStore const): Deleted.
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::GraphicsLayerCA):
(WebCore::GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush const):
(WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):
(WebCore::GraphicsLayerCA::recursiveCommitChanges):
(WebCore::GraphicsLayerCA::updateCoverage):
(WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::updateLayerPositions):
(WebCore::outputPaintOrderTreeLegend):
(WebCore::outputPaintOrderTreeRecursive):
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateAllowsBackingStoreDetaching):
(WebCore::RenderLayerBacking::updateOverflowControlsLayers):
(WebCore::RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole): Deleted.
* rendering/RenderLayerBacking.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::requiresCompositingForPosition const):
(WebCore::RenderLayerCompositor::updateOverflowControlsLayers):
(WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer):

LayoutTests:

* compositing/layer-creation/fixed-position-change-out-of-view-in-view.html:
* compositing/layer-creation/fixed-position-descendants-out-of-view-expected.txt: Added.
* compositing/layer-creation/fixed-position-descendants-out-of-view.html: Added.
* compositing/layer-creation/fixed-position-out-of-view.html:
* platform/ios-wk2/fast/scrolling/ios/reconcile-layer-position-recursive-expected.txt: Added.

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html
LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view-expected.txt [new file with mode: 0644]
LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view.html [new file with mode: 0644]
LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html
LayoutTests/platform/ios-wk2/fast/scrolling/ios/reconcile-layer-position-recursive-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/scrolling/ScrollingStateStickyNode.cpp
Source/WebCore/page/scrolling/ScrollingStateStickyNode.h
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp

index d8232b4..0cf55f1 100644 (file)
@@ -1,3 +1,17 @@
+2019-07-17  Simon Fraser  <simon.fraser@apple.com>
+
+        [iOS WK2] Avoid lots of compositing backing store for offscreen position:fixed descendants
+        https://bugs.webkit.org/show_bug.cgi?id=199819
+        rdar://problem/51977416
+
+        Reviewed by Zalan Bujtas.
+
+        * compositing/layer-creation/fixed-position-change-out-of-view-in-view.html:
+        * compositing/layer-creation/fixed-position-descendants-out-of-view-expected.txt: Added.
+        * compositing/layer-creation/fixed-position-descendants-out-of-view.html: Added.
+        * compositing/layer-creation/fixed-position-out-of-view.html:
+        * platform/ios-wk2/fast/scrolling/ios/reconcile-layer-position-recursive-expected.txt: Added.
+
 2019-07-17  Alex Christensen  <achristensen@webkit.org>
 
         Add a runtime-disabled dialog element skeleton
index 1b4a762..e48e00c 100644 (file)
@@ -3,9 +3,13 @@
 <html>
 <head>
   <style>
-    #fixed1, #fixed2 {
-        background-color: silver;
-    }
+      .fixed {
+          position: fixed;
+          width: 10px;
+          height: 10px;
+          background-color: silver;
+          transform: translateX(0); /* Defeat clip to viewport */
+      }
   </style>
   <script type="text/javascript">
     if (window.testRunner && window.internals) {
       internals.settings.setAcceleratedCompositingForFixedPositionEnabled(true);
 
       addEventListener("load", function() {
-        document.getElementById("layerTree1").innerText = internals.layerTreeAsText(document);
+        let layers1 = internals.layerTreeAsText(document);
         document.getElementById("fixed1").style.top = "50px";
         document.getElementById("fixed2").style.height = "10px";
-        document.getElementById("layerTree2").innerText = internals.layerTreeAsText(document);
+
+        let layers2 = internals.layerTreeAsText(document);
         document.getElementById("fixed1").style.top = "-100px";
         document.getElementById("fixed2").style.height = "0px";
-        document.getElementById("layerTree3").innerText = internals.layerTreeAsText(document);
+
+        let layers3 = internals.layerTreeAsText(document);
+        document.getElementById("layerTree1").innerText = layers1;
+        document.getElementById("layerTree2").innerText = layers2;
+        document.getElementById("layerTree3").innerText = layers3;
       }, false);
     }
   </script>
@@ -32,8 +41,7 @@
   <pre id="layerTree2"></pre>
   Layer tree when the fixed elements are out-of-view again (should be blank):
   <pre id="layerTree3"></pre>
-  <div id="fixed1" style="position: fixed; top: -100px; left: 100px; width: 10px; height: 10px"></div>
-  <div id="fixed2" style="position: fixed; top: 100px; left: 100px; width: 10px; height: 0px"></div>
+  <div id="fixed1" class="fixed" style="top: -100px; left: 100px;"></div>
+  <div id="fixed2" class="fixed" style="top: 100px; left: 100px; height: 0px"></div>
 </body>
 </html>
-
diff --git a/LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view-expected.txt b/LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view-expected.txt
new file mode 100644 (file)
index 0000000..c5b7352
--- /dev/null
@@ -0,0 +1,57 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (backingStoreAttached 1)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (backingStoreAttached 1)
+      (children 3
+        (GraphicsLayer
+          (position 8.00 13.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (backingStoreAttached 1)
+          (children 1
+            (GraphicsLayer
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (backingStoreAttached 1)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 120.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (backingStoreAttached 0)
+          (transform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 0.00] [-110.00 0.00 0.00 1.00])
+          (children 1
+            (GraphicsLayer
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (backingStoreAttached 0)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 240.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (backingStoreAttached 0)
+          (transform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 0.00] [-110.00 0.00 0.00 1.00])
+          (children 1
+            (GraphicsLayer
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (backingStoreAttached 1)
+              (transform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 0.00] [122.40 0.00 0.00 1.00])
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view.html b/LayoutTests/compositing/layer-creation/fixed-position-descendants-out-of-view.html
new file mode 100644 (file)
index 0000000..00d5ccb
--- /dev/null
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .fixed {
+            position: fixed;
+            width: 100px;
+            height: 100px;
+            background-color: silver;
+            transform: translateX(0); /* Defeat clip to viewport */
+        }
+        
+        .offscreen {
+            transform: translateX(-110%);
+        }
+        
+        .absolute {
+            position: absolute;
+            width: 100px;
+            height: 100px;
+            border: 1px solid black;
+            transform: translateZ(0);
+        }
+        
+        .absolute.onscreen {
+            transform: translate3d(120%, 0, 0);
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+
+        window.addEventListener("load", () => {
+                document.getElementById("layertree").innerText = window.internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED);
+            }, false);
+        }
+    </script>
+</head>
+
+<body>
+
+    <div class="fixed container">
+        <div class="absolute">
+        </div>
+    </div>
+
+    <div class="fixed offscreen container" style="top: 120px">
+        <div class="absolute">
+        </div>
+    </div>
+
+    <div class="fixed offscreen container" style="top: 240px">
+        <div class="absolute onscreen">
+        </div>
+    </div>
+
+    <pre id="layertree"></pre>
+</body>
+</html>
+
index 3fda5e5..0e6f447 100644 (file)
@@ -8,6 +8,7 @@
       width: 10px;
       height: 10px;
       background-color: silver;
+      transform: translateX(0); /* Defeat clip to viewport */
     }
   </style>
 
diff --git a/LayoutTests/platform/ios-wk2/fast/scrolling/ios/reconcile-layer-position-recursive-expected.txt b/LayoutTests/platform/ios-wk2/fast/scrolling/ios/reconcile-layer-position-recursive-expected.txt
new file mode 100644 (file)
index 0000000..b686ad5
--- /dev/null
@@ -0,0 +1,138 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 1621.00)
+  (visible rect 0.00, 1021.00 800.00 x 600.00)
+  (coverage rect 0.00, 1021.00 800.00 x 600.00)
+  (intersects coverage rect 1)
+  (contentsScale 2.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 1621.00)
+      (contentsOpaque 1)
+      (visible rect 0.00, 1021.00 800.00 x 600.00)
+      (coverage rect 0.00, 765.00 1056.00 x 856.00)
+      (intersects coverage rect 1)
+      (contentsScale 2.00)
+      (tile cache coverage 0, 512 800 x 1109)
+      (tile size 800 x 512)
+      (top left tile 0, 1 tiles grid 1 x 3)
+      (in window 1)
+      (children 1
+        (GraphicsLayer
+          (position 8.00 1008.00)
+          (bounds 300.00 300.00)
+          (drawsContent 1)
+          (visible rect 0.00, 13.00 300.00 x 287.00)
+          (coverage rect -8.00, -243.00 1056.00 x 856.00)
+          (intersects coverage rect 1)
+          (contentsScale 2.00)
+          (children 1
+            (GraphicsLayer
+              (bounds 300.00 300.00)
+              (visible rect 0.00, 13.00 300.00 x 287.00)
+              (coverage rect 0.00, 13.00 300.00 x 287.00)
+              (intersects coverage rect 1)
+              (contentsScale 2.00)
+              (children 1
+                (GraphicsLayer
+                  (anchor 0.00 0.00)
+                  (bounds 300.00 510.00)
+                  (drawsContent 1)
+                  (visible rect 0.00, 13.00 300.00 x 287.00)
+                  (coverage rect 0.00, 12.00 300.00 x 288.00)
+                  (intersects coverage rect 1)
+                  (contentsScale 2.00)
+                  (children 1
+                    (GraphicsLayer
+                      (position 50.00 50.00)
+                      (bounds 210.00 410.00)
+                      (drawsContent 1)
+                      (visible rect 0.00, 0.00 210.00 x 250.00)
+                      (coverage rect -50.00, -38.00 300.00 x 288.00)
+                      (intersects coverage rect 1)
+                      (contentsScale 2.00)
+                      (children 1
+                        (GraphicsLayer
+                          (offsetFromRenderer width=5 height=5)
+                          (position 5.00 5.00)
+                          (bounds 200.00 400.00)
+                          (visible rect 0.00, 0.00 200.00 x 245.00)
+                          (coverage rect 0.00, 0.00 200.00 x 245.00)
+                          (intersects coverage rect 1)
+                          (contentsScale 2.00)
+                          (children 1
+                            (GraphicsLayer
+                              (offsetFromRenderer width=5 height=5)
+                              (anchor 0.00 0.00)
+                              (bounds 270.00 610.00)
+                              (drawsContent 1)
+                              (visible rect 0.00, 0.00 200.00 x 245.00)
+                              (coverage rect 0.00, 0.00 200.00 x 245.00)
+                              (intersects coverage rect 1)
+                              (contentsScale 2.00)
+                              (children 2
+                                (GraphicsLayer
+                                  (position 7.00 28.00)
+                                  (approximate position 7.00 28.00)
+                                  (bounds 110.00 110.00)
+                                  (contentsOpaque 1)
+                                  (drawsContent 1)
+                                  (visible rect 0.00, 0.00 110.00 x 110.00)
+                                  (coverage rect -7.00, -28.00 200.00 x 245.00)
+                                  (intersects coverage rect 1)
+                                  (contentsScale 2.00)
+                                  (children 1
+                                    (GraphicsLayer
+                                      (position 55.00 55.00)
+                                      (approximate position 55.00 55.00)
+                                      (bounds 110.00 110.00)
+                                      (contentsOpaque 1)
+                                      (drawsContent 1)
+                                      (visible rect 0.00, 0.00 110.00 x 110.00)
+                                      (coverage rect -62.00, -83.00 200.00 x 245.00)
+                                      (intersects coverage rect 1)
+                                      (contentsScale 2.00)
+                                    )
+                                  )
+                                )
+                                (GraphicsLayer
+                                  (position 105.00 105.00)
+                                  (approximate position 105.00 105.00)
+                                  (bounds 110.00 110.00)
+                                  (contentsOpaque 1)
+                                  (drawsContent 1)
+                                  (visible rect 0.00, 0.00 95.00 x 110.00)
+                                  (coverage rect -105.00, -105.00 200.00 x 245.00)
+                                  (intersects coverage rect 1)
+                                  (contentsScale 2.00)
+                                  (children 1
+                                    (GraphicsLayer
+                                      (position 55.00 55.00)
+                                      (approximate position 55.00 55.00)
+                                      (bounds 110.00 110.00)
+                                      (contentsOpaque 1)
+                                      (drawsContent 1)
+                                      (visible rect 0.00, 0.00 40.00 x 85.00)
+                                      (coverage rect -160.00, -160.00 200.00 x 245.00)
+                                      (intersects coverage rect 1)
+                                      (contentsScale 2.00)
+                                    )
+                                  )
+                                )
+                              )
+                            )
+                          )
+                        )
+                      )
+                    )
+                  )
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
index dfa44ab..be247b0 100644 (file)
@@ -1,3 +1,80 @@
+2019-07-17  Simon Fraser  <simon.fraser@apple.com>
+
+        [iOS WK2] Avoid lots of compositing backing store for offscreen position:fixed descendants
+        https://bugs.webkit.org/show_bug.cgi?id=199819
+        rdar://problem/51977416
+
+        Reviewed by Zalan Bujtas.
+
+        There was code to ensure that position:fixed layers and their descendants don't have their
+        backing store detached (thrown away to save memory when offscreen), since that can trigger
+        flashing when async scrolling moves layers in and out of the visual viewport.
+
+        However, some pages have many descendant layers of positon:fixed which entrain backing
+        store, because, for example, they have a stack of translated-offscreen menu elements inside
+        a fixed header, and those elements may composite because of overflow:scroll.
+
+        To avoid using too much memory on such pages, allow backing store detachment for fixed
+        layers that are outside the layout viewport. Add a flag to RenderLayer that's set for layers
+        which are fixed, or descendants of fixed, and consult that flag in
+        updateAllowsBackingStoreDetaching(). The logic there is similar to
+        RenderLayerCompositor::requiresCompositingForPosition().
+        
+        I considered allowing all position:fixed to composite (since this patch would keep most of
+        the memory saving), but historically we've avoided compositing out-of-viewport
+        position:fixed because it's quite common to have them with negative z-index, and compositing
+        those has significant compositing knock-on effects.
+        
+        GraphicsLayer flushing no longer needs to track the viewport-constrained status of layers,
+        so remove that code.
+        
+        This patch removes backing-store pinning for sticky layers.
+        scrolling/ios/reconcile-layer-position-recursive.html then revealed a bug in
+        ScrollingStateStickyNode::reconcileLayerPositionForViewportRect(), which was assuming that
+        the sticky element was scrolled by the page, causing a bad layer position to get sync'd onto
+        the layer. Fixed by copying code from ScrollingTreeStickyNode that is smarter about
+        computing layer positions.
+        
+        This patch fixes jetsams on kmart.com.au in iOS 13 beta.
+
+        Test: compositing/layer-creation/fixed-position-descendants-out-of-view.html
+
+        * page/scrolling/ScrollingStateStickyNode.cpp:
+        (WebCore::ScrollingStateStickyNode::computeLayerPosition const):
+        (WebCore::ScrollingStateStickyNode::reconcileLayerPositionForViewportRect):
+        * page/scrolling/ScrollingStateStickyNode.h:
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setAllowsBackingStoreDetaching):
+        (WebCore::GraphicsLayer::allowsBackingStoreDetaching const):
+        (WebCore::GraphicsLayer::setIsViewportConstrained): Deleted.
+        (WebCore::GraphicsLayer::isViewportConstrained const): Deleted.
+        (WebCore::GraphicsLayer::setCanDetachBackingStore): Deleted.
+        (WebCore::GraphicsLayer::canDetachBackingStore const): Deleted.
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::GraphicsLayerCA):
+        (WebCore::GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush const):
+        (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):
+        (WebCore::GraphicsLayerCA::recursiveCommitChanges):
+        (WebCore::GraphicsLayerCA::updateCoverage):
+        (WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::updateLayerPositions):
+        (WebCore::outputPaintOrderTreeLegend):
+        (WebCore::outputPaintOrderTreeRecursive):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateAllowsBackingStoreDetaching):
+        (WebCore::RenderLayerBacking::updateOverflowControlsLayers):
+        (WebCore::RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole): Deleted.
+        * rendering/RenderLayerBacking.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+        (WebCore::RenderLayerCompositor::requiresCompositingForPosition const):
+        (WebCore::RenderLayerCompositor::updateOverflowControlsLayers):
+        (WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer):
+
 2019-07-17  Chris Dumez  <cdumez@apple.com>
 
         Avoid unnecessary copy of monitors under DisplayRefreshMonitorManager::displayWasUpdated()
index d908f0d..c18a84b 100644 (file)
 
 #include "GraphicsLayer.h"
 #include "Logging.h"
+#include "ScrollingStateFixedNode.h"
+#include "ScrollingStateFrameScrollingNode.h"
+#include "ScrollingStateOverflowScrollProxyNode.h"
+#include "ScrollingStateOverflowScrollingNode.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingTree.h"
 #include <wtf/text/TextStream.h>
@@ -76,9 +80,45 @@ void ScrollingStateStickyNode::updateConstraints(const StickyPositionViewportCon
     setPropertyChanged(ViewportConstraints);
 }
 
+FloatPoint ScrollingStateStickyNode::computeLayerPosition(const LayoutRect& viewportRect) const
+{
+    // This logic follows ScrollingTreeStickyNode::computeLayerPosition().
+    auto computeLayerPositionForScrollingNode = [&](ScrollingStateNode& scrollingStateNode) {
+        FloatRect constrainingRect;
+        if (is<ScrollingStateFrameScrollingNode>(scrollingStateNode))
+            constrainingRect = viewportRect;
+        else {
+            auto& overflowScrollingNode = downcast<ScrollingStateOverflowScrollingNode>(scrollingStateNode);
+            constrainingRect = FloatRect(overflowScrollingNode.scrollPosition(), m_constraints.constrainingRectAtLastLayout().size());
+        }
+        return m_constraints.layerPositionForConstrainingRect(constrainingRect);
+    };
+
+    for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+        if (is<ScrollingStateOverflowScrollProxyNode>(*ancestor)) {
+            auto& overflowProxyNode = downcast<ScrollingStateOverflowScrollProxyNode>(*ancestor);
+            auto overflowNode = scrollingStateTree().stateNodeForID(overflowProxyNode.overflowScrollingNode());
+            if (!overflowNode)
+                break;
+
+            return computeLayerPositionForScrollingNode(*overflowNode);
+        }
+
+        if (is<ScrollingStateScrollingNode>(*ancestor))
+            return computeLayerPositionForScrollingNode(*ancestor);
+
+        if (is<ScrollingStateFixedNode>(*ancestor) || is<ScrollingStateStickyNode>(*ancestor)) {
+            // FIXME: Do we need scrolling tree nodes at all for nested cases?
+            return m_constraints.layerPositionAtLastLayout();
+        }
+    }
+    ASSERT_NOT_REACHED();
+    return m_constraints.layerPositionAtLastLayout();
+}
+
 void ScrollingStateStickyNode::reconcileLayerPositionForViewportRect(const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
 {
-    FloatPoint position = m_constraints.layerPositionForConstrainingRect(viewportRect);
+    FloatPoint position = computeLayerPosition(viewportRect);
     if (layer().representsGraphicsLayer()) {
         auto* graphicsLayer = static_cast<GraphicsLayer*>(layer());
 
index c09f581..1fbba4d 100644 (file)
@@ -57,6 +57,7 @@ private:
 
     void setPropertyChangedBitsAfterReattach() override;
 
+    FloatPoint computeLayerPosition(const LayoutRect& viewportRect) const;
     void reconcileLayerPositionForViewportRect(const LayoutRect& viewportRect, ScrollingLayerPositionAction) override;
 
     void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const override;
index e395716..009d486 100644 (file)
@@ -557,9 +557,9 @@ public:
     float pageScaleFactor() const { return client().pageScaleFactor(); }
     float deviceScaleFactor() const { return client().deviceScaleFactor(); }
     
-    // Whether this layer is viewport constrained, implying that it's moved around externally from GraphicsLayer (e.g. by the scrolling tree).
-    virtual void setIsViewportConstrained(bool) { }
-    virtual bool isViewportConstrained() const { return false; }
+    // Whether this layer can throw away backing store to save memory. False for layers that can be revealed by async scrolling.
+    virtual void setAllowsBackingStoreDetaching(bool) { }
+    virtual bool allowsBackingStoreDetaching() const { return true; }
 
     virtual void deviceOrPageScaleFactorChanged() { }
     WEBCORE_EXPORT void noteDeviceOrPageScaleFactorChangedIncludingDescendants();
@@ -595,9 +595,6 @@ public:
     virtual bool backingStoreAttached() const { return true; }
     virtual bool backingStoreAttachedForTesting() const { return backingStoreAttached(); }
 
-    void setCanDetachBackingStore(bool b) { m_canDetachBackingStore = b; }
-    bool canDetachBackingStore() const { return m_canDetachBackingStore; }
-
     virtual TiledBacking* tiledBacking() const { return 0; }
 
     void resetTrackedRepaints();
index 5d8658a..171f277 100644 (file)
@@ -403,7 +403,7 @@ GraphicsLayerCA::GraphicsLayerCA(Type layerType, GraphicsLayerClient& client)
     : GraphicsLayer(layerType, client)
     , m_needsFullRepaint(false)
     , m_usingBackdropLayerType(false)
-    , m_isViewportConstrained(false)
+    , m_allowsBackingStoreDetaching(true)
     , m_intersectsCoverageRect(false)
     , m_hasEverPainted(false)
     , m_hasDescendantsWithRunningTransformAnimations(false)
@@ -1312,8 +1312,7 @@ bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const CommitState&
 
     auto bounds = FloatRect(m_boundsOrigin, size());
 
-    bool isViewportConstrained = m_isViewportConstrained || commitState.ancestorIsViewportConstrained;
-    bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
+    bool intersectsCoverageRect = rects.coverageRect.intersects(bounds);
     if (intersectsCoverageRect != m_intersectsCoverageRect)
         return true;
 
@@ -1324,8 +1323,6 @@ bool GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush(const CommitState&
         }
     }
 
-    childCommitState.ancestorIsViewportConstrained |= m_isViewportConstrained;
-
     if (m_maskLayer) {
         auto& maskLayerCA = downcast<GraphicsLayerCA>(*m_maskLayer);
         if (maskLayerCA.recursiveVisibleRectChangeRequiresFlush(childCommitState, localState))
@@ -1470,7 +1467,7 @@ bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const F
     return true;
 }
 
-void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& rects, bool isViewportConstrained)
+void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& rects)
 {
     bool visibleRectChanged = rects.visibleRect != m_visibleRect;
     bool coverageRectChanged = rects.coverageRect != m_coverageRect;
@@ -1484,7 +1481,7 @@ void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects&
     }
 
     // FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
-    bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
+    bool intersectsCoverageRect = rects.coverageRect.intersects(bounds);
     if (intersectsCoverageRect != m_intersectsCoverageRect) {
         addUncommittedChanges(CoverageRectChanged);
         m_intersectsCoverageRect = intersectsCoverageRect;
@@ -1538,7 +1535,7 @@ void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const Tra
             localState.setLastPlanarSecondaryQuad(&secondaryQuad);
         }
     }
-    setVisibleAndCoverageRects(rects, m_isViewportConstrained || commitState.ancestorIsViewportConstrained);
+    setVisibleAndCoverageRects(rects);
 
     if (commitState.ancestorStartedOrEndedTransformAnimation)
         addUncommittedChanges(CoverageRectChanged);
@@ -1601,10 +1598,8 @@ void GraphicsLayerCA::recursiveCommitChanges(CommitState& commitState, const Tra
         affectedByTransformAnimation = true;
     }
     
-    childCommitState.ancestorIsViewportConstrained |= m_isViewportConstrained;
-
     if (GraphicsLayerCA* maskLayer = downcast<GraphicsLayerCA>(m_maskLayer.get())) {
-        maskLayer->setVisibleAndCoverageRects(rects, m_isViewportConstrained || commitState.ancestorIsViewportConstrained);
+        maskLayer->setVisibleAndCoverageRects(rects);
         maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, layerTypeChanged);
     }
 
@@ -2415,32 +2410,34 @@ void GraphicsLayerCA::updateCoverage(const CommitState& commitState)
         backing->setCoverageRect(m_coverageRect);
     }
 
-    if (canDetachBackingStore()) {
-        bool requiresBacking = m_intersectsCoverageRect
-            || commitState.ancestorWithTransformAnimationIntersectsCoverageRect // FIXME: Compute backing exactly for descendants of animating layers.
-            || (isRunningTransformAnimation() && !animationExtent()); // Create backing if we don't know the animation extent.
+    bool requiresBacking = m_intersectsCoverageRect
+        || !allowsBackingStoreDetaching()
+        || commitState.ancestorWithTransformAnimationIntersectsCoverageRect // FIXME: Compute backing exactly for descendants of animating layers.
+        || (isRunningTransformAnimation() && !animationExtent()); // Create backing if we don't know the animation extent.
 
 #if !LOG_DISABLED
-        if (requiresBacking) {
-            auto reasonForBacking = [&]() -> const char* {
-                if (m_intersectsCoverageRect)
-                    return "intersectsCoverageRect";
-                
-                if (commitState.ancestorWithTransformAnimationIntersectsCoverageRect)
-                    return "ancestor with transform";
-                
-                return "has transform animation with unknown extent";
-            };
-            LOG_WITH_STREAM(Layers, stream << "GraphicsLayerCA " << this << " id " << primaryLayerID() << " setBackingStoreAttached: " << requiresBacking << " (" << reasonForBacking() << ")");
-        } else
-            LOG_WITH_STREAM(Layers, stream << "GraphicsLayerCA " << this << " id " << primaryLayerID() << " setBackingStoreAttached: " << requiresBacking);
+    if (requiresBacking) {
+        auto reasonForBacking = [&]() -> const char* {
+            if (m_intersectsCoverageRect)
+                return "intersectsCoverageRect";
+            
+            if (!allowsBackingStoreDetaching())
+                return "backing detachment disallowed";
+
+            if (commitState.ancestorWithTransformAnimationIntersectsCoverageRect)
+                return "ancestor with transform";
+            
+            return "has transform animation with unknown extent";
+        };
+        LOG_WITH_STREAM(Layers, stream << "GraphicsLayerCA " << this << " id " << primaryLayerID() << " setBackingStoreAttached: " << requiresBacking << " (" << reasonForBacking() << ")");
+    } else
+        LOG_WITH_STREAM(Layers, stream << "GraphicsLayerCA " << this << " id " << primaryLayerID() << " setBackingStoreAttached: " << requiresBacking);
 #endif
 
-        m_layer->setBackingStoreAttached(requiresBacking);
-        if (m_layerClones) {
-            for (auto& layer : m_layerClones->primaryLayerClones.values())
-                layer->setBackingStoreAttached(requiresBacking);
-        }
+    m_layer->setBackingStoreAttached(requiresBacking);
+    if (m_layerClones) {
+        for (auto& layer : m_layerClones->primaryLayerClones.values())
+            layer->setBackingStoreAttached(requiresBacking);
     }
 
     m_sizeAtLastCoverageRectUpdate = m_size;
@@ -3639,6 +3636,15 @@ String GraphicsLayerCA::displayListAsText(DisplayList::AsTextFlags flags) const
     return m_displayList->asText(flags);
 }
 
+void GraphicsLayerCA::setAllowsBackingStoreDetaching(bool allowDetaching)
+{
+    if (allowDetaching == m_allowsBackingStoreDetaching)
+        return;
+
+    m_allowsBackingStoreDetaching = allowDetaching;
+    noteLayerPropertyChanged(CoverageRectChanged);
+}
+
 void GraphicsLayerCA::setIsTrackingDisplayListReplay(bool isTracking)
 {
     if (isTracking == m_isTrackingDisplayListReplay)
@@ -4118,15 +4124,6 @@ void GraphicsLayerCA::updateOpacityOnLayer()
     }
 }
 
-void GraphicsLayerCA::setIsViewportConstrained(bool isViewportConstrained)
-{
-    if (isViewportConstrained == m_isViewportConstrained)
-        return;
-
-    m_isViewportConstrained = isViewportConstrained;
-    noteLayerPropertyChanged(CoverageRectChanged);
-}
-
 void GraphicsLayerCA::deviceOrPageScaleFactorChanged()
 {
     noteChangesForScaleSensitiveProperties();
index c921d5f..3ac4c1e 100644 (file)
@@ -163,7 +163,6 @@ public:
         bool ancestorHasTransformAnimation { false };
         bool ancestorStartedOrEndedTransformAnimation { false };
         bool ancestorWithTransformAnimationIntersectsCoverageRect { false };
-        bool ancestorIsViewportConstrained { false };
     };
     bool needsCommit(const CommitState&);
     void recursiveCommitChanges(CommitState&, const TransformState&, float pageScaleFactor = 1, const FloatPoint& positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false);
@@ -215,8 +214,8 @@ private:
     bool isCommittingChanges() const override { return m_isCommittingChanges; }
     bool isUsingDisplayListDrawing(PlatformCALayer*) const override { return m_usesDisplayListDrawing; }
 
-    WEBCORE_EXPORT void setIsViewportConstrained(bool) override;
-    bool isViewportConstrained() const override { return m_isViewportConstrained; }
+    WEBCORE_EXPORT void setAllowsBackingStoreDetaching(bool) override;
+    bool allowsBackingStoreDetaching() const override { return m_allowsBackingStoreDetaching; }
 
     WEBCORE_EXPORT String displayListAsText(DisplayList::AsTextFlags) const override;
 
@@ -321,7 +320,7 @@ private:
     const FloatRect& visibleRect() const { return m_visibleRect; }
     const FloatRect& coverageRect() const { return m_coverageRect; }
 
-    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&, bool isViewportConstrained);
+    void setVisibleAndCoverageRects(const VisibleAndCoverageRects&);
     
     bool recursiveVisibleRectChangeRequiresFlush(const CommitState&, const TransformState&) const;
     
@@ -625,7 +624,7 @@ private:
 
     bool m_needsFullRepaint : 1;
     bool m_usingBackdropLayerType : 1;
-    bool m_isViewportConstrained : 1;
+    bool m_allowsBackingStoreDetaching : 1;
     bool m_intersectsCoverageRect : 1;
     bool m_hasEverPainted : 1;
     bool m_hasDescendantsWithRunningTransformAnimations : 1;
index 5a8b2d3..852f9bf 100644 (file)
@@ -303,6 +303,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_hasVisibleDescendant(false)
     , m_registeredScrollableArea(false)
     , m_isFixedIntersectingViewport(false)
+    , m_behavesAsFixed(false)
     , m_3DTransformedDescendantStatusDirty(true)
     , m_has3DTransformedDescendant(false)
     , m_hasCompositingDescendant(false)
@@ -948,6 +949,7 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
     m_repaintStatus = NeedsNormalRepaint;
     m_hasTransformedAncestor = flags.contains(SeenTransformedLayer);
     m_has3DTransformedAncestor = flags.contains(Seen3DTransformedLayer);
+    m_behavesAsFixed = flags.contains(SeenFixedLayer);
     setHasCompositedScrollingAncestor(flags.contains(SeenCompositedScrollingLayer));
 
     // Update the reflection's position and size.
@@ -964,7 +966,13 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
         if (!transform()->isAffine())
             flags.add(Seen3DTransformedLayer);
     }
-    
+
+    // Fixed inside transform behaves like absolute (per spec).
+    if (renderer().isFixedPositioned() && !m_hasTransformedAncestor) {
+        m_behavesAsFixed = true;
+        flags.add(SeenFixedLayer);
+    }
+
     if (hasCompositedScrollableOverflow())
         flags.add(SeenCompositedScrollingLayer);
 
@@ -6930,7 +6938,7 @@ void showLayerTree(const WebCore::RenderObject* renderer)
 static void outputPaintOrderTreeLegend(TextStream& stream)
 {
     stream.nextLine();
-    stream << "(S)tacking Context/(F)orced SC/O(P)portunistic SC, (N)ormal flow only, (O)verflow clip, (A)lpha (opacity or mask), has (B)lend mode, (I)solates blending, (T)ransform-ish, (F)ilter, Fi(X)ed position, (C)omposited, (P)rovides backing/uses (p)rovided backing/paints to (a)ncestor, (c)omposited descendant, (s)scrolling ancestor\n"
+    stream << "(S)tacking Context/(F)orced SC/O(P)portunistic SC, (N)ormal flow only, (O)verflow clip, (A)lpha (opacity or mask), has (B)lend mode, (I)solates blending, (T)ransform-ish, (F)ilter, Fi(X)ed position, Behaves as fi(x)ed, (C)omposited, (P)rovides backing/uses (p)rovided backing/paints to (a)ncestor, (c)omposited descendant, (s)scrolling ancestor\n"
         "Dirty (z)-lists, Dirty (n)ormal flow lists\n"
         "Traversal needs: requirements (t)raversal on descendants, (b)acking or hierarchy traversal on descendants, (r)equirements traversal on all descendants, requirements traversal on all (s)ubsequent layers, (h)ierarchy traversal on all descendants, update of paint (o)rder children\n"
         "Update needs:    post-(l)ayout requirements, (g)eometry, (k)ids geometry, (c)onfig, layer conne(x)ion, (s)crolling tree\n";
@@ -6955,6 +6963,7 @@ static void outputPaintOrderTreeRecursive(TextStream& stream, const WebCore::Ren
     stream << (layer.renderer().hasTransformRelatedProperty() ? "T" : "-");
     stream << (layer.hasFilter() ? "F" : "-");
     stream << (layer.renderer().isFixedPositioned() ? "X" : "-");
+    stream << (layer.behavesAsFixed() ? "x" : "-");
     stream << (layer.isComposited() ? "C" : "-");
     
     auto compositedPaintingDestinationString = [&layer]() {
index 8cc8758..e31abb8 100644 (file)
@@ -534,9 +534,10 @@ public:
         NeedsFullRepaintInBacking           = 1 << 1,
         ContainingClippingLayerChangedSize  = 1 << 2,
         UpdatePagination                    = 1 << 3,
-        SeenTransformedLayer                = 1 << 4,
-        Seen3DTransformedLayer              = 1 << 5,
-        SeenCompositedScrollingLayer        = 1 << 6,
+        SeenFixedLayer                      = 1 << 4,
+        SeenTransformedLayer                = 1 << 5,
+        Seen3DTransformedLayer              = 1 << 6,
+        SeenCompositedScrollingLayer        = 1 << 7,
     };
     static constexpr OptionSet<UpdateLayerPositionsFlag> updateLayerPositionsDefaultFlags() { return { CheckForRepaint }; }
 
@@ -579,6 +580,8 @@ public:
 
     bool hasVisibleBoxDecorationsOrBackground() const;
     bool hasVisibleBoxDecorations() const;
+    
+    bool behavesAsFixed() const { return m_behavesAsFixed; }
 
     struct PaintedContentRequest {
         void makeStatesUndetermined()
@@ -1222,6 +1225,7 @@ private:
     bool m_hasVisibleDescendant : 1;
     bool m_registeredScrollableArea : 1;
     bool m_isFixedIntersectingViewport : 1;
+    bool m_behavesAsFixed : 1;
 
     bool m_3DTransformedDescendantStatusDirty : 1;
     bool m_has3DTransformedDescendant : 1;  // Set on a stacking context layer that has 3D descendants anywhere
index a78a74e..7d35cb5 100644 (file)
@@ -721,6 +721,37 @@ bool RenderLayerBacking::updateCompositedBounds()
     return setCompositedBounds(layerBounds);
 }
 
+void RenderLayerBacking::updateAllowsBackingStoreDetaching(const LayoutRect& absoluteBounds)
+{
+    auto setAllowsBackingStoreDetaching = [&](bool allowDetaching) {
+        m_graphicsLayer->setAllowsBackingStoreDetaching(allowDetaching);
+        if (m_foregroundLayer)
+            m_foregroundLayer->setAllowsBackingStoreDetaching(allowDetaching);
+        if (m_backgroundLayer)
+            m_backgroundLayer->setAllowsBackingStoreDetaching(allowDetaching);
+        if (m_scrolledContentsLayer)
+            m_scrolledContentsLayer->setAllowsBackingStoreDetaching(allowDetaching);
+    };
+
+    if (!m_owningLayer.behavesAsFixed()) {
+        setAllowsBackingStoreDetaching(true);
+        return;
+    }
+
+    // We'll allow detaching if the layer is outside the layout viewport. Fixed layers inside
+    // the layout viewport can be revealed by async scrolling, so we want to pin their backing store.
+    FrameView& frameView = renderer().view().frameView();
+    LayoutRect fixedLayoutRect;
+    if (frameView.useFixedLayout())
+        fixedLayoutRect = renderer().view().unscaledDocumentRect();
+    else
+        fixedLayoutRect = frameView.rectForFixedPositionLayout();
+
+    bool allowDetaching = !fixedLayoutRect.intersects(absoluteBounds);
+    LOG_WITH_STREAM(Compositing, stream << "RenderLayerBacking (layer " << &m_owningLayer << ") updateAllowsBackingStoreDetaching - absoluteBounds " << absoluteBounds << " layoutViewportRect " << fixedLayoutRect << ", allowDetaching " << allowDetaching);
+    setAllowsBackingStoreDetaching(allowDetaching);
+}
+
 void RenderLayerBacking::updateAfterWidgetResize()
 {
     if (!is<RenderWidget>(renderer()))
@@ -1690,7 +1721,7 @@ bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScroll
     if (needsHorizontalScrollbarLayer) {
         if (!m_layerForHorizontalScrollbar) {
             m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
-            m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
+            m_layerForHorizontalScrollbar->setAllowsBackingStoreDetaching(false);
             horizontalScrollbarLayerChanged = true;
         }
     } else if (m_layerForHorizontalScrollbar) {
@@ -1703,7 +1734,7 @@ bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScroll
     if (needsVerticalScrollbarLayer) {
         if (!m_layerForVerticalScrollbar) {
             m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
-            m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
+            m_layerForVerticalScrollbar->setAllowsBackingStoreDetaching(false);
             verticalScrollbarLayerChanged = true;
         }
     } else if (m_layerForVerticalScrollbar) {
@@ -1716,7 +1747,7 @@ bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScroll
     if (needsScrollCornerLayer) {
         if (!m_layerForScrollCorner) {
             m_layerForScrollCorner = createGraphicsLayer("scroll corner");
-            m_layerForScrollCorner->setCanDetachBackingStore(false);
+            m_layerForScrollCorner->setAllowsBackingStoreDetaching(false);
             scrollCornerLayerChanged = true;
         }
     } else if (m_layerForScrollCorner) {
@@ -1996,11 +2027,6 @@ ScrollingNodeID RenderLayerBacking::scrollingNodeIDForChildren() const
     return m_positioningNodeID;
 }
 
-void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
-{
-    m_graphicsLayer->setIsViewportConstrained(viewportCoordinated);
-}
-
 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
 {
     float finalOpacity = rendererOpacity;
index 3b5dee2..b354d0b 100644 (file)
@@ -153,7 +153,6 @@ public:
             break;
         case ScrollCoordinationRole::ViewportConstrained:
             m_viewportConstrainedNodeID = nodeID;
-            setIsScrollCoordinatedWithViewportConstrainedRole(nodeID);
             break;
         case ScrollCoordinationRole::Positioning:
             m_positioningNodeID = nodeID;
@@ -162,7 +161,6 @@ public:
     }
 
     ScrollingNodeID scrollingNodeIDForChildren() const;
-    void setIsScrollCoordinatedWithViewportConstrainedRole(bool);
 
     bool hasMaskLayer() const { return m_maskLayer; }
     bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer != nullptr; }
@@ -209,6 +207,8 @@ public:
     bool setCompositedBounds(const LayoutRect&);
     // Returns true if changed.
     bool updateCompositedBounds();
+    
+    void updateAllowsBackingStoreDetaching(const LayoutRect& absoluteBounds);
 
     void updateEventRegion();
     
index cad39e2..82f1fec 100644 (file)
@@ -982,7 +982,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
             layerWillComposite();
         }
     }
-    
+
     for (auto* childLayer : layer.normalFlowLayers())
         computeCompositingRequirements(&layer, *childLayer, overlapMap, currentState, backingSharingState, anyDescendantHas3DTransform);
 
@@ -1070,6 +1070,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
     bool layerContributesToOverlap = (currentState.compositingAncestor && !currentState.compositingAncestor->isRenderViewLayer()) || currentState.backingSharingAncestor;
     updateOverlapMap(overlapMap, layer, layerExtent, didPushOverlapContainer, layerContributesToOverlap, becameCompositedAfterDescendantTraversal && !descendantsAddedToOverlap);
 
+    if (layer.isComposited())
+        layer.backing()->updateAllowsBackingStoreDetaching(layerExtent.bounds);
+
     overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
 
     LOG_WITH_STREAM(Compositing, stream << TextStream::Repeat(compositingState.depth * 2, ' ') << &layer << " computeCompositingRequirements - willBeComposited " << willBeComposited << " (backing provider candidate " << backingSharingState.backingProviderCandidate() << ")");
@@ -2971,7 +2974,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
     ASSERT(container);
 
     // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
-    // They will stay fixed wrt the container rather than the enclosing frame.j
+    // They will stay fixed wrt the container rather than the enclosing frame.
     if (container != &m_renderView) {
         queryData.nonCompositedForPositionReason = RenderLayer::NotCompositedForNonViewContainer;
         return false;
@@ -3754,7 +3757,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
     if (requiresHorizontalScrollbarLayer()) {
         if (!m_layerForHorizontalScrollbar) {
             m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
-            m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
+            m_layerForHorizontalScrollbar->setAllowsBackingStoreDetaching(false);
             m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
             m_layerForHorizontalScrollbar->setName("horizontal scrollbar container");
 #if PLATFORM(COCOA) && USE(CA)
@@ -3775,7 +3778,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
     if (requiresVerticalScrollbarLayer()) {
         if (!m_layerForVerticalScrollbar) {
             m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
-            m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
+            m_layerForVerticalScrollbar->setAllowsBackingStoreDetaching(false);
             m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
             m_layerForVerticalScrollbar->setName("vertical scrollbar container");
 #if PLATFORM(COCOA) && USE(CA)
@@ -3796,7 +3799,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
     if (requiresScrollCornerLayer()) {
         if (!m_layerForScrollCorner) {
             m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), *this);
-            m_layerForScrollCorner->setCanDetachBackingStore(false);
+            m_layerForScrollCorner->setAllowsBackingStoreDetaching(false);
             m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
             m_layerForScrollCorner->setName("scroll corner");
 #if PLATFORM(COCOA) && USE(CA)
@@ -4312,19 +4315,15 @@ ScrollingNodeID RenderLayerCompositor::updateScrollCoordinationForLayer(RenderLa
 {
     auto roles = coordinatedScrollingRolesForLayer(layer);
 
-    bool isViewportConstrained = roles.contains(ScrollCoordinationRole::ViewportConstrained);
 #if PLATFORM(IOS_FAMILY)
     if (m_legacyScrollingLayerCoordinator) {
-        if (isViewportConstrained)
+        if (roles.contains(ScrollCoordinationRole::ViewportConstrained))
             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;