Chromium Code Reviews| Index: Source/core/rendering/RenderLayerCompositor.cpp |
| diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp |
| index cf6fe341df00e8f0e94ab9013b88b23f4e7b24d2..850f532ac11764e14d5b939dbfe1b520a7071169 100644 |
| --- a/Source/core/rendering/RenderLayerCompositor.cpp |
| +++ b/Source/core/rendering/RenderLayerCompositor.cpp |
| @@ -443,15 +443,22 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update |
| // scrolling and animation bounds is implemented (crbug.com/252472). |
| Vector<RenderLayer*> unclippedDescendants; |
| computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants); |
| + } |
| + { |
| + TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::assignLayersToBackings"); |
| assignLayersToBackings(updateRoot, layersChanged); |
| + } |
| + { |
| + 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; |
| } |
| @@ -480,6 +487,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update |
| else |
| m_rootContentLayer->setChildren(childList); |
| } else if (needGeometryUpdate) { |
| + |
|
Ian Vollick
2013/12/07 02:44:42
Unnecessary ws change?
shawnsingh
2013/12/11 18:50:34
removed
|
| // 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); |
| @@ -506,11 +514,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); |
| @@ -546,6 +566,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()) |
| @@ -612,6 +640,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()) |
| @@ -638,15 +669,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(); |
| } |
| } |
| @@ -809,7 +844,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())); |
| @@ -828,7 +863,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; |
| @@ -927,7 +962,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 |
| @@ -969,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 { |
| @@ -991,7 +1026,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; |
| +} |
| + |
| +void RenderLayerCompositor::assignLayersToBackings(RenderLayer* updateRoot, bool& layersChanged) |
| +{ |
| + SquashingState squashingState; |
| + assignLayersToBackingsInternal(updateRoot, squashingState, layersChanged); |
| + if (squashingState.hasMostRecentMapping) |
| + squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex); |
| +} |
| + |
| +static IntPoint computeOffsetFromAbsolute(RenderLayer* layer) |
| +{ |
| + TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
| + layer->renderer()->mapLocalToContainer(0, transformState, ApplyContainerFlip); |
| + transformState.flatten(); |
| + return roundedIntPoint(transformState.lastPlanarPoint()); |
| +} |
| + |
| +void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged) |
| { |
| if (allocateOrClearCompositedLayerMapping(layer)) |
| layersChanged = true; |
| @@ -999,21 +1062,49 @@ 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); |
| + |
| + 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; |
| + } |
| + } |
| 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) |
| @@ -1040,6 +1131,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(); |
| @@ -1512,7 +1606,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()); |
|
Ian Vollick
2013/12/07 02:44:42
Does this not imply that the only reason we'd ever
shawnsingh
2013/12/11 18:50:34
No, it may not always be true... re-named variable
|
| + |
| + return requiresCompositing(layer->compositingReasons()) || needsOwnBackingDueToOverlap || (inCompositingMode() && layer->isRootLayer()); |
| } |
| bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const |
| @@ -1577,6 +1674,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; |