Fix RenderLayer::collectLayers logic bug.
In collectLayers, if a layer is normal flow only, we will not add it
to the z-order lists. The trouble is that
RenderLayer::shouldBeNormalFlowOnly depends on
RenderLayer::needsCompositedScrolling. This means that the result of
collectLayers depends on the opt-in decision of other layers,
something which must not happen: when we are determining opt-in, we
must never depend on the opt-in decision for another layer. This CL
makes this function opt-in agnostic when it needs to be.
R=jchaffraix
BUG=238282
Review URL: https://chromiumcodereview.appspot.com/14999005
git-svn-id: svn://svn.chromium.org/blink/trunk@151665 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations
index 7539f35..08eb35c 100644
--- a/LayoutTests/TestExpectations
+++ b/LayoutTests/TestExpectations
@@ -1287,15 +1287,6 @@
webkit.org/b/110247 [ Debug ] fast/workers/storage/interrupt-database.html [ Crash Pass Slow ]
-# Logic in RenderLayer::collectLayers needs to be fixed.
-crbug.com/238282 compositing/overflow/out-of-flow-pos-descendants-should-affect-all-ancestors.html [ Failure ]
-crbug.com/238282 compositing/overflow/textarea-scroll-touch.html [ Pass Failure ]
-crbug.com/238282 virtual/gpu/compositedscrolling/overflow/out-of-flow-pos-descendants-should-affect-all-ancestors.html [ Failure ]
-crbug.com/238282 virtual/gpu/compositedscrolling/overflow/textarea-scroll-touch.html [ Pass Failure ]
-crbug.com/238282 virtual/gpu/compositedscrolling/scrollbars/overflow-scrollbar-combinations.html [ Failure ]
-crbug.com/238282 virtual/softwarecompositing/overflow/out-of-flow-pos-descendants-should-affect-all-ancestors.html [ Failure ]
-crbug.com/238282 virtual/softwarecompositing/overflow/textarea-scroll-touch.html [ Failure ]
-
# This test is quite large, and can time out on win debug builds.
crbug.com/245836 [ Win Debug ] compositing/overflow/automatically-opt-into-composited-scrolling.html [ Pass Timeout ]
crbug.com/245836 [ Win Debug ] virtual/gpu/compositedscrolling/overflow/automatically-opt-into-composited-scrolling.html [ Pass Timeout ]
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
index 4416269..47daac7 100644
--- a/Source/core/rendering/RenderLayer.cpp
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -577,17 +577,7 @@
void RenderLayer::collectBeforePromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListBeforePromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListBeforePromote)
{
- // FIXME: TemporaryChange should support bit fields.
- bool oldNeedsCompositedScrolling = m_needsCompositedScrolling;
- bool oldIsNormalFlowOnly = m_isNormalFlowOnly;
-
- m_needsCompositedScrolling = false;
- m_isNormalFlowOnly = shouldBeNormalFlowOnly();
-
- ancestorStackingContext->rebuildZOrderLists(StopAtStackingContexts, posZOrderListBeforePromote, negZOrderListBeforePromote, 0);
-
- m_needsCompositedScrolling = oldNeedsCompositedScrolling;
- m_isNormalFlowOnly = oldIsNormalFlowOnly;
+ ancestorStackingContext->rebuildZOrderLists(posZOrderListBeforePromote, negZOrderListBeforePromote, this, OnlyStackingContextsCanBeStackingContainers);
const RenderLayer* positionedAncestor = parent();
while (positionedAncestor && !isPositionedContainer(positionedAncestor) && !positionedAncestor->isStackingContext())
@@ -618,17 +608,7 @@
void RenderLayer::collectAfterPromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListAfterPromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListAfterPromote)
{
- // FIXME: TemporaryChange should support bit fields.
- bool oldNeedsCompositedScrolling = m_needsCompositedScrolling;
- bool oldIsNormalFlowOnly = m_isNormalFlowOnly;
-
- m_isNormalFlowOnly = false;
- m_needsCompositedScrolling = true;
-
- ancestorStackingContext->rebuildZOrderLists(StopAtStackingContexts, posZOrderListAfterPromote, negZOrderListAfterPromote, this);
-
- m_needsCompositedScrolling = oldNeedsCompositedScrolling;
- m_isNormalFlowOnly = oldIsNormalFlowOnly;
+ ancestorStackingContext->rebuildZOrderLists(posZOrderListAfterPromote, negZOrderListAfterPromote, this, ForceLayerToStackingContainer);
}
// Compute what positive and negative z-order lists would look like before and
@@ -5591,16 +5571,16 @@
{
ASSERT(m_layerListMutationAllowed);
ASSERT(isDirtyStackingContainer());
- rebuildZOrderLists(StopAtStackingContainers, m_posZOrderList, m_negZOrderList);
+ rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
m_zOrderListsDirty = false;
}
-void RenderLayer::rebuildZOrderLists(CollectLayersBehavior behavior, OwnPtr<Vector<RenderLayer*> >& posZOrderList, OwnPtr<Vector<RenderLayer*> >& negZOrderList, const RenderLayer* layerToForceAsStackingContainer)
+void RenderLayer::rebuildZOrderLists(OwnPtr<Vector<RenderLayer*> >& posZOrderList, OwnPtr<Vector<RenderLayer*> >& negZOrderList, const RenderLayer* layerToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior)
{
bool includeHiddenLayers = compositor()->inCompositingMode();
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
if (!m_reflection || reflectionLayer() != child)
- child->collectLayers(includeHiddenLayers, behavior, posZOrderList, negZOrderList, layerToForceAsStackingContainer);
+ child->collectLayers(includeHiddenLayers, posZOrderList, negZOrderList, layerToForceAsStackingContainer, collectLayersBehavior);
// Sort the two lists.
if (posZOrderList)
@@ -5642,7 +5622,7 @@
m_normalFlowListDirty = false;
}
-void RenderLayer::collectLayers(bool includeHiddenLayers, CollectLayersBehavior behavior, OwnPtr<Vector<RenderLayer*> >& posBuffer, OwnPtr<Vector<RenderLayer*> >& negBuffer, const RenderLayer* layerToForceAsStackingContainer)
+void RenderLayer::collectLayers(bool includeHiddenLayers, OwnPtr<Vector<RenderLayer*> >& posBuffer, OwnPtr<Vector<RenderLayer*> >& negBuffer, const RenderLayer* layerToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior)
{
if (isInTopLayer())
return;
@@ -5650,20 +5630,33 @@
updateDescendantDependentFlags();
bool isStacking = false;
+ bool isNormalFlow = false;
- switch (behavior) {
- case StopAtStackingContexts:
- isStacking = (this == layerToForceAsStackingContainer) || isStackingContext();
- break;
-
- case StopAtStackingContainers:
- isStacking = (this == layerToForceAsStackingContainer) || isStackingContainer();
- break;
+ switch (collectLayersBehavior) {
+ case ForceLayerToStackingContainer:
+ ASSERT(layerToForceAsStackingContainer);
+ if (this == layerToForceAsStackingContainer) {
+ isStacking = true;
+ isNormalFlow = false;
+ } else {
+ isStacking = isStackingContext();
+ isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
+ }
+ break;
+ case OverflowScrollCanBeStackingContainers:
+ ASSERT(!layerToForceAsStackingContainer);
+ isStacking = isStackingContainer();
+ isNormalFlow = isNormalFlowOnly();
+ break;
+ case OnlyStackingContextsCanBeStackingContainers:
+ isStacking = isStackingContext();
+ isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
+ break;
}
// Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStacking));
- if (includeHiddenLayer && !isNormalFlowOnly() && !isOutOfFlowRenderFlowThread()) {
+ if (includeHiddenLayer && !isNormalFlow && !isOutOfFlowRenderFlowThread()) {
// Determine which buffer the child should be in.
OwnPtr<Vector<RenderLayer*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
@@ -5681,7 +5674,7 @@
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
// Ignore reflections.
if (!m_reflection || reflectionLayer() != child)
- child->collectLayers(includeHiddenLayers, behavior, posBuffer, negBuffer, layerToForceAsStackingContainer);
+ child->collectLayers(includeHiddenLayers, posBuffer, negBuffer, layerToForceAsStackingContainer, collectLayersBehavior);
}
}
}
@@ -5743,23 +5736,28 @@
bool RenderLayer::shouldBeNormalFlowOnly() const
{
- return (renderer()->hasOverflowClip()
- || renderer()->hasReflection()
- || renderer()->hasMask()
- || renderer()->isCanvas()
- || renderer()->isVideo()
- || renderer()->isEmbeddedObject()
- || renderer()->isRenderIFrame()
- || (renderer()->style()->specifiesColumns() && !isRootLayer()))
- && !renderer()->isPositioned()
- && !renderer()->hasTransform()
- && !renderer()->hasClipPath()
- && !renderer()->hasFilter()
- && !renderer()->hasBlendMode()
- && !isTransparent()
- && !needsCompositedScrolling()
- && !renderer()->isFloatingWithShapeOutside()
- ;
+ return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !needsCompositedScrolling();
+}
+
+bool RenderLayer::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const
+{
+ const bool couldBeNormalFlow = renderer()->hasOverflowClip()
+ || renderer()->hasReflection()
+ || renderer()->hasMask()
+ || renderer()->isCanvas()
+ || renderer()->isVideo()
+ || renderer()->isEmbeddedObject()
+ || renderer()->isRenderIFrame()
+ || (renderer()->style()->specifiesColumns() && !isRootLayer());
+ const bool preventsElementFromBeingNormalFlow = renderer()->isPositioned()
+ || renderer()->hasTransform()
+ || renderer()->hasClipPath()
+ || renderer()->hasFilter()
+ || renderer()->hasBlendMode()
+ || isTransparent()
+ || renderer()->isFloatingWithShapeOutside();
+
+ return couldBeNormalFlow && !preventsElementFromBeingNormalFlow;
}
void RenderLayer::updateIsNormalFlowOnly()
diff --git a/Source/core/rendering/RenderLayer.h b/Source/core/rendering/RenderLayer.h
index 3661b2c..ce7f7c8 100644
--- a/Source/core/rendering/RenderLayer.h
+++ b/Source/core/rendering/RenderLayer.h
@@ -878,12 +878,16 @@
void setForceNeedsCompositedScrolling(ForceNeedsCompositedScrollingMode);
private:
- enum CollectLayersBehavior { StopAtStackingContexts, StopAtStackingContainers };
+enum CollectLayersBehavior {
+ ForceLayerToStackingContainer,
+ OverflowScrollCanBeStackingContainers,
+ OnlyStackingContextsCanBeStackingContainers
+};
void updateZOrderLists();
void rebuildZOrderLists();
// See the comment for collectLayers for information about the layerToForceAsStackingContainer parameter.
- void rebuildZOrderLists(CollectLayersBehavior, OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0);
+ void rebuildZOrderLists(OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0, CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
void clearZOrderLists();
void updateNormalFlowList();
@@ -962,7 +966,7 @@
// post-promotion layer lists, by allowing us to treat a layer as if it is a
// stacking context, without adding a new member to RenderLayer or modifying
// the style (which could cause extra allocations).
- void collectLayers(bool includeHiddenLayers, CollectLayersBehavior, OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0);
+ void collectLayers(bool includeHiddenLayers, OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0, CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
struct LayerPaintingInfo {
LayerPaintingInfo(RenderLayer* inRootLayer, const LayoutRect& inDirtyRect, PaintBehavior inPaintBehavior, const LayoutSize& inSubPixelAccumulation, RenderObject* inPaintingRoot = 0, RenderRegion*inRegion = 0, OverlapTestRequestMap* inOverlapTestRequests = 0)
@@ -1046,6 +1050,7 @@
bool hasScrollableVerticalOverflow() const;
bool shouldBeNormalFlowOnly() const;
+ bool shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const;
bool shouldBeSelfPaintingLayer() const;