 Chromium Code Reviews
 Chromium Code Reviews Issue 88863002:
  Land layer squashing behind a flag  (Closed) 
  Base URL: svn://svn.chromium.org/blink/trunk
    
  
    Issue 88863002:
  Land layer squashing behind a flag  (Closed) 
  Base URL: svn://svn.chromium.org/blink/trunk| Index: Source/core/rendering/RenderLayerCompositor.cpp | 
| diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp | 
| index 4389ddff9aa45d76085b43d38e569318424aea1d..ff02a56289c831262b2bd22daf224eca45d1e32f 100644 | 
| --- a/Source/core/rendering/RenderLayerCompositor.cpp | 
| +++ b/Source/core/rendering/RenderLayerCompositor.cpp | 
| @@ -440,15 +440,27 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update | 
| // scrolling and animation bounds is implemented (crbug.com/252472). | 
| Vector<RenderLayer*> unclippedDescendants; | 
| computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants); | 
| + } | 
| - assignLayersToBackings(updateRoot, layersChanged); | 
| + { | 
| + TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::assignLayersToBackings"); | 
| + SquashingState squashingState; | 
| + // FIXME: this last vestigal if-statement is depressing, see if we can remove it cleanly somehow | 
| 
enne (OOO)
2013/11/27 23:20:26
You could put it in the squashing state destructor
 
shawnsingh
2013/12/02 01:55:03
Done - used a toplevel wrapper function.
 | 
| + assignLayersToBackings(updateRoot, squashingState, layersChanged); | 
| + if (squashingState.hasMostRecentMapping) | 
| + squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(); | 
| + } | 
| + | 
| + { | 
| + TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateHasVisibleNonLayerContent"); | 
| const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView->frameView()->scrollableAreas(); | 
| if (scrollableAreas) { | 
| for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it) | 
| (*it)->updateHasVisibleNonLayerContent(); | 
| } | 
| } | 
| + | 
| needHierarchyAndGeometryUpdate |= layersChanged; | 
| } | 
| @@ -477,6 +489,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update | 
| else | 
| m_rootContentLayer->setChildren(childList); | 
| } else if (needGeometryUpdate) { | 
| + | 
| // We just need to do a geometry update. This is only used for position:fixed scrolling; | 
| // most of the time, geometry is updated via RenderLayer::styleChanged(). | 
| updateLayerTreeGeometry(updateRoot); | 
| @@ -503,11 +516,23 @@ void RenderLayerCompositor::layerBecameNonComposited(const RenderLayer* renderLa | 
| --m_compositedLayerCount; | 
| } | 
| -static bool requiresCompositing(CompositingReasons reasons) | 
| +static bool requiresCompositingOrSquashing(CompositingReasons reasons) | 
| { | 
| return reasons != CompositingReasonNone; | 
| } | 
| +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); | 
| +} | 
| + | 
| void RenderLayerCompositor::addOutOfFlowPositionedLayer(RenderLayer* layer) | 
| { | 
| m_outOfFlowPositionedLayers.add(layer); | 
| @@ -543,6 +568,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? | 
| + // where are we doing that, again? | 
| + // and what happens when the groupedMapping may have changed under our feet based on previou CLMs being allocated/de-allocated? | 
| + 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()) | 
| @@ -609,6 +642,9 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer) | 
| updateDirectCompositingReasons(layer); | 
| bool layerChanged = allocateOrClearCompositedLayerMapping(layer); | 
| + // 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()) | 
| @@ -635,15 +671,19 @@ 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) | 
| + compositedAncestor->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(repaintRect); | 
| + else | 
| + ASSERT_NOT_REACHED(); | 
| } | 
| } | 
| @@ -665,11 +705,14 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye | 
| void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/) | 
| { | 
| + // FIXME: possibly need to do something here for squashed layers... | 
| setCompositingLayersNeedRebuild(); | 
| } | 
| void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child) | 
| { | 
| + // FIXME: almost certainly need to do something here for squashed layers... | 
| + | 
| if (!child->hasCompositedLayerMapping() || parent->renderer()->documentBeingDestroyed()) | 
| return; | 
| @@ -806,7 +849,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())); | 
| @@ -825,7 +868,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; | 
| @@ -914,10 +957,15 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor | 
| if (overlapMap && childRecursionData.m_compositingAncestor && !childRecursionData.m_compositingAncestor->isRootLayer()) | 
| addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); | 
| + // At this point, we definitely have computed the absolute bounds for the layers if it needs to be squashed or composited. | 
| + // FIXME: can we do something cleaner? | 
| + if (haveComputedBounds) | 
| + layer->setAbsoluteBounds(absBounds); | 
| + | 
| // 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 | 
| @@ -956,7 +1004,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 { | 
| @@ -978,7 +1026,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor | 
| overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer); | 
| } | 
| -void RenderLayerCompositor::assignLayersToBackings(RenderLayer* layer, bool& layersChanged) | 
| +void RenderLayerCompositor::assignLayersToBackings(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged) | 
| { | 
| if (allocateOrClearCompositedLayerMapping(layer)) | 
| layersChanged = true; | 
| @@ -986,21 +1034,58 @@ void RenderLayerCompositor::assignLayersToBackings(RenderLayer* layer, bool& lay | 
| 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); | 
| + | 
| + IntRect absBounds = layer->absoluteBounds(); | 
| + | 
| + // FIXME: see if we can refactor this to be clearer | 
| + IntSize offsetFromTargetBacking(absBounds.x() + squashingState.absToLocalOffset.width(), | 
| + absBounds.y() + squashingState.absToLocalOffset.height()); | 
| + | 
| + squashingState.mostRecentMapping->addRenderLayerToSquashingGraphicsLayer(layer, offsetFromTargetBacking); | 
| + | 
| + // FIXME: does this need to be true here? Do we need more logic to decide when it should be true? | 
| + layersChanged = true; | 
| + } | 
| + } | 
| if (layer->stackingNode()->isStackingContainer()) { | 
| RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren); | 
| while (RenderLayerStackingNode* curNode = iterator.next()) | 
| - assignLayersToBackings(curNode->layer(), layersChanged); | 
| + assignLayersToBackings(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) { | 
| 
enne (OOO)
2013/11/27 23:20:26
If a layer paints into an ancestor, is the offset
 
shawnsingh
2013/12/02 01:55:03
Sorry, I'm not understanding what the question is.
 | 
| + ASSERT(!requiresSquashing(layer->compositingReasons())); | 
| + | 
| + IntRect absBounds = layer->absoluteBounds(); | 
| + | 
| + // The most recent backing is done accumulating any more squashing layers. | 
| + if (squashingState.hasMostRecentMapping) | 
| 
enne (OOO)
2013/11/27 23:20:26
I think these next few lines could be cleaner if S
 
shawnsingh
2013/12/02 01:55:03
done
 | 
| + squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(); | 
| + | 
| + layer->compositedLayerMapping()->beginAccumulatingSquashingLayers(); | 
| + | 
| + squashingState.mostRecentMapping = layer->compositedLayerMapping(); | 
| + squashingState.hasMostRecentMapping = true; | 
| + squashingState.absToLocalOffset = IntSize(-absBounds.x(), -absBounds.y()); | 
| + } | 
| + } | 
| RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren); | 
| while (RenderLayerStackingNode* curNode = iterator.next()) | 
| - assignLayersToBackings(curNode->layer(), layersChanged); | 
| + assignLayersToBackings(curNode->layer(), squashingState, layersChanged); | 
| } | 
| void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) | 
| @@ -1027,6 +1112,9 @@ void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, Render | 
| void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer) | 
| { | 
| ASSERT(layer->hasCompositedLayerMapping()); | 
| + // FIXME: this is probably not necessary, a leftover from the hacked prototype. | 
| + if (!layer->hasCompositedLayerMapping()) | 
| + return; | 
| GraphicsLayer* hostingLayer = layer->compositedLayerMapping()->parentForSublayers(); | 
| hostingLayer->removeAllChildren(); | 
| @@ -1499,7 +1587,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 needsOwnBackingDueToOverlap = !isLayerSquashingEnabled() && requiresSquashing(layer->compositingReasons()); | 
| + | 
| + return requiresCompositing(layer->compositingReasons()) || needsOwnBackingDueToOverlap || (inCompositingMode() && layer->isRootLayer()); | 
| } | 
| bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const | 
| @@ -1564,6 +1655,7 @@ bool RenderLayerCompositor::clippedByAncestor(const RenderLayer* layer) const | 
| if (!layer->hasCompositedLayerMapping() || !layer->parent()) | 
| return false; | 
| + // FIXME: need to see if new semantics of ancestorCompositingLayer() work correctly here? | 
| const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); | 
| if (!compositingAncestor) | 
| return false; |