Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1465)

Unified Diff: Source/core/rendering/RenderLayerCompositor.cpp

Issue 23903012: Set up scroll and clip parents (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Make WebLayer additions pure virtual. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/rendering/RenderLayerCompositor.h ('k') | Source/core/testing/Internals.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « Source/core/rendering/RenderLayerCompositor.h ('k') | Source/core/testing/Internals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698