Index: Source/core/rendering/RenderLayerCompositor.cpp |
diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp |
index e7b5a0f21a3d37333f34d10368c69e0914d43ea4..8f6d8c420b42507052c5b0e7cf8aecb2e08b22bf 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,31 @@ bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const |
return o->supportsAcceleratedRendering(); |
} |
-void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth) |
+void RenderLayerCompositor::rebuildCompositingLayerTreeForLayerAndScrollParents(RenderLayer* curLayer, Vector<GraphicsLayer*>& childList, HashSet<RenderLayer*>& visited, HashMap<RenderLayer*, Vector<GraphicsLayer*> >& scrollParentChildLists, int depth) |
hartmanng
2013/09/06 01:46:38
I think this function could use an explanation in
Ian Vollick
2013/09/06 02:38:11
Done.
hartmanng
2013/09/06 20:35:20
Much better, I think this makes the purpose of the
Ian Vollick
2013/09/06 23:00:59
Done.
|
+{ |
+ ASSERT(curLayer->zIndex() >= 0 || !visited.contains(curLayer)); |
+ if (visited.contains(curLayer)) { |
+ 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)); |
+ Vector<GraphicsLayer*> scrollParentChildList; |
+ rebuildCompositingLayerTreeForLayerAndScrollParents(scrollParent, scrollParentChildList, visited, scrollParentChildLists, depth); |
+ 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 +1087,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 +1131,30 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect |
LayerListMutationDetector mutationChecker(layer); |
#endif |
+ // Visit the normal flow descendants first. We do this for the sake of scroll |
+ // parents. A scroll parent is not a stacking context, so it will either appear |
+ // in the normal flow tree, or in the positive z-order list (if it had a positioned |
+ // ancestor). Visiting the scroll parent ahead of time if it appears in one |
+ // of these lists is a simple matter since we have the lists in hand at this |
+ // level of the recursion, but it's tricker for layers in the normal flow tree, |
+ // so it will be easier to just process this ahead of time. |
+ Vector<GraphicsLayer*> normalFlowChildList; |
+ |
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { |
+ size_t listSize = normalFlowList->size(); |
+ for (size_t i = 0; i < listSize; ++i) { |
+ RenderLayer* curLayer = normalFlowList->at(i); |
+ rebuildCompositingLayerTree(curLayer, normalFlowChildList, visited, depth + 1); |
+ } |
+ } |
+ |
+ 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); |
} |
} |
@@ -1117,20 +1163,14 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect |
childList.append(layerBacking->foregroundLayer()); |
} |
- if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { |
- size_t listSize = normalFlowList->size(); |
- for (size_t i = 0; i < listSize; ++i) { |
- RenderLayer* curLayer = normalFlowList->at(i); |
- rebuildCompositingLayerTree(curLayer, childList, depth + 1); |
- } |
- } |
+ childList.append(normalFlowChildList); |
if (layer->isStackingContainer()) { |
if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { |
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); |
} |
} |
} |
@@ -1311,9 +1351,25 @@ bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer) |
return true; |
} |
+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. |
@@ -1341,25 +1397,25 @@ 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); |
} |
} |
} |
@@ -1755,7 +1811,11 @@ bool RenderLayerCompositor::clippedByAncestor(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; |
@@ -1977,34 +2037,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 |