Clean up code related to compositing overlap map maintenance
https://bugs.webkit.org/show_bug.cgi?id=197936

Reviewed by Zalan Bujtas.

Clarify the logic around updating the overlap map:

When a layer becomes composited, or paints into a non-root composited layer, we add it to the overlap map
after traversing descendants (since it only affets layers later in traversal).

If a layer became composited after traversing descendants, we need to go back and add all the descendants
to the overlap map with a recursive traversal.

We can do all this near the end of computeCompositingRequirements/traverseUnchangedSubtree because
we only check overlap when we enter this function on later layers.

Add a CompositingOverlap log channel and use it to log the state of the overlap map.

* platform/Logging.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
(WebCore::RenderLayerCompositor::addToOverlapMap const):
(WebCore::RenderLayerCompositor::addDescendantsToOverlapMapRecursive const):
(WebCore::RenderLayerCompositor::updateOverlapMap const):
(WebCore::RenderLayerCompositor::addToOverlapMap): Deleted.
(WebCore::RenderLayerCompositor::addToOverlapMapRecursive): Deleted.
* rendering/RenderLayerCompositor.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245373 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index d7010f2d..fe85dea 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,34 @@
+2019-05-15  Simon Fraser  <simon.fraser@apple.com>
+
+        Clean up code related to compositing overlap map maintenance
+        https://bugs.webkit.org/show_bug.cgi?id=197936
+
+        Reviewed by Zalan Bujtas.
+
+        Clarify the logic around updating the overlap map:
+
+        When a layer becomes composited, or paints into a non-root composited layer, we add it to the overlap map
+        after traversing descendants (since it only affets layers later in traversal).
+
+        If a layer became composited after traversing descendants, we need to go back and add all the descendants
+        to the overlap map with a recursive traversal.
+
+        We can do all this near the end of computeCompositingRequirements/traverseUnchangedSubtree because
+        we only check overlap when we enter this function on later layers.
+
+        Add a CompositingOverlap log channel and use it to log the state of the overlap map.
+
+        * platform/Logging.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+        (WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
+        (WebCore::RenderLayerCompositor::addToOverlapMap const):
+        (WebCore::RenderLayerCompositor::addDescendantsToOverlapMapRecursive const):
+        (WebCore::RenderLayerCompositor::updateOverlapMap const):
+        (WebCore::RenderLayerCompositor::addToOverlapMap): Deleted.
+        (WebCore::RenderLayerCompositor::addToOverlapMapRecursive): Deleted.
+        * rendering/RenderLayerCompositor.h:
+
 2019-05-15  Timothy Hatcher  <timothy@apple.com>
 
         REGRESSION (r245072): Missing code in Document::styleColorOptions to propagate StyleColor::Options::UseInactiveAppearance
diff --git a/Source/WebCore/platform/Logging.h b/Source/WebCore/platform/Logging.h
index e120a29..27bfebb 100644
--- a/Source/WebCore/platform/Logging.h
+++ b/Source/WebCore/platform/Logging.h
@@ -44,6 +44,7 @@
     M(Archives) \
     M(ClipRects) \
     M(Compositing) \
+    M(CompositingOverlap) \
     M(ContentFiltering) \
     M(ContentObservation) \
     M(DatabaseTracker) \
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 7592eda..b5b6c65 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -854,6 +854,7 @@
     // We updated compositing for direct reasons in layerStyleChanged(). Here, check for compositing that can only be evaluated after layout.
     RequiresCompositingData queryData;
     bool willBeComposited = layer.isComposited();
+    bool becameCompositedAfterDescendantTraversal = false;
     if (layer.needsPostLayoutCompositingUpdate() || compositingState.fullPaintOrderTraversalRequired || compositingState.descendantsRequireCompositingUpdate) {
         layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::None);
         willBeComposited = needsToBeComposited(layer, queryData);
@@ -918,6 +919,7 @@
         // This layer now acts as the ancestor for kids.
         currentState.compositingAncestor = &layer;
         overlapMap.pushCompositingContainer();
+        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " will composite, pushed container " << overlapMap);
 
         willBeComposited = true;
         layerPaintsIntoProvidedBacking = false;
@@ -926,7 +928,7 @@
     auto layerWillCompositePostDescendants = [&] {
         layerWillComposite();
         currentState.subtreeIsCompositing = true;
-        addToOverlapMapRecursive(overlapMap, layer);
+        becameCompositedAfterDescendantTraversal = true;
     };
 
     if (willBeComposited) {
@@ -939,6 +941,7 @@
     } else if (layerPaintsIntoProvidedBacking) {
         currentState.backingSharingAncestor = &layer;
         overlapMap.pushCompositingContainer();
+        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " will share, pushed container " << overlapMap);
     }
 
     backingSharingState.updateBeforeDescendantTraversal(layer, willBeComposited);
@@ -972,14 +975,6 @@
         if (usesCompositing() && m_hasAcceleratedCompositing)
             willBeComposited = true;
     }
-    
-    // All layers (even ones that aren't being composited) need to get added to
-    // the overlap map. Layers that do not composite will draw into their
-    // compositing ancestor's backing, and so are still considered for overlap.
-    // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
-    // include descendants, so we don't need to add them all to the overlap map.
-    if (currentState.compositingAncestor && !currentState.compositingAncestor->isRenderViewLayer())
-        addToOverlapMap(overlapMap, layer, layerExtent);
 
 #if ENABLE(CSS_COMPOSITING)
     bool isolatedCompositedBlending = layer.isolatesCompositedBlending();
@@ -1052,9 +1047,14 @@
     descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform();
     compositingState.updateWithDescendantStateAndLayer(currentState, layer, layerExtent);
 
+    bool layerContributesToOverlap = currentState.compositingAncestor && !currentState.compositingAncestor->isRenderViewLayer();
+    updateOverlapMap(overlapMap, layer, layerExtent, layerContributesToOverlap, becameCompositedAfterDescendantTraversal);
+
     // Pop backing/overlap sharing state.
-    if ((willBeComposited && !layer.isRenderViewLayer()) || currentState.backingSharingAncestor == &layer)
+    if ((willBeComposited && !layer.isRenderViewLayer()) || currentState.backingSharingAncestor == &layer) {
         overlapMap.popCompositingContainer();
+        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " is composited, popped container " << overlapMap);
+    }
 
     backingSharingState.updateAfterDescendantTraversal(layer, compositingState.stackingContextAncestor);
     overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
@@ -1102,6 +1102,7 @@
         // This layer now acts as the ancestor for kids.
         currentState.compositingAncestor = &layer;
         overlapMap.pushCompositingContainer();
+        LOG_WITH_STREAM(CompositingOverlap, stream << "unchangedSubtree: layer " << &layer << " will composite, pushed container " << overlapMap);
 
         computeExtent(overlapMap, layer, layerExtent);
         currentState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
@@ -1129,14 +1130,6 @@
     for (auto* childLayer : layer.positiveZOrderLayers())
         traverseUnchangedSubtree(&layer, *childLayer, overlapMap, currentState, backingSharingState, anyDescendantHas3DTransform);
 
-    // All layers (even ones that aren't being composited) need to get added to
-    // the overlap map. Layers that do not composite will draw into their
-    // compositing ancestor's backing, and so are still considered for overlap.
-    // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
-    // include descendants, so we don't need to add them all to the overlap map.
-    if (currentState.compositingAncestor && !currentState.compositingAncestor->isRenderViewLayer())
-        addToOverlapMap(overlapMap, layer, layerExtent);
-
     // Set the flag to say that this layer has compositing children.
     ASSERT(layer.hasCompositingDescendant() == currentState.subtreeIsCompositing);
     ASSERT_IMPLIES(canBeComposited(layer) && clipsCompositingDescendants(layer), layerIsComposited);
@@ -1146,8 +1139,13 @@
     ASSERT(!currentState.fullPaintOrderTraversalRequired);
     compositingState.updateWithDescendantStateAndLayer(currentState, layer, layerExtent, true);
 
-    if ((layerIsComposited && !layer.isRenderViewLayer()) || currentState.backingSharingAncestor == &layer)
+    bool layerContributesToOverlap = currentState.compositingAncestor && !currentState.compositingAncestor->isRenderViewLayer();
+    updateOverlapMap(overlapMap, layer, layerExtent, layerContributesToOverlap);
+
+    if ((layerIsComposited && !layer.isRenderViewLayer()) || currentState.backingSharingAncestor == &layer) {
         overlapMap.popCompositingContainer();
+        LOG_WITH_STREAM(CompositingOverlap, stream << "unchangedSubtree: layer " << &layer << " is composited, popped container " << overlapMap);
+    }
 
     backingSharingState.updateAfterDescendantTraversal(layer, compositingState.stackingContextAncestor);
     overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
@@ -1778,7 +1776,7 @@
     extent.extentComputed = true;
 }
 
-void RenderLayerCompositor::addToOverlapMap(LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent)
+void RenderLayerCompositor::addToOverlapMap(LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) const
 {
     if (layer.isRenderViewLayer())
         return;
@@ -1794,35 +1792,57 @@
     overlapMap.add(clipRect);
 }
 
-void RenderLayerCompositor::addToOverlapMapRecursive(LayerOverlapMap& overlapMap, const RenderLayer& layer, const RenderLayer* ancestorLayer)
+void RenderLayerCompositor::addDescendantsToOverlapMapRecursive(LayerOverlapMap& overlapMap, const RenderLayer& layer, const RenderLayer* ancestorLayer) const
 {
     if (!canBeComposited(layer))
         return;
 
     // A null ancestorLayer is an indication that 'layer' has already been pushed.
-    if (ancestorLayer)
+    if (ancestorLayer) {
         overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer);
     
-    OverlapExtent layerExtent;
-    addToOverlapMap(overlapMap, layer, layerExtent);
+        OverlapExtent layerExtent;
+        addToOverlapMap(overlapMap, layer, layerExtent);
+    }
 
 #if !ASSERT_DISABLED
     LayerListMutationDetector mutationChecker(const_cast<RenderLayer&>(layer));
 #endif
 
     for (auto* renderLayer : layer.negativeZOrderLayers())
-        addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
+        addDescendantsToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
 
     for (auto* renderLayer : layer.normalFlowLayers())
-        addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
+        addDescendantsToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
 
     for (auto* renderLayer : layer.positiveZOrderLayers())
-        addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
+        addDescendantsToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
     
     if (ancestorLayer)
         overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
 }
 
+void RenderLayerCompositor::updateOverlapMap(LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& layerExtent, bool layerContributesToOverlap, bool addDescendantsToOverlap) const
+{
+    ASSERT_IMPLIES(addDescendantsToOverlap, layerContributesToOverlap);
+
+    // All layers (even ones that aren't being composited) need to get added to
+    // the overlap map. Layers that do not composite will draw into their
+    // compositing ancestor's backing, and so are still considered for overlap.
+    // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
+    // include descendants, so we don't need to add them all to the overlap map.
+    if (layerContributesToOverlap) {
+        addToOverlapMap(overlapMap, layer, layerExtent);
+        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " contributes to overlap, added to map " << overlapMap);
+    }
+
+    if (addDescendantsToOverlap) {
+        // If this is the first non-root layer to composite, we need to add all the descendants we already traversed to the overlap map.
+        addDescendantsToOverlapMapRecursive(overlapMap, layer);
+        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " composited post descendant traversal, added recursive " << overlapMap);
+    }
+}
+
 #if ENABLE(VIDEO)
 bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo& video) const
 {
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index db22436..f516b83 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -406,8 +406,9 @@
     void recursiveRepaintLayer(RenderLayer&);
 
     void computeExtent(const LayerOverlapMap&, const RenderLayer&, OverlapExtent&) const;
-    void addToOverlapMap(LayerOverlapMap&, const RenderLayer&, OverlapExtent&);
-    void addToOverlapMapRecursive(LayerOverlapMap&, const RenderLayer&, const RenderLayer* ancestorLayer = nullptr);
+    void addToOverlapMap(LayerOverlapMap&, const RenderLayer&, OverlapExtent&) const;
+    void addDescendantsToOverlapMapRecursive(LayerOverlapMap&, const RenderLayer&, const RenderLayer* ancestorLayer = nullptr) const;
+    void updateOverlapMap(LayerOverlapMap&, const RenderLayer&, OverlapExtent&, bool layerContributesToOverlap, bool addDescendantsToOverlap = false) const;
 
     void updateCompositingLayersTimerFired();