Index: Source/core/rendering/RenderLayerCompositor.cpp |
diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp |
index de23521a09894249e82fdad99630a7785f9b65fc..a9d1a2d1b393022c1ff38ddabc5468a47265ea60 100644 |
--- a/Source/core/rendering/RenderLayerCompositor.cpp |
+++ b/Source/core/rendering/RenderLayerCompositor.cpp |
@@ -500,6 +500,23 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update |
static bool requiresCompositing(CompositingReasons reasons) |
{ |
+ // Any reasons other than overlap or assumed overlap will require the layer to be separately compositing. |
+ return reasons & ~CompositingReasonComboAllOverlapReasons; |
+} |
+ |
+static bool requiresSquashing(CompositingReasons reasons) |
+{ |
+ // If the layer has overlap or assumed overlap, but no other reasons, then it should be squashed. |
+ return !requiresCompositing(reasons) && (reasons & CompositingReasonComboAllOverlapReasons); |
+} |
+ |
+static bool requiresCompositingOrSquashing(CompositingReasons reasons) |
+{ |
+#ifndef NDEBUG |
+ bool fastAnswer = reasons != CompositingReasonNone; |
+ bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons); |
+ ASSERT(fastAnswer == slowAnswer); |
+#endif |
return reasons != CompositingReasonNone; |
} |
@@ -538,6 +555,14 @@ bool RenderLayerCompositor::allocateOrClearCompositedLayerMapping(RenderLayer* l |
scrollingCoordinator->frameViewRootLayerDidChange(m_renderView->frameView()); |
} |
+ // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so |
+ // that computing repaint rects will know the layer's correct compositingState. |
+ // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping? |
+ // Need to create a test where a squashed layer pops into compositing. And also to cover all other |
+ // sorts of compositingState transitions. |
+ layer->setGroupedMapping(0); |
+ |
+ // FIXME: it seems premature to compute this before all compositing state has been updated? |
// This layer and all of its descendants have cached repaints rects that are relative to |
// the repaint container, so change when compositing changes; we need to update them here. |
if (layer->parent()) |
@@ -604,6 +629,11 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer) |
updateDirectCompositingReasons(layer); |
bool layerChanged = allocateOrClearCompositedLayerMapping(layer); |
+ if (isLayerSquashingEnabled()) { |
+ // FIXME: this is not correct... info may be out of date and squashing returning true doesn't indicate that the layer changed |
+ layerChanged = requiresSquashing(layer->compositingReasons()); |
+ } |
+ |
// See if we need content or clipping layers. Methods called here should assume |
// that the compositing state of descendant layers has not been updated yet. |
if (layer->hasCompositedLayerMapping() && layer->compositedLayerMapping()->updateGraphicsLayerConfiguration()) |
@@ -630,15 +660,21 @@ void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, cons |
{ |
RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(false /*exclude self*/); |
if (compositedAncestor) { |
- ASSERT(compositedAncestor->compositingState() == PaintsIntoOwnBacking); |
- |
+ // FIXME: make sure repaintRect is computed correctly for squashed scenario |
LayoutPoint offset; |
layer->convertToLayerCoords(compositedAncestor, offset); |
LayoutRect repaintRect = rect; |
repaintRect.moveBy(offset); |
- compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect); |
+ if (compositedAncestor->compositingState() == PaintsIntoOwnBacking) { |
+ compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect); |
+ } else if (compositedAncestor->compositingState() == PaintsIntoGroupedBacking) { |
+ // FIXME: Need to perform the correct coordinate conversion for repaintRect here, including transforms |
+ compositedAncestor->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(repaintRect); |
+ } else { |
+ ASSERT_NOT_REACHED(); |
+ } |
} |
} |
@@ -801,7 +837,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor |
bool haveComputedBounds = false; |
IntRect absBounds; |
// If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map. |
- if (overlapMap && !overlapMap->isEmpty() && currentRecursionData.m_testingOverlap && !requiresCompositing(directReasons)) { |
+ if (overlapMap && !overlapMap->isEmpty() && currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing(directReasons)) { |
// If we're testing for overlap, we only need to composite if we overlap something that is already composited. |
absBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(layer->overlapBounds())); |
@@ -820,7 +856,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor |
CompositingRecursionData childRecursionData(currentRecursionData); |
childRecursionData.m_subtreeIsCompositing = false; |
- bool willBeComposited = canBeComposited(layer) && requiresCompositing(reasonsToComposite); |
+ bool willBeComposited = canBeComposited(layer) && requiresCompositingOrSquashing(reasonsToComposite); |
if (willBeComposited) { |
// Tell the parent it has compositing descendants. |
currentRecursionData.m_subtreeIsCompositing = true; |
@@ -919,7 +955,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor |
// Now check for reasons to become composited that depend on the state of descendant layers. |
CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3DTransform); |
reasonsToComposite |= subtreeCompositingReasons; |
- if (!willBeComposited && canBeComposited(layer) && requiresCompositing(subtreeCompositingReasons)) { |
+ if (!willBeComposited && canBeComposited(layer) && requiresCompositingOrSquashing(subtreeCompositingReasons)) { |
childRecursionData.m_compositingAncestor = layer; |
if (overlapMap) { |
// FIXME: this context push is effectively a no-op but needs to exist for |
@@ -961,7 +997,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor |
if (layer->isRootLayer()) { |
// The root layer needs to be composited if anything else in the tree is composited. |
// Otherwise, we can disable compositing entirely. |
- if (childRecursionData.m_subtreeIsCompositing || requiresCompositing(reasonsToComposite) || m_forceCompositingMode) { |
+ if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSquashing(reasonsToComposite) || m_forceCompositingMode) { |
willBeComposited = true; |
reasonsToComposite |= CompositingReasonRoot; |
} else { |
@@ -983,13 +1019,35 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor |
overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer); |
} |
-void RenderLayerCompositor::assignLayersToBackings(RenderLayer* layer, bool& layersChanged) |
+void RenderLayerCompositor::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMappingPtr newCompositedLayerMapping, bool hasNewCompositedLayerMapping, IntPoint newOffsetFromAbsolute) |
+{ |
+ // The most recent backing is done accumulating any more squashing layers. |
+ if (hasMostRecentMapping) |
+ mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex); |
+ |
+ nextSquashedLayerIndex = 0; |
+ mostRecentMapping = newCompositedLayerMapping; |
+ hasMostRecentMapping = hasNewCompositedLayerMapping; |
+ offsetFromAbsolute = newOffsetFromAbsolute; |
+} |
+ |
+static IntPoint computeOffsetFromAbsolute(RenderLayer* layer) |
+{ |
+ TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
+ layer->renderer()->mapLocalToContainer(0, transformState, ApplyContainerFlip); |
+ transformState.flatten(); |
+ return roundedIntPoint(transformState.lastPlanarPoint()); |
+} |
+ |
+void RenderLayerCompositor::assignLayersToBackings(RenderLayer* updateRoot, bool& layersChanged) |
{ |
- // FIXME: squashing state will be added internally here. |
- assignLayersToBackingsInternal(layer, layersChanged); |
+ SquashingState squashingState; |
+ assignLayersToBackingsInternal(updateRoot, squashingState, layersChanged); |
+ if (squashingState.hasMostRecentMapping) |
+ squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex); |
} |
-void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, bool& layersChanged) |
+void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged) |
{ |
if (allocateOrClearCompositedLayerMapping(layer)) |
layersChanged = true; |
@@ -997,21 +1055,52 @@ void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, b |
if (layer->reflectionInfo() && updateLayerCompositingState(layer->reflectionInfo()->reflectionLayer())) |
layersChanged = true; |
- // FIXME: squashing code here: if a layer requiresSquashing(), then assign this layer to the most recent |
- // squashing layer and update recursion state of this function. |
+ // Add this layer to a squashing backing if needed. |
+ if (isLayerSquashingEnabled()) { |
+ // NOTE: In the future as we generalize this, the background of this layer may need to be assigned to a different backing than |
+ // the layer's own primary contents. This would happen when we have a composited negative z-index element that needs to |
+ // paint on top of the background, but below the layer's main contents. For now, because we always composite layers |
+ // when they have a composited negative z-index child, such layers will never need squashing so it is not yet an issue. |
+ if (requiresSquashing(layer->compositingReasons())) { |
+ // A layer that is squashed with other layers cannot have its own CompositedLayerMapping. |
+ ASSERT(!layer->hasCompositedLayerMapping()); |
+ ASSERT(squashingState.hasMostRecentMapping); |
+ |
+ IntPoint offsetFromAbsolute = computeOffsetFromAbsolute(layer); |
+ |
+ // FIXME: see if we can refactor this to be clearer |
+ IntSize offsetFromTargetBacking(offsetFromAbsolute.x() - squashingState.offsetFromAbsolute.x(), |
+ offsetFromAbsolute.y() - squashingState.offsetFromAbsolute.y()); |
+ |
+ squashingState.mostRecentMapping->addRenderLayerToSquashingGraphicsLayer(layer, offsetFromTargetBacking, squashingState.nextSquashedLayerIndex); |
+ squashingState.nextSquashedLayerIndex++; |
+ |
+ // FIXME: does this need to be true here? Do we need more logic to decide when it should be true? |
+ layersChanged = true; |
+ |
+ // FIXME: this should be conditioned on whether this layer actually changed status |
+ layer->clipper().clearClipRectsIncludingDescendants(); |
+ } |
+ } |
if (layer->stackingNode()->isStackingContainer()) { |
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren); |
while (RenderLayerStackingNode* curNode = iterator.next()) |
- assignLayersToBackings(curNode->layer(), layersChanged); |
+ assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged); |
} |
- // FIXME: squashing code here: if this layer actually becomes separately composited, then we need to update the |
- // squashing layer that subsequent overlapping layers will contribute to. |
+ if (isLayerSquashingEnabled()) { |
+ // At this point, if the layer is to be "separately" composited, then its backing becomes the most recent in paint-order. |
+ if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) { |
+ ASSERT(!requiresSquashing(layer->compositingReasons())); |
+ IntPoint offsetFromAbsolute = computeOffsetFromAbsolute(layer); |
+ squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping(), offsetFromAbsolute); |
+ } |
+ } |
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren); |
while (RenderLayerStackingNode* curNode = iterator.next()) |
- assignLayersToBackings(curNode->layer(), layersChanged); |
+ assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged); |
} |
void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) |
@@ -1510,7 +1599,10 @@ bool RenderLayerCompositor::needsOwnBacking(const RenderLayer* layer) const |
if (!canBeComposited(layer)) |
return false; |
- return requiresCompositing(layer->compositingReasons()) || (inCompositingMode() && layer->isRootLayer()); |
+ // If squashing is disabled, then layers that would have been squashed should just be separately composited. |
+ bool needsOwnBackingForDisabledSquashing = !isLayerSquashingEnabled() && requiresSquashing(layer->compositingReasons()); |
+ |
+ return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (inCompositingMode() && layer->isRootLayer()); |
} |
bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const |
@@ -1575,6 +1667,7 @@ bool RenderLayerCompositor::clippedByAncestor(const RenderLayer* layer) const |
if (!layer->hasCompositedLayerMapping() || !layer->parent()) |
return false; |
+ // FIXME: need to double-check if semantics of ancestorCompositingLayer() work correctly here? |
const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); |
if (!compositingAncestor) |
return false; |