Make some RenderLayer tree traversal in RenderLayerBacking more generic
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 Mar 2017 19:14:12 +0000 (19:14 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 Mar 2017 19:14:12 +0000 (19:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169177

Reviewed by Zalan Bujtas.

The real goal of this patch is reduce the number of callers of
RenderLayerBacking::isPaintDestinationForDescendantLayers() to one. To achieve that,
have the setContentsVisible() logic (which is really just about the CSS 'visibility' property)
do its own tree traversal which just consults layer.hasVisibleContent(). So
make descendantLayerPaintsIntoAncestor() a generic traversal function which walks
descendant layers which may paint into the target layer. The "Visible" in the name
reflects the fact that it can bypass a subtree for a layer with !hasVisibleDescendant().

* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateAfterDescendants):
(WebCore::traverseVisibleNonCompositedDescendantLayers):
(WebCore::RenderLayerBacking::isPaintDestinationForDescendantLayers):
(WebCore::RenderLayerBacking::hasVisibleNonCompositedDescendants):
(WebCore::descendantLayerPaintsIntoAncestor): Deleted.
* rendering/RenderLayerBacking.h:

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h

index 47250e1..eaf9c89 100644 (file)
@@ -1,3 +1,26 @@
+2017-03-05  Simon Fraser  <simon.fraser@apple.com>
+
+        Make some RenderLayer tree traversal in RenderLayerBacking more generic
+        https://bugs.webkit.org/show_bug.cgi?id=169177
+
+        Reviewed by Zalan Bujtas.
+
+        The real goal of this patch is reduce the number of callers of
+        RenderLayerBacking::isPaintDestinationForDescendantLayers() to one. To achieve that,
+        have the setContentsVisible() logic (which is really just about the CSS 'visibility' property)
+        do its own tree traversal which just consults layer.hasVisibleContent(). So
+        make descendantLayerPaintsIntoAncestor() a generic traversal function which walks
+        descendant layers which may paint into the target layer. The "Visible" in the name
+        reflects the fact that it can bypass a subtree for a layer with !hasVisibleDescendant().
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateAfterDescendants):
+        (WebCore::traverseVisibleNonCompositedDescendantLayers):
+        (WebCore::RenderLayerBacking::isPaintDestinationForDescendantLayers):
+        (WebCore::RenderLayerBacking::hasVisibleNonCompositedDescendants):
+        (WebCore::descendantLayerPaintsIntoAncestor): Deleted.
+        * rendering/RenderLayerBacking.h:
+
 2017-03-04  Simon Fraser  <simon.fraser@apple.com>
 
         Clarify some terminology in RenderLayerBacking
index 345022f..c13bb26 100644 (file)
@@ -1104,7 +1104,7 @@ void RenderLayerBacking::updateAfterDescendants()
 
     updateDrawsContent(isSimpleContainer);
 
-    m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || isPaintDestinationForDescendantLayers());
+    m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositedDescendants());
     if (m_scrollingLayer) {
         m_scrollingLayer->setContentsVisible(renderer().style().visibility() == VISIBLE);
         m_scrollingLayer->setUserInteractionEnabled(renderer().style().pointerEvents() != PE_NONE);
@@ -1948,7 +1948,9 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
     return true;
 }
 
-static bool descendantLayerPaintsIntoAncestor(RenderLayer& parent)
+enum class LayerTraversal { Continue, Stop };
+
+static LayerTraversal traverseVisibleNonCompositedDescendantLayers(RenderLayer& parent, std::function<LayerTraversal (const RenderLayer&)> layerFunc)
 {
     // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
     parent.updateLayerListsIfNeeded();
@@ -1959,38 +1961,73 @@ static bool descendantLayerPaintsIntoAncestor(RenderLayer& parent)
 
     if (auto* normalFlowList = parent.normalFlowList()) {
         for (auto* childLayer : *normalFlowList) {
-            if (!compositedWithOwnBackingStore(*childLayer) && (childLayer->isVisuallyNonEmpty() || descendantLayerPaintsIntoAncestor(*childLayer)))
-                return true;
+            if (compositedWithOwnBackingStore(*childLayer))
+                continue;
+
+            if (layerFunc(*childLayer) == LayerTraversal::Stop)
+                return LayerTraversal::Stop;
+            
+            if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
+                return LayerTraversal::Stop;
         }
     }
 
     if (parent.isStackingContainer()) {
         if (!parent.hasVisibleDescendant())
-            return false;
+            return LayerTraversal::Continue;
 
         // Use the m_hasCompositingDescendant bit to optimize?
         if (auto* negZOrderList = parent.negZOrderList()) {
             for (auto* childLayer : *negZOrderList) {
-                if (!compositedWithOwnBackingStore(*childLayer) && (childLayer->isVisuallyNonEmpty() || descendantLayerPaintsIntoAncestor(*childLayer)))
-                    return true;
+                if (compositedWithOwnBackingStore(*childLayer))
+                    continue;
+
+                if (layerFunc(*childLayer) == LayerTraversal::Stop)
+                    return LayerTraversal::Stop;
+
+                if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
+                    return LayerTraversal::Stop;
             }
         }
 
         if (auto* posZOrderList = parent.posZOrderList()) {
             for (auto* childLayer : *posZOrderList) {
-                if (!compositedWithOwnBackingStore(*childLayer) && (childLayer->isVisuallyNonEmpty() || descendantLayerPaintsIntoAncestor(*childLayer)))
-                    return true;
+                if (compositedWithOwnBackingStore(*childLayer))
+                    continue;
+
+                if (layerFunc(*childLayer) == LayerTraversal::Stop)
+                    return LayerTraversal::Stop;
+
+                if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
+                    return LayerTraversal::Stop;
             }
         }
     }
 
-    return false;
+    return LayerTraversal::Continue;
 }
 
 // Conservative test for having no rendered children.
 bool RenderLayerBacking::isPaintDestinationForDescendantLayers() const
 {
-    return descendantLayerPaintsIntoAncestor(m_owningLayer);
+    bool hasPaintingDescendant = false;
+    traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasPaintingDescendant](const RenderLayer& layer) {
+        hasPaintingDescendant = layer.isVisuallyNonEmpty();
+        return hasPaintingDescendant ? LayerTraversal::Stop : LayerTraversal::Continue;
+    });
+
+    return hasPaintingDescendant;
+}
+
+bool RenderLayerBacking::hasVisibleNonCompositedDescendants() const
+{
+    bool hasVisibleDescendant = false;
+    traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasVisibleDescendant](const RenderLayer& layer) {
+        hasVisibleDescendant = layer.hasVisibleContent();
+        return hasVisibleDescendant ? LayerTraversal::Stop : LayerTraversal::Continue;
+    });
+
+    return hasVisibleDescendant;
 }
 
 bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const
index 7702e11..ff73ea7 100644 (file)
@@ -329,6 +329,7 @@ private:
     void resetContentsRect();
 
     bool isPaintDestinationForDescendantLayers() const;
+    bool hasVisibleNonCompositedDescendants() const;
 
     bool shouldClipCompositedBounds() const;