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;