Avoid doing positioned scrolling tree node work for layers not inside overflow:scroll
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Apr 2019 05:28:50 +0000 (05:28 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Apr 2019 05:28:50 +0000 (05:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196848

Reviewed by Zalan Bujtas.

Maintain a bit on RenderLayer which says if a layer has a composited scrolling ancestor
in the layer tree. We only need to do work related to making positioned scrolling tree nodes
for layers which are layer tree descendants of overflow:scroll.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::updateLayerPositions):
(WebCore::outputPaintOrderTreeLegend):
(WebCore::outputPaintOrderTreeRecursive):
* rendering/RenderLayer.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingForPosition const):
(WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason const):
(WebCore::RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer const):
(WebCore::RenderLayerCompositor::fixedLayerIntersectsViewport const):
(WebCore::RenderLayerCompositor::computeCoordinatedPositioningForLayer const):

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerCompositor.cpp

index 9f96418..e2da3dd 100644 (file)
@@ -1,3 +1,27 @@
+2019-04-11  Simon Fraser  <simon.fraser@apple.com>
+
+        Avoid doing positioned scrolling tree node work for layers not inside overflow:scroll
+        https://bugs.webkit.org/show_bug.cgi?id=196848
+
+        Reviewed by Zalan Bujtas.
+
+        Maintain a bit on RenderLayer which says if a layer has a composited scrolling ancestor
+        in the layer tree. We only need to do work related to making positioned scrolling tree nodes
+        for layers which are layer tree descendants of overflow:scroll.
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::updateLayerPositions):
+        (WebCore::outputPaintOrderTreeLegend):
+        (WebCore::outputPaintOrderTreeRecursive):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingForPosition const):
+        (WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason const):
+        (WebCore::RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer const):
+        (WebCore::RenderLayerCompositor::fixedLayerIntersectsViewport const):
+        (WebCore::RenderLayerCompositor::computeCoordinatedPositioningForLayer const):
+
 2019-04-11  Zalan Bujtas  <zalan@apple.com>
 
         Try to fix Windows build.
index 6966283..31645ae 100644 (file)
@@ -291,6 +291,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_3DTransformedDescendantStatusDirty(true)
     , m_has3DTransformedDescendant(false)
     , m_hasCompositingDescendant(false)
+    , m_hasCompositedScrollingAncestor(false)
     , m_hasTransformedAncestor(false)
     , m_has3DTransformedAncestor(false)
     , m_indirectCompositingReason(static_cast<unsigned>(IndirectCompositingReason::None))
@@ -911,6 +912,7 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
     m_repaintStatus = NeedsNormalRepaint;
     m_hasTransformedAncestor = flags.contains(SeenTransformedLayer);
     m_has3DTransformedAncestor = flags.contains(Seen3DTransformedLayer);
+    setHasCompositedScrollingAncestor(flags.contains(SeenCompositedScrollingLayer));
 
     // Update the reflection's position and size.
     if (m_reflection)
@@ -926,6 +928,9 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
         if (!transform()->isAffine())
             flags.add(Seen3DTransformedLayer);
     }
+    
+    if (hasCompositedScrollableOverflow())
+        flags.add(SeenCompositedScrollingLayer);
 
     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
         child->updateLayerPositions(geometryMap, flags);
@@ -939,7 +944,7 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
         m_updatingMarqueePosition = oldUpdatingMarqueePosition;
     }
 
-    if (renderer().isOutOfFlowPositioned() && renderer().style().position() == PositionType::Fixed && renderer().settings().acceleratedCompositingForFixedPositionEnabled()) {
+    if (renderer().isFixedPositioned() && renderer().settings().acceleratedCompositingForFixedPositionEnabled()) {
         bool intersectsViewport = compositor().fixedLayerIntersectsViewport(*this);
         if (intersectsViewport != m_isFixedIntersectingViewport) {
             m_isFixedIntersectingViewport = intersectsViewport;
@@ -6750,7 +6755,7 @@ void showLayerTree(const WebCore::RenderObject* renderer)
 static void outputPaintOrderTreeLegend(TextStream& stream)
 {
     stream.nextLine();
-    stream << "(S)tacking Context, (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, (c)omposited descendant\n"
+    stream << "(S)tacking Context, (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, (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";
@@ -6777,6 +6782,7 @@ static void outputPaintOrderTreeRecursive(TextStream& stream, const WebCore::Ren
     stream << (layer.renderer().isFixedPositioned() ? "X" : "-");
     stream << (layer.isComposited() ? "C" : "-");
     stream << (layer.hasCompositingDescendant() ? "c" : "-");
+    stream << (layer.hasCompositedScrollingAncestor() ? "s" : "-");
 
     stream << " ";
 
index f0e3e5e..90748fb 100644 (file)
@@ -516,6 +516,7 @@ public:
         UpdatePagination                    = 1 << 3,
         SeenTransformedLayer                = 1 << 4,
         Seen3DTransformedLayer              = 1 << 5,
+        SeenCompositedScrollingLayer        = 1 << 6,
     };
     static constexpr OptionSet<UpdateLayerPositionsFlag> updateLayerPositionsDefaultFlags() { return { CheckForRepaint }; }
 
@@ -814,6 +815,9 @@ public:
     bool usesCompositedScrolling() const override;
     bool usesAsyncScrolling() const override;
 
+    bool hasCompositedScrollingAncestor() const { return m_hasCompositedScrollingAncestor; }
+    void setHasCompositedScrollingAncestor(bool hasCompositedScrollingAncestor) { m_hasCompositedScrollingAncestor = hasCompositedScrollingAncestor; }
+
     bool paintsWithTransparency(OptionSet<PaintBehavior> paintBehavior) const
     {
         return (isTransparent() || hasBlendMode() || (isolatesBlending() && !renderer().isDocumentElementRenderer())) && ((paintBehavior & PaintBehavior::FlattenCompositingLayers) || !isComposited());
@@ -1201,6 +1205,8 @@ private:
                                             // in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
     bool m_hasCompositingDescendant : 1; // In the z-order tree.
 
+    bool m_hasCompositedScrollingAncestor : 1; // In the layer-order tree.
+
     bool m_hasTransformedAncestor : 1;
     bool m_has3DTransformedAncestor : 1;
 
index 1c2bb90..491c17b 100644 (file)
@@ -2715,7 +2715,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
 #endif
 
     auto position = renderer.style().position();
-    bool isFixed = renderer.isOutOfFlowPositioned() && position == PositionType::Fixed;
+    bool isFixed = renderer.isFixedPositioned();
     if (isFixed && !layer.isStackingContext())
         return false;
     
@@ -2800,7 +2800,7 @@ bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerMode
         }
     }
 
-    if (renderer.isAbsolutelyPositioned() && compositingAncestor) {
+    if (renderer.isAbsolutelyPositioned() && compositingAncestor && layer.hasCompositedScrollingAncestor()) {
         if (layerContainingBlockCrossesCoordinatedScrollingBoundary(layer, *compositingAncestor)) {
             reason = RenderLayer::IndirectCompositingReason::OverflowScrollPositioning;
             return true;
@@ -2862,7 +2862,7 @@ bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const Render
     if (layer.renderer().isStickilyPositioned())
         return isAsyncScrollableStickyLayer(layer);
 
-    if (layer.renderer().style().position() != PositionType::Fixed)
+    if (!layer.renderer().isFixedPositioned())
         return false;
 
     // FIXME: Handle fixed inside of a transform, which should not behave as fixed.
@@ -2876,7 +2876,7 @@ bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const Render
 
 bool RenderLayerCompositor::fixedLayerIntersectsViewport(const RenderLayer& layer) const
 {
-    ASSERT(layer.renderer().style().position() == PositionType::Fixed);
+    ASSERT(layer.renderer().isFixedPositioned());
 
     // Fixed position elements that are invisible in the current view don't get their own layer.
     // FIXME: We shouldn't have to check useFixedLayout() here; one of the viewport rects needs to give the correct answer.
@@ -2947,6 +2947,9 @@ ScrollPositioningBehavior RenderLayerCompositor::computeCoordinatedPositioningFo
 
     if (layer.renderer().isFixedPositioned())
         return ScrollPositioningBehavior::None;
+    
+    if (!layer.hasCompositedScrollingAncestor())
+        return ScrollPositioningBehavior::None;
 
     auto* scrollingCoordinator = this->scrollingCoordinator();
     if (!scrollingCoordinator)