| Index: Source/core/rendering/RenderLayerCompositor.cpp
|
| diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp
|
| index ca69154269837eb9da2c96fe8b1737e383ef9467..7e69cf5deac8b64d7d9594e6133848eb29a42eb1 100644
|
| --- a/Source/core/rendering/RenderLayerCompositor.cpp
|
| +++ b/Source/core/rendering/RenderLayerCompositor.cpp
|
| @@ -439,9 +439,10 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
|
| if (needHierarchyUpdate) {
|
| // Update the hierarchy of the compositing layers.
|
| Vector<GraphicsLayer*> childList;
|
| + HashSet<RenderLayer*> visited;
|
| {
|
| TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::rebuildCompositingLayerTree");
|
| - rebuildCompositingLayerTree(updateRoot, childList, 0);
|
| + rebuildCompositingLayerTree(updateRoot, childList, visited, 0);
|
| }
|
|
|
| // Host the document layer in the RenderView's root layer.
|
| @@ -456,7 +457,8 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
|
| } 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, 0);
|
| + HashSet<RenderLayer*> visited;
|
| + updateLayerTreeGeometry(updateRoot, visited, 0);
|
| }
|
|
|
| #if !LOG_DISABLED
|
| @@ -1045,7 +1047,46 @@ bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
|
| return o->supportsAcceleratedRendering();
|
| }
|
|
|
| -void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth)
|
| +// The purpose of this function is to ensure that we call rebuildCompostingLayerTree on curLayer's
|
| +// scroll parent (if it has one) before we call it on curLayer. This is necessary because rebuilding the
|
| +// compositing layer tree for curLayer will use values we computed for the scroll parent. More specifically,
|
| +// rebuildCompositingLayreTree will call RenderLayerBacking::updateGraphicsLayerGeometry, and it's this
|
| +// function that will pull values from a scroll parent's graphics layers. Unfortunately,
|
| +// the childList needs to be populated as if we'd visited all the layers in paint order. To work around
|
| +// this, when we visit a scroll parent out of order, we'll set its additions to childList aside (in
|
| +// scrollParentChildLists), and add them to the real childList when we visit the scroll parent in paint
|
| +// order.
|
| +void RenderLayerCompositor::rebuildCompositingLayerTreeForLayerAndScrollParents(RenderLayer* curLayer, Vector<GraphicsLayer*>& childList, HashSet<RenderLayer*>& visited, HashMap<RenderLayer*, Vector<GraphicsLayer*> >& scrollParentChildLists, int depth)
|
| +{
|
| + ASSERT(curLayer->zIndex() >= 0 || !visited.contains(curLayer));
|
| + if (visited.contains(curLayer)) {
|
| + // We've already processed this layer, but since we processed it out of order, its
|
| + // contribution to childList was not added. We must do that now.
|
| + HashMap<RenderLayer*, Vector<GraphicsLayer*> >::iterator it = scrollParentChildLists.find(curLayer);
|
| + ASSERT(it != scrollParentChildLists.end());
|
| + childList.append(it->value);
|
| + scrollParentChildLists.remove(it);
|
| + return;
|
| + }
|
| +
|
| + if (requiresCompositingForOverflowScrollingParent(curLayer)) {
|
| + RenderLayer* scrollParent = curLayer->ancestorScrollingLayer();
|
| + if (!visited.contains(scrollParent)) {
|
| + ASSERT(!scrollParentChildLists.contains(scrollParent));
|
| + // We will populate scrollParentChildList rather than childList, since we're visiting it
|
| + // out of order.
|
| + Vector<GraphicsLayer*> scrollParentChildList;
|
| + rebuildCompositingLayerTreeForLayerAndScrollParents(scrollParent, scrollParentChildList, visited, scrollParentChildLists, depth);
|
| + // We will set aside the scrollParentChildList in scrollParentChildLists so that we can
|
| + // add it to childList when we visit the scrollParent normally.
|
| + scrollParentChildLists.add(scrollParent, scrollParentChildList);
|
| + }
|
| + }
|
| +
|
| + rebuildCompositingLayerTree(curLayer, childList, visited, depth);
|
| +}
|
| +
|
| +void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, HashSet<RenderLayer*>& visited, int depth)
|
| {
|
| // Make the layer compositing if necessary, and set up clipping and content layers.
|
| // Note that we can only do work here that is independent of whether the descendant layers
|
| @@ -1061,6 +1102,8 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
|
| pixelsAddedByPromotingAllTransitions = 0.0;
|
| }
|
|
|
| + visited.add(layer);
|
| +
|
| RenderLayerBacking* layerBacking = layer->backing();
|
| if (layerBacking) {
|
| // The compositing state of all our children has been updated already, so now
|
| @@ -1103,12 +1146,13 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
|
| LayerListMutationDetector mutationChecker(layer);
|
| #endif
|
|
|
| + HashMap<RenderLayer*, Vector<GraphicsLayer*> > scrollParentChildLists;
|
| if (layer->isStackingContainer()) {
|
| if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
|
| size_t listSize = negZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i) {
|
| RenderLayer* curLayer = negZOrderList->at(i);
|
| - rebuildCompositingLayerTree(curLayer, childList, depth + 1);
|
| + rebuildCompositingLayerTreeForLayerAndScrollParents(curLayer, childList, visited, scrollParentChildLists, depth + 1);
|
| }
|
| }
|
|
|
| @@ -1121,7 +1165,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
|
| size_t listSize = normalFlowList->size();
|
| for (size_t i = 0; i < listSize; ++i) {
|
| RenderLayer* curLayer = normalFlowList->at(i);
|
| - rebuildCompositingLayerTree(curLayer, childList, depth + 1);
|
| + rebuildCompositingLayerTreeForLayerAndScrollParents(curLayer, childList, visited, scrollParentChildLists, depth + 1);
|
| }
|
| }
|
|
|
| @@ -1130,7 +1174,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
|
| size_t listSize = posZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i) {
|
| RenderLayer* curLayer = posZOrderList->at(i);
|
| - rebuildCompositingLayerTree(curLayer, childList, depth + 1);
|
| + rebuildCompositingLayerTreeForLayerAndScrollParents(curLayer, childList, visited, scrollParentChildLists, depth + 1);
|
| }
|
| }
|
| }
|
| @@ -1332,9 +1376,29 @@ bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
|
| return true;
|
| }
|
|
|
| +// The purpose of this function is to ensure that we call updateLayerTreeGeometry on layer's
|
| +// scroll parent (if it has one) before we call it on layer. This is necessary because updating
|
| +// layer tree geometry for layer will use values we computed for its scroll parent.
|
| +void RenderLayerCompositor::updateLayerTreeGeometryForLayerAndScrollParents(RenderLayer* layer, HashSet<RenderLayer*>& visited, int depth)
|
| +{
|
| + ASSERT(layer->zIndex() >= 0 || !visited.contains(layer));
|
| + if (visited.contains(layer))
|
| + return;
|
| +
|
| + if (requiresCompositingForOverflowScrollingParent(layer)) {
|
| + RenderLayer* scrollParent = layer->ancestorScrollingLayer();
|
| + if (!visited.contains(scrollParent))
|
| + updateLayerTreeGeometryForLayerAndScrollParents(scrollParent, visited, depth);
|
| + }
|
| +
|
| + updateLayerTreeGeometry(layer, visited, depth);
|
| +}
|
| +
|
| // This just updates layer geometry without changing the hierarchy.
|
| -void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer, int depth)
|
| +void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer, HashSet<RenderLayer*>& visited, int depth)
|
| {
|
| + visited.add(layer);
|
| +
|
| if (RenderLayerBacking* layerBacking = layer->backing()) {
|
| // The compositing state of all our children has been updated already, so now
|
| // we can compute and cache the composited bounds for this layer.
|
| @@ -1362,32 +1426,52 @@ void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer, int dept
|
| LayerListMutationDetector mutationChecker(layer);
|
| #endif
|
|
|
| + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
|
| + size_t listSize = normalFlowList->size();
|
| + for (size_t i = 0; i < listSize; ++i)
|
| + updateLayerTreeGeometry(normalFlowList->at(i), visited, depth + 1);
|
| + }
|
| +
|
| if (layer->isStackingContainer()) {
|
| if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
|
| size_t listSize = negZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i)
|
| - updateLayerTreeGeometry(negZOrderList->at(i), depth + 1);
|
| + updateLayerTreeGeometryForLayerAndScrollParents(negZOrderList->at(i), visited, depth + 1);
|
| }
|
| }
|
|
|
| - if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
|
| - size_t listSize = normalFlowList->size();
|
| - for (size_t i = 0; i < listSize; ++i)
|
| - updateLayerTreeGeometry(normalFlowList->at(i), depth + 1);
|
| - }
|
| -
|
| if (layer->isStackingContainer()) {
|
| if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
|
| size_t listSize = posZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i)
|
| - updateLayerTreeGeometry(posZOrderList->at(i), depth + 1);
|
| + updateLayerTreeGeometryForLayerAndScrollParents(posZOrderList->at(i), visited, depth + 1);
|
| }
|
| }
|
| }
|
|
|
| +// The purpose of this function is to ensure that we call updateCompositingDescendantGeometry on layer's
|
| +// scroll parent (if it has one) before we call it on layer. This is necessary because updating
|
| +// layer tree geometry for layer will use values we computed for its scroll parent.
|
| +void RenderLayerCompositor::updateCompositingDescendantGeometryForLayerAndScrollParents(RenderLayer* compositingAncestor, RenderLayer* layer, HashSet<RenderLayer*>& visited, bool compositedChildrenOnly)
|
| +{
|
| + ASSERT(layer->zIndex() >= 0 || !visited.contains(layer));
|
| + if (visited.contains(layer))
|
| + return;
|
| +
|
| + if (requiresCompositingForOverflowScrollingParent(layer)) {
|
| + RenderLayer* scrollParent = layer->ancestorScrollingLayer();
|
| + if (!visited.contains(scrollParent))
|
| + updateCompositingDescendantGeometryForLayerAndScrollParents(compositingAncestor, scrollParent, visited, compositedChildrenOnly);
|
| + }
|
| +
|
| + updateCompositingDescendantGeometry(compositingAncestor, layer, visited, compositedChildrenOnly);
|
| +}
|
| +
|
| // Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
|
| -void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, bool compositedChildrenOnly)
|
| +void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, HashSet<RenderLayer*>& visited, bool compositedChildrenOnly)
|
| {
|
| + visited.add(layer);
|
| +
|
| if (layer != compositingAncestor) {
|
| if (RenderLayerBacking* layerBacking = layer->backing()) {
|
| layerBacking->updateCompositedBounds();
|
| @@ -1404,7 +1488,7 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* com
|
| }
|
|
|
| if (layer->reflectionLayer())
|
| - updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionLayer(), compositedChildrenOnly);
|
| + updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionLayer(), visited, compositedChildrenOnly);
|
|
|
| if (!layer->hasCompositingDescendant())
|
| return;
|
| @@ -1417,21 +1501,21 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* com
|
| if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
|
| size_t listSize = negZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i)
|
| - updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), compositedChildrenOnly);
|
| + updateCompositingDescendantGeometryForLayerAndScrollParents(compositingAncestor, negZOrderList->at(i), visited, compositedChildrenOnly);
|
| }
|
| }
|
|
|
| if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
|
| size_t listSize = normalFlowList->size();
|
| for (size_t i = 0; i < listSize; ++i)
|
| - updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), compositedChildrenOnly);
|
| + updateCompositingDescendantGeometryForLayerAndScrollParents(compositingAncestor, normalFlowList->at(i), visited, compositedChildrenOnly);
|
| }
|
|
|
| if (layer->isStackingContainer()) {
|
| if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
|
| size_t listSize = posZOrderList->size();
|
| for (size_t i = 0; i < listSize; ++i)
|
| - updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), compositedChildrenOnly);
|
| + updateCompositingDescendantGeometryForLayerAndScrollParents(compositingAncestor, posZOrderList->at(i), visited, compositedChildrenOnly);
|
| }
|
| }
|
| }
|
| @@ -1771,22 +1855,26 @@ const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer* l
|
| // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
|
| // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
|
| // but a sibling in the z-order hierarchy.
|
| -bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
|
| +bool RenderLayerCompositor::clippedByAncestor(const RenderLayer* layer) const
|
| {
|
| if (!layer->isComposited() || !layer->parent())
|
| return false;
|
|
|
| - RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
|
| + // Scroll children use their scrolling ancestor as their clip root.
|
| + RenderLayer* compositingAncestor = requiresCompositingForOverflowScrollingParent(layer)
|
| + ? layer->ancestorScrollingLayer()
|
| + : layer->ancestorCompositingLayer();
|
| +
|
| if (!compositingAncestor)
|
| return false;
|
|
|
| // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
|
| // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
|
| // and layer.
|
| - RenderLayer* computeClipRoot = 0;
|
| - RenderLayer* curr = layer;
|
| + const RenderLayer* computeClipRoot = 0;
|
| + const RenderLayer* curr = layer;
|
| while (curr) {
|
| - RenderLayer* next = curr->parent();
|
| + const RenderLayer* next = curr->parent();
|
| if (next == compositingAncestor) {
|
| computeClipRoot = curr;
|
| break;
|
| @@ -1998,34 +2086,7 @@ bool RenderLayerCompositor::requiresCompositingForBlending(RenderObject* rendere
|
|
|
| bool RenderLayerCompositor::requiresCompositingForOverflowScrollingParent(const RenderLayer* layer) const
|
| {
|
| - if (!layer->compositorDrivenAcceleratedScrollingEnabled())
|
| - return false;
|
| -
|
| - // A layer scrolls with its containing block. So to find the overflow scrolling layer
|
| - // that we scroll with respect to, we must ascend the layer tree until we reach the
|
| - // first overflow scrolling div at or above our containing block. I will refer to this
|
| - // layer as our 'scrolling ancestor'.
|
| - //
|
| - // Now, if we reside in a normal flow list, then we will naturally scroll with our scrolling
|
| - // ancestor, and we need not be composited. If, on the other hand, we reside in a z-order
|
| - // list, and on our walk upwards to our scrolling ancestor we find no layer that is a stacking
|
| - // context, then we know that in the stacking tree, we will not be in the subtree rooted at
|
| - // our scrolling ancestor, and we will therefore not scroll with it. In this case, we must
|
| - // be a composited layer since the compositor will need to take special measures to ensure
|
| - // that we scroll with our scrolling ancestor and it cannot do this if we do not promote.
|
| - RenderLayer* scrollParent = layer->ancestorScrollingLayer();
|
| -
|
| - if (!scrollParent || scrollParent->isStackingContext())
|
| - return false;
|
| -
|
| - // If we hit a stacking context on our way up to the ancestor scrolling layer, it will already
|
| - // be composited due to an overflow scrolling parent, so we don't need to.
|
| - for (RenderLayer* ancestor = layer->parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) {
|
| - if (ancestor->isStackingContext())
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| + return !!layer->scrollParent();
|
| }
|
|
|
| bool RenderLayerCompositor::requiresCompositingForOutOfFlowClipping(const RenderLayer* layer) const
|
|
|