Refactor composited backing-sharing code
https://bugs.webkit.org/show_bug.cgi?id=197824
Reviewed by Zalan Bujtas.
Clean up the backing-sharing code to share more code, and make it easier to understand.
Moves more logic into member functions on BackingSharingState, which are named to make
their functions clearer: startBackingSharingSequence/endBackingSharingSequence.
computeCompositingRequirements() and traverseUnchangedSubtree() now just call
updateBeforeDescendantTraversal/updateAfterDescendantTraversal.
No behavior change.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::willBeDestroyed):
(WebCore::RenderLayerBacking::setBackingSharingLayers): Remove the early return, since
we need to call setBackingProviderLayer() on the sharing layers in both code paths.
(WebCore::RenderLayerBacking::removeBackingSharingLayer):
(WebCore::RenderLayerBacking::clearBackingSharingLayers):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::BackingSharingState::backingProviderCandidate const):
(WebCore::RenderLayerCompositor::BackingSharingState::appendSharingLayer):
(WebCore::RenderLayerCompositor::BackingSharingState::startBackingSharingSequence):
(WebCore::RenderLayerCompositor::BackingSharingState::endBackingSharingSequence):
(WebCore::RenderLayerCompositor::BackingSharingState::updateBeforeDescendantTraversal):
(WebCore::RenderLayerCompositor::BackingSharingState::updateAfterDescendantTraversal):
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
(WebCore::RenderLayerCompositor::BackingSharingState::resetBackingProviderCandidate): Deleted.
* rendering/RenderLayerCompositor.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245218 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 1e21209..e4b808b 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,38 @@
+2019-05-12 Simon Fraser <simon.fraser@apple.com>
+
+ Refactor composited backing-sharing code
+ https://bugs.webkit.org/show_bug.cgi?id=197824
+
+ Reviewed by Zalan Bujtas.
+
+ Clean up the backing-sharing code to share more code, and make it easier to understand.
+
+ Moves more logic into member functions on BackingSharingState, which are named to make
+ their functions clearer: startBackingSharingSequence/endBackingSharingSequence.
+
+ computeCompositingRequirements() and traverseUnchangedSubtree() now just call
+ updateBeforeDescendantTraversal/updateAfterDescendantTraversal.
+
+ No behavior change.
+
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore::RenderLayerBacking::willBeDestroyed):
+ (WebCore::RenderLayerBacking::setBackingSharingLayers): Remove the early return, since
+ we need to call setBackingProviderLayer() on the sharing layers in both code paths.
+ (WebCore::RenderLayerBacking::removeBackingSharingLayer):
+ (WebCore::RenderLayerBacking::clearBackingSharingLayers):
+ * rendering/RenderLayerCompositor.cpp:
+ (WebCore::RenderLayerCompositor::BackingSharingState::backingProviderCandidate const):
+ (WebCore::RenderLayerCompositor::BackingSharingState::appendSharingLayer):
+ (WebCore::RenderLayerCompositor::BackingSharingState::startBackingSharingSequence):
+ (WebCore::RenderLayerCompositor::BackingSharingState::endBackingSharingSequence):
+ (WebCore::RenderLayerCompositor::BackingSharingState::updateBeforeDescendantTraversal):
+ (WebCore::RenderLayerCompositor::BackingSharingState::updateAfterDescendantTraversal):
+ (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+ (WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
+ (WebCore::RenderLayerCompositor::BackingSharingState::resetBackingProviderCandidate): Deleted.
+ * rendering/RenderLayerCompositor.h:
+
2019-05-12 Youenn Fablet <youenn@apple.com>
Use clampTo in AVVideoCaptureSource::setSizeAndFrameRateWithPreset
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 43d1a57..f839e46 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -260,8 +260,6 @@
ASSERT(m_owningLayer.backing() == this);
compositor().removeFromScrollCoordinatedLayers(m_owningLayer);
- LOG(Compositing, "RenderLayer(backing) %p willBeDestroyed", &m_owningLayer);
-
clearBackingSharingLayers();
}
@@ -282,29 +280,21 @@
void RenderLayerBacking::setBackingSharingLayers(Vector<WeakPtr<RenderLayer>>&& sharingLayers)
{
- if (m_backingSharingLayers == sharingLayers) {
- sharingLayers.clear();
- return;
- }
-
clearBackingSharingLayerProviders(m_backingSharingLayers);
m_backingSharingLayers = WTFMove(sharingLayers);
+
for (auto& layerWeakPtr : m_backingSharingLayers)
layerWeakPtr->setBackingProviderLayer(&m_owningLayer);
}
void RenderLayerBacking::removeBackingSharingLayer(RenderLayer& layer)
{
- LOG(Compositing, "RenderLayer %p removeBackingSharingLayer %p", &m_owningLayer, &layer);
-
layer.setBackingProviderLayer(nullptr);
m_backingSharingLayers.removeAll(&layer);
}
void RenderLayerBacking::clearBackingSharingLayers()
{
- LOG(Compositing, "RenderLayer %p clearBackingSharingLayers", &m_owningLayer);
-
clearBackingSharingLayerProviders(m_backingSharingLayers);
m_backingSharingLayers.clear();
}
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 283273c..07e8cc7 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -284,22 +284,85 @@
#endif
};
-struct RenderLayerCompositor::BackingSharingState {
- RenderLayer* backingProviderCandidate { nullptr };
- RenderLayer* backingProviderStackingContext { nullptr };
- Vector<WeakPtr<RenderLayer>> backingSharingLayers;
+class RenderLayerCompositor::BackingSharingState {
+ WTF_MAKE_NONCOPYABLE(BackingSharingState);
+public:
+ BackingSharingState() = default;
- void resetBackingProviderCandidate(RenderLayer* candidateLayer = nullptr, RenderLayer* candidateStackingContext = nullptr)
+ RenderLayer* backingProviderCandidate() const { return m_backingProviderCandidate; };
+
+ void appendSharingLayer(RenderLayer& layer)
{
- if (!backingSharingLayers.isEmpty()) {
- ASSERT(backingProviderCandidate);
- backingProviderCandidate->backing()->setBackingSharingLayers(WTFMove(backingSharingLayers));
- }
- backingProviderCandidate = candidateLayer;
- backingProviderStackingContext = candidateLayer ? candidateStackingContext : nullptr;
+ LOG_WITH_STREAM(Compositing, stream << &layer << " appendSharingLayer " << &layer << " for backing provider " << m_backingProviderCandidate);
+ m_backingSharingLayers.append(makeWeakPtr(layer));
}
+
+ void updateBeforeDescendantTraversal(RenderLayer&, bool willBeComposited);
+ void updateAfterDescendantTraversal(RenderLayer&, RenderLayer* stackingContextAncestor);
+
+private:
+ void layerWillBeComposited(RenderLayer&);
+
+ void startBackingSharingSequence(RenderLayer& candidateLayer, RenderLayer* candidateStackingContext);
+ void endBackingSharingSequence();
+
+ RenderLayer* m_backingProviderCandidate { nullptr };
+ RenderLayer* m_backingProviderStackingContext { nullptr };
+ Vector<WeakPtr<RenderLayer>> m_backingSharingLayers;
};
+void RenderLayerCompositor::BackingSharingState::startBackingSharingSequence(RenderLayer& candidateLayer, RenderLayer* candidateStackingContext)
+{
+ ASSERT(!m_backingProviderCandidate);
+ ASSERT(m_backingSharingLayers.isEmpty());
+
+ m_backingProviderCandidate = &candidateLayer;
+ m_backingProviderStackingContext = candidateStackingContext;
+}
+
+void RenderLayerCompositor::BackingSharingState::endBackingSharingSequence()
+{
+ if (m_backingProviderCandidate) {
+ m_backingProviderCandidate->backing()->setBackingSharingLayers(WTFMove(m_backingSharingLayers));
+ m_backingSharingLayers.clear();
+ }
+
+ m_backingProviderCandidate = nullptr;
+}
+
+void RenderLayerCompositor::BackingSharingState::updateBeforeDescendantTraversal(RenderLayer& layer, bool willBeComposited)
+{
+ layer.setBackingProviderLayer(nullptr);
+
+ // A layer that composites resets backing-sharing, since subsequent layers need to composite to overlap it.
+ if (willBeComposited) {
+ m_backingSharingLayers.removeAll(&layer);
+ LOG_WITH_STREAM(Compositing, stream << "Pre-descendant compositing of " << &layer << ", ending sharing sequence for " << m_backingProviderCandidate << " with " << m_backingSharingLayers.size() << " sharing layers");
+ endBackingSharingSequence();
+ }
+}
+
+void RenderLayerCompositor::BackingSharingState::updateAfterDescendantTraversal(RenderLayer& layer, RenderLayer* stackingContextAncestor)
+{
+ if (layer.isComposited()) {
+ // If this layer is being composited, clean up sharing-related state.
+ layer.disconnectFromBackingProviderLayer();
+ m_backingSharingLayers.removeAll(&layer);
+ }
+
+ if (m_backingProviderCandidate && &layer == m_backingProviderStackingContext) {
+ LOG_WITH_STREAM(Compositing, stream << "End of stacking context for backing provider " << m_backingProviderCandidate << ", ending sharing sequence with " << m_backingSharingLayers.size() << " sharing layers");
+ endBackingSharingSequence();
+ } else if (!m_backingProviderCandidate && layer.isComposited()) {
+ LOG_WITH_STREAM(Compositing, stream << "Post-descendant compositing of " << &layer << ", ending sharing sequence for " << m_backingProviderCandidate << " with " << m_backingSharingLayers.size() << " sharing layers");
+ endBackingSharingSequence();
+ startBackingSharingSequence(layer, stackingContextAncestor);
+ }
+
+ if (&layer != m_backingProviderCandidate && layer.isComposited())
+ layer.backing()->clearBackingSharingLayers();
+}
+
struct RenderLayerCompositor::OverlapExtent {
LayoutRect bounds;
bool extentComputed { false };
@@ -880,7 +943,7 @@
}
#if ENABLE(TREE_DEBUGGING)
- LOG(Compositing, "%*p %s computeCompositingRequirements (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, layer.isNormalFlowOnly() ? "n" : "s", backingSharingState.backingProviderCandidate);
+ LOG(Compositing, "%*p %s computeCompositingRequirements (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, layer.isNormalFlowOnly() ? "n" : "s", backingSharingState.backingProviderCandidate());
#endif
// FIXME: maybe we can avoid updating all remaining layers in paint order.
@@ -891,7 +954,6 @@
layer.updateLayerListsIfNeeded();
layer.setHasCompositingDescendant(false);
- layer.setBackingProviderLayer(nullptr);
// We updated compositing for direct reasons in layerStyleChanged(). Here, check for compositing that can only be evaluated after layout.
RequiresCompositingData queryData;
@@ -921,9 +983,9 @@
// If we're testing for overlap, we only need to composite if we overlap something that is already composited.
if (overlapMap.overlapsLayers(layerExtent.bounds)) {
- if (backingSharingState.backingProviderCandidate && canBeComposited(layer) && backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate, layer)) {
- backingSharingState.backingSharingLayers.append(makeWeakPtr(layer));
- LOG(Compositing, " layer %p can share with %p", &layer, backingSharingState.backingProviderCandidate);
+ if (backingSharingState.backingProviderCandidate() && canBeComposited(layer) && backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate(), layer)) {
+ backingSharingState.appendSharingLayer(layer);
+ LOG(Compositing, " layer %p can share with %p", &layer, backingSharingState.backingProviderCandidate());
compositingReason = RenderLayer::IndirectCompositingReason::None;
layerPaintsIntoProvidedBacking = true;
} else
@@ -967,10 +1029,7 @@
// animation running behind this layer, meaning they can rely on the overlap map testing again.
childState.testingOverlap = true;
willBeComposited = true;
-
layerPaintsIntoProvidedBacking = false;
- layer.disconnectFromBackingProviderLayer();
- backingSharingState.backingSharingLayers.removeAll(&layer);
};
if (willBeComposited) {
@@ -983,15 +1042,13 @@
childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
// Too hard to compute animated bounds if both us and some ancestor is animating transform.
layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation;
-
- // Compositing for any reason disables backing sharing.
- LOG_WITH_STREAM(Compositing, stream << &layer << " is compositing - flushing sharing to " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- backingSharingState.resetBackingProviderCandidate();
} else if (layerPaintsIntoProvidedBacking) {
childState.backingSharingAncestor = &layer;
overlapMap.pushCompositingContainer();
}
+ backingSharingState.updateBeforeDescendantTraversal(layer, willBeComposited);
+
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(layer);
#endif
@@ -1100,18 +1157,10 @@
layer.setChildrenNeedCompositingGeometryUpdate();
// The composited bounds of enclosing layers depends on which descendants are composited, so they need a geometry update.
layer.setNeedsCompositingGeometryUpdateOnAncestors();
- } else if (layer.isComposited())
- layer.backing()->clearBackingSharingLayers();
-
- if (backingSharingState.backingProviderCandidate && &layer == backingSharingState.backingProviderStackingContext) {
- LOG_WITH_STREAM(Compositing, stream << &layer << " popping stacking context " << backingSharingState.backingProviderStackingContext << ", flushing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- backingSharingState.resetBackingProviderCandidate();
- } else if (!backingSharingState.backingProviderCandidate && layer.isComposited()) {
- LOG_WITH_STREAM(Compositing, stream << &layer << " compositing - sharing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- // Flush out any earlier candidate in this stacking context. This layer becomes a candidate.
- backingSharingState.resetBackingProviderCandidate(&layer, compositingState.stackingContextAncestor);
}
+ backingSharingState.updateAfterDescendantTraversal(layer, compositingState.stackingContextAncestor);
+
if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), queryData, CompositingChangeRepaintNow))
layer.setNeedsCompositingLayerConnection();
@@ -1124,7 +1173,7 @@
}
#if ENABLE(TREE_DEBUGGING)
- LOG(Compositing, "%*p computeCompositingRequirements - willBeComposited %d (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, willBeComposited, backingSharingState.backingProviderCandidate);
+ LOG(Compositing, "%*p computeCompositingRequirements - willBeComposited %d (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, willBeComposited, backingSharingState.backingProviderCandidate());
#endif
layer.clearCompositingRequirementsTraversalState();
@@ -1160,9 +1209,9 @@
computeExtent(overlapMap, layer, layerExtent);
if (layer.paintsIntoProvidedBacking()) {
- ASSERT(backingSharingState.backingProviderCandidate);
- ASSERT(backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate, layer));
- backingSharingState.backingSharingLayers.append(makeWeakPtr(layer));
+ ASSERT(backingSharingState.backingProviderCandidate());
+ ASSERT(backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate(), layer));
+ backingSharingState.appendSharingLayer(layer);
}
CompositingState childState = compositingState.stateForPaintOrderChildren(layer);
@@ -1182,12 +1231,10 @@
childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
// Too hard to compute animated bounds if both us and some ancestor is animating transform.
layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation;
-
- // Compositing for any reason disables backing sharing.
- LOG_WITH_STREAM(Compositing, stream << "tus: " << &layer << " is compositing - flushing sharing to " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- backingSharingState.resetBackingProviderCandidate();
}
+ backingSharingState.updateBeforeDescendantTraversal(layer, layerIsComposited);
+
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(layer);
#endif
@@ -1240,17 +1287,7 @@
if ((childState.compositingAncestor == &layer && !layer.isRenderViewLayer()) || childState.backingSharingAncestor == &layer)
overlapMap.popCompositingContainer();
- if (layer.isComposited())
- layer.backing()->clearBackingSharingLayers();
-
- if (backingSharingState.backingProviderCandidate && &layer == backingSharingState.backingProviderStackingContext) {
- LOG_WITH_STREAM(Compositing, stream << &layer << " tus: popping stacking context " << backingSharingState.backingProviderStackingContext << ", flushing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- backingSharingState.resetBackingProviderCandidate();
- } else if (!backingSharingState.backingProviderCandidate && layer.isComposited()) {
- LOG_WITH_STREAM(Compositing, stream << &layer << " tus: compositing - sharing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
- // Flush out any earlier candidate in this stacking context. This layer becomes a candidate.
- backingSharingState.resetBackingProviderCandidate(&layer, compositingState.stackingContextAncestor);
- }
+ backingSharingState.updateAfterDescendantTraversal(layer, compositingState.stackingContextAncestor);
descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform();
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index 54ca466..125b329 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -367,9 +367,9 @@
unsigned compositingUpdateCount() const { return m_compositingUpdateCount; }
private:
+ class BackingSharingState;
class OverlapMap;
struct CompositingState;
- struct BackingSharingState;
struct OverlapExtent;
// Returns true if the policy changed.