• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3  *
4  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5  *
6  * Other contributors:
7  *   Robert O'Callahan <roc+@cs.cmu.edu>
8  *   David Baron <dbaron@fas.harvard.edu>
9  *   Christian Biesinger <cbiesinger@web.de>
10  *   Randall Jesup <rjesup@wgate.com>
11  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12  *   Josh Soref <timeless@mac.com>
13  *   Boris Zbarsky <bzbarsky@mit.edu>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  *
29  * Alternatively, the contents of this file may be used under the terms
30  * of either the Mozilla Public License Version 1.1, found at
31  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33  * (the "GPL"), in which case the provisions of the MPL or the GPL are
34  * applicable instead of those above.  If you wish to allow use of your
35  * version of this file only under the terms of one of those two
36  * licenses (the MPL or the GPL) and not to allow others to use your
37  * version of this file under the LGPL, indicate your decision by
38  * deletingthe provisions above and replace them with the notice and
39  * other provisions required by the MPL or the GPL, as the case may be.
40  * If you do not delete the provisions above, a recipient may use your
41  * version of this file under any of the LGPL, the MPL or the GPL.
42  */
43 
44 #include "config.h"
45 #include "core/rendering/RenderLayerStackingNode.h"
46 
47 #include "core/rendering/RenderLayer.h"
48 #include "core/rendering/RenderLayerCompositor.h"
49 #include "core/rendering/RenderView.h"
50 #include "public/platform/Platform.h"
51 
52 namespace WebCore {
53 
54 // FIXME: This should not require RenderLayer. There is currently a cycle where
55 // in order to determine if we shoulBeNormalFlowOnly() and isStackingContainer()
56 // we have to ask the render layer about some of its state.
RenderLayerStackingNode(RenderLayer * layer)57 RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer)
58     : m_layer(layer)
59     , m_descendantsAreContiguousInStackingOrder(false)
60     , m_descendantsAreContiguousInStackingOrderDirty(true)
61     , m_normalFlowListDirty(true)
62     , m_needsToBeStackingContainer(false)
63     , m_needsToBeStackingContainerHasBeenRecorded(false)
64 #if !ASSERT_DISABLED
65     , m_layerListMutationAllowed(true)
66     , m_stackingParent(0)
67 #endif
68 {
69     m_isNormalFlowOnly = shouldBeNormalFlowOnly();
70 
71     // Non-stacking containers should have empty z-order lists. As this is already the case,
72     // there is no need to dirty / recompute these lists.
73     m_zOrderListsDirty = isStackingContainer();
74 }
75 
~RenderLayerStackingNode()76 RenderLayerStackingNode::~RenderLayerStackingNode()
77 {
78 #if !ASSERT_DISABLED
79     if (!renderer()->documentBeingDestroyed()) {
80         ASSERT(!isInStackingParentZOrderLists());
81         ASSERT(!isInStackingParentNormalFlowList());
82 
83         updateStackingParentForZOrderLists(0);
84         updateStackingParentForNormalFlowList(0);
85     }
86 #endif
87 }
88 
isStackingContext(const RenderStyle * style) const89 bool RenderLayerStackingNode::isStackingContext(const RenderStyle* style) const
90 {
91     return !style->hasAutoZIndex() || layer()->isRootLayer();
92 }
93 
94 // Helper for the sorting of layers by z-index.
compareZIndex(RenderLayerStackingNode * first,RenderLayerStackingNode * second)95 static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStackingNode* second)
96 {
97     return first->zIndex() < second->zIndex();
98 }
99 
compositor() const100 RenderLayerCompositor* RenderLayerStackingNode::compositor() const
101 {
102     if (!renderer()->view())
103         return 0;
104     return renderer()->view()->compositor();
105 }
106 
dirtyNormalFlowListCanBePromotedToStackingContainer()107 void RenderLayerStackingNode::dirtyNormalFlowListCanBePromotedToStackingContainer()
108 {
109     m_descendantsAreContiguousInStackingOrderDirty = true;
110 
111     if (m_normalFlowListDirty || !normalFlowList())
112         return;
113 
114     for (size_t index = 0; index < normalFlowList()->size(); ++index)
115         normalFlowList()->at(index)->dirtyNormalFlowListCanBePromotedToStackingContainer();
116 }
117 
dirtySiblingStackingNodeCanBePromotedToStackingContainer()118 void RenderLayerStackingNode::dirtySiblingStackingNodeCanBePromotedToStackingContainer()
119 {
120     RenderLayerStackingNode* stackingNode = ancestorStackingNode();
121     if (!stackingNode)
122         return;
123 
124     if (!stackingNode->zOrderListsDirty() && stackingNode->posZOrderList()) {
125         for (size_t index = 0; index < stackingNode->posZOrderList()->size(); ++index)
126             stackingNode->posZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
127     }
128 
129     stackingNode->dirtyNormalFlowListCanBePromotedToStackingContainer();
130 
131     if (!stackingNode->zOrderListsDirty() && stackingNode->negZOrderList()) {
132         for (size_t index = 0; index < stackingNode->negZOrderList()->size(); ++index)
133             stackingNode->negZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
134     }
135 }
136 
dirtyZOrderLists()137 void RenderLayerStackingNode::dirtyZOrderLists()
138 {
139     ASSERT(m_layerListMutationAllowed);
140     ASSERT(isStackingContainer());
141 
142 #if !ASSERT_DISABLED
143     updateStackingParentForZOrderLists(0);
144 #endif
145 
146     if (m_posZOrderList)
147         m_posZOrderList->clear();
148     if (m_negZOrderList)
149         m_negZOrderList->clear();
150     m_zOrderListsDirty = true;
151 
152     m_descendantsAreContiguousInStackingOrderDirty = true;
153 
154     if (!renderer()->documentBeingDestroyed()) {
155         compositor()->setNeedsUpdateCompositingRequirementsState();
156         compositor()->setCompositingLayersNeedRebuild();
157         if (layer()->acceleratedCompositingForOverflowScrollEnabled())
158             compositor()->setNeedsToRecomputeCompositingRequirements();
159     }
160 }
161 
dirtyStackingContainerZOrderLists()162 void RenderLayerStackingNode::dirtyStackingContainerZOrderLists()
163 {
164     // Any siblings in the ancestor stacking context could also be affected.
165     // Changing z-index, for example, could cause us to stack in between a
166     // sibling's descendants, meaning that we have to recompute
167     // m_descendantsAreContiguousInStackingOrder for that sibling.
168     dirtySiblingStackingNodeCanBePromotedToStackingContainer();
169 
170     RenderLayerStackingNode* stackingContainerNode = ancestorStackingContainerNode();
171     if (stackingContainerNode)
172         stackingContainerNode->dirtyZOrderLists();
173 
174     // Any change that could affect our stacking container's z-order list could
175     // cause other RenderLayers in our stacking context to either opt in or out
176     // of composited scrolling. It is important that we make our stacking
177     // context aware of these z-order changes so the appropriate updating can
178     // happen.
179     RenderLayerStackingNode* stackingNode = ancestorStackingNode();
180     if (stackingNode && stackingNode != stackingContainerNode)
181         stackingNode->dirtyZOrderLists();
182 }
183 
dirtyNormalFlowList()184 void RenderLayerStackingNode::dirtyNormalFlowList()
185 {
186     ASSERT(m_layerListMutationAllowed);
187 
188 #if !ASSERT_DISABLED
189     updateStackingParentForNormalFlowList(0);
190 #endif
191 
192     if (m_normalFlowList)
193         m_normalFlowList->clear();
194     m_normalFlowListDirty = true;
195 
196     if (!renderer()->documentBeingDestroyed()) {
197         compositor()->setCompositingLayersNeedRebuild();
198         if (layer()->acceleratedCompositingForOverflowScrollEnabled())
199             compositor()->setNeedsToRecomputeCompositingRequirements();
200     }
201 }
202 
rebuildZOrderLists()203 void RenderLayerStackingNode::rebuildZOrderLists()
204 {
205     ASSERT(m_layerListMutationAllowed);
206     ASSERT(isDirtyStackingContainer());
207     rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
208 
209 #if !ASSERT_DISABLED
210     updateStackingParentForZOrderLists(this);
211 #endif
212 
213     m_zOrderListsDirty = false;
214 }
215 
rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode * >> & posZOrderList,OwnPtr<Vector<RenderLayerStackingNode * >> & negZOrderList,const RenderLayerStackingNode * nodeToForceAsStackingContainer,CollectLayersBehavior collectLayersBehavior)216 void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList,
217     OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer,
218     CollectLayersBehavior collectLayersBehavior)
219 {
220     for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
221         if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
222             child->stackingNode()->collectLayers(posZOrderList, negZOrderList, nodeToForceAsStackingContainer, collectLayersBehavior);
223     }
224 
225     // Sort the two lists.
226     if (posZOrderList)
227         std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
228 
229     if (negZOrderList)
230         std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
231 
232     // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes.
233     // The renderers of top layer elements are children of the view, sorted in top layer stacking order.
234     if (layer()->isRootLayer()) {
235         RenderObject* view = renderer()->view();
236         for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
237             Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0;
238             if (childElement && childElement->isInTopLayer()) {
239                 RenderLayer* layer = toRenderLayerModelObject(child)->layer();
240                 // Create the buffer if it doesn't exist yet.
241                 if (!posZOrderList)
242                     posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>);
243                 posZOrderList->append(layer->stackingNode());
244             }
245         }
246     }
247 }
248 
updateNormalFlowList()249 void RenderLayerStackingNode::updateNormalFlowList()
250 {
251     if (!m_normalFlowListDirty)
252         return;
253 
254     ASSERT(m_layerListMutationAllowed);
255 
256     for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
257         // Ignore non-overflow layers and reflections.
258         if (child->stackingNode()->isNormalFlowOnly() && (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)) {
259             if (!m_normalFlowList)
260                 m_normalFlowList = adoptPtr(new Vector<RenderLayerStackingNode*>);
261             m_normalFlowList->append(child->stackingNode());
262         }
263     }
264 
265 #if !ASSERT_DISABLED
266     updateStackingParentForNormalFlowList(this);
267 #endif
268 
269     m_normalFlowListDirty = false;
270 }
271 
collectLayers(OwnPtr<Vector<RenderLayerStackingNode * >> & posBuffer,OwnPtr<Vector<RenderLayerStackingNode * >> & negBuffer,const RenderLayerStackingNode * nodeToForceAsStackingContainer,CollectLayersBehavior collectLayersBehavior)272 void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer,
273     const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior)
274 {
275     if (layer()->isInTopLayer())
276         return;
277 
278     layer()->updateDescendantDependentFlags();
279 
280     bool isStacking = false;
281     bool isNormalFlow = false;
282 
283     switch (collectLayersBehavior) {
284     case ForceLayerToStackingContainer:
285         ASSERT(nodeToForceAsStackingContainer);
286         if (this == nodeToForceAsStackingContainer) {
287             isStacking = true;
288             isNormalFlow = false;
289         } else {
290             isStacking = isStackingContext();
291             isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
292         }
293         break;
294     case OverflowScrollCanBeStackingContainers:
295         ASSERT(!nodeToForceAsStackingContainer);
296         isStacking = isStackingContainer();
297         isNormalFlow = isNormalFlowOnly();
298         break;
299     case OnlyStackingContextsCanBeStackingContainers:
300         isStacking = isStackingContext();
301         isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
302         break;
303     }
304 
305     // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
306     if (!isNormalFlow && !layer()->isOutOfFlowRenderFlowThread()) {
307         // Determine which buffer the child should be in.
308         OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
309 
310         // Create the buffer if it doesn't exist yet.
311         if (!buffer)
312             buffer = adoptPtr(new Vector<RenderLayerStackingNode*>);
313 
314         // Append ourselves at the end of the appropriate buffer.
315         buffer->append(this);
316     }
317 
318     // Recur into our children to collect more layers, but only if we don't establish
319     // a stacking context/container.
320     if (!isStacking) {
321         for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
322             // Ignore reflections.
323             if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
324                 child->stackingNode()->collectLayers(posBuffer, negBuffer, nodeToForceAsStackingContainer, collectLayersBehavior);
325         }
326     }
327 }
328 
329 #if !ASSERT_DISABLED
isInStackingParentZOrderLists() const330 bool RenderLayerStackingNode::isInStackingParentZOrderLists() const
331 {
332     if (!m_stackingParent || m_stackingParent->zOrderListsDirty())
333         return false;
334 
335     if (m_stackingParent->posZOrderList() && m_stackingParent->posZOrderList()->find(this) != kNotFound)
336         return true;
337 
338     if (m_stackingParent->negZOrderList() && m_stackingParent->negZOrderList()->find(this) != kNotFound)
339         return true;
340 
341     return false;
342 }
343 
isInStackingParentNormalFlowList() const344 bool RenderLayerStackingNode::isInStackingParentNormalFlowList() const
345 {
346     if (!m_stackingParent || m_stackingParent->normalFlowListDirty())
347         return false;
348 
349     return (m_stackingParent->normalFlowList() && m_stackingParent->normalFlowList()->find(this) != kNotFound);
350 }
351 
updateStackingParentForZOrderLists(RenderLayerStackingNode * stackingParent)352 void RenderLayerStackingNode::updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent)
353 {
354     if (m_posZOrderList) {
355         for (size_t i = 0; i < m_posZOrderList->size(); ++i)
356             m_posZOrderList->at(i)->setStackingParent(stackingParent);
357     }
358 
359     if (m_negZOrderList) {
360         for (size_t i = 0; i < m_negZOrderList->size(); ++i)
361             m_negZOrderList->at(i)->setStackingParent(stackingParent);
362     }
363 }
364 
updateStackingParentForNormalFlowList(RenderLayerStackingNode * stackingParent)365 void RenderLayerStackingNode::updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent)
366 {
367     if (m_normalFlowList) {
368         for (size_t i = 0; i < m_normalFlowList->size(); ++i)
369             m_normalFlowList->at(i)->setStackingParent(stackingParent);
370     }
371 }
372 #endif
373 
updateLayerListsIfNeeded()374 void RenderLayerStackingNode::updateLayerListsIfNeeded()
375 {
376     updateZOrderLists();
377     updateNormalFlowList();
378 
379     if (!layer()->reflectionInfo())
380         return;
381 
382     RenderLayer* reflectionLayer = layer()->reflectionInfo()->reflectionLayer();
383     reflectionLayer->stackingNode()->updateZOrderLists();
384     reflectionLayer->stackingNode()->updateNormalFlowList();
385 }
386 
updateStackingNodesAfterStyleChange(const RenderStyle * oldStyle)387 void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle)
388 {
389     bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false;
390     EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
391     int oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
392 
393     // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
394     // likely be folded along with the rest.
395     bool isStackingContext = this->isStackingContext();
396     if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == zIndex())
397         return;
398 
399     dirtyStackingContainerZOrderLists();
400 
401     if (isStackingContainer())
402         dirtyZOrderLists();
403     else
404         clearZOrderLists();
405 
406     compositor()->setNeedsUpdateCompositingRequirementsState();
407 }
408 
shouldBeNormalFlowOnly() const409 bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const
410 {
411     return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !layer()->needsCompositedScrolling();
412 }
413 
shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const414 bool RenderLayerStackingNode::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const
415 {
416     const bool couldBeNormalFlow = renderer()->hasOverflowClip()
417         || renderer()->hasReflection()
418         || renderer()->hasMask()
419         || renderer()->isCanvas()
420         || renderer()->isVideo()
421         || renderer()->isEmbeddedObject()
422         || renderer()->isRenderIFrame()
423         || (renderer()->style()->specifiesColumns() && !layer()->isRootLayer());
424     const bool preventsElementFromBeingNormalFlow = renderer()->isPositioned()
425         || renderer()->hasTransform()
426         || renderer()->hasClipPath()
427         || renderer()->hasFilter()
428         || renderer()->hasBlendMode()
429         || layer()->isTransparent()
430         || renderer()->style()->hasFlowFrom();
431 
432     return couldBeNormalFlow && !preventsElementFromBeingNormalFlow;
433 }
434 
updateIsNormalFlowOnly()435 void RenderLayerStackingNode::updateIsNormalFlowOnly()
436 {
437     bool isNormalFlowOnly = shouldBeNormalFlowOnly();
438     if (isNormalFlowOnly == this->isNormalFlowOnly())
439         return;
440 
441     m_isNormalFlowOnly = isNormalFlowOnly;
442     if (RenderLayer* p = layer()->parent())
443         p->stackingNode()->dirtyNormalFlowList();
444     dirtyStackingContainerZOrderLists();
445 }
446 
needsToBeStackingContainer() const447 bool RenderLayerStackingNode::needsToBeStackingContainer() const
448 {
449     return layer()->scrollableArea() && layer()->scrollableArea()->adjustForForceCompositedScrollingMode(m_needsToBeStackingContainer);
450 }
451 
452 // Determine whether the current layer can be promoted to a stacking container.
453 // We do this by computing what positive and negative z-order lists would look
454 // like before and after promotion, and ensuring that proper stacking order is
455 // preserved between the two sets of lists.
updateDescendantsAreContiguousInStackingOrder()456 void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder()
457 {
458     TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder");
459 
460     const RenderLayer* currentLayer = layer();
461     if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !currentLayer->acceleratedCompositingForOverflowScrollEnabled())
462         return;
463 
464     if (!currentLayer->scrollsOverflow())
465         return;
466 
467     RenderLayerStackingNode* stackingNode = ancestorStackingNode();
468     if (!stackingNode)
469         return;
470 
471     OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
472     OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
473     OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
474     OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
475 
476     collectBeforePromotionZOrderList(stackingNode, posZOrderListBeforePromote, negZOrderListBeforePromote);
477     collectAfterPromotionZOrderList(stackingNode, posZOrderListAfterPromote, negZOrderListAfterPromote);
478 
479     size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size());
480 
481     m_descendantsAreContiguousInStackingOrderDirty = false;
482     m_descendantsAreContiguousInStackingOrder = false;
483 
484     const RenderLayerStackingNode* nodeAfterPromote = 0;
485     for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
486         const RenderLayerStackingNode* nodeBeforePromote = i < negZOrderListBeforePromote->size()
487             ? negZOrderListBeforePromote->at(i)
488             : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size());
489         nodeAfterPromote = i < negZOrderListAfterPromote->size()
490             ? negZOrderListAfterPromote->at(i)
491             : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size());
492 
493         if (nodeBeforePromote != nodeAfterPromote && (nodeAfterPromote != this || renderer()->hasBackground()))
494             return;
495     }
496 
497     nodeAfterPromote = 0;
498     for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
499         const RenderLayerStackingNode* nodeBeforePromote = i < posZOrderListBeforePromote->size()
500             ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1)
501             : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1);
502         nodeAfterPromote = i < posZOrderListAfterPromote->size()
503             ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1)
504             : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1);
505 
506         if (nodeBeforePromote != nodeAfterPromote && nodeAfterPromote != this)
507             return;
508     }
509 
510     m_descendantsAreContiguousInStackingOrder = true;
511 }
512 
collectBeforePromotionZOrderList(RenderLayerStackingNode * ancestorStackingNode,OwnPtr<Vector<RenderLayerStackingNode * >> & posZOrderList,OwnPtr<Vector<RenderLayerStackingNode * >> & negZOrderList)513 void RenderLayerStackingNode::collectBeforePromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
514     OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
515 {
516     ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, OnlyStackingContextsCanBeStackingContainers);
517 
518     const RenderLayer* currentLayer = layer();
519     const RenderLayer* positionedAncestor = currentLayer->parent();
520     while (positionedAncestor && !positionedAncestor->isPositionedContainer() && !positionedAncestor->stackingNode()->isStackingContext())
521         positionedAncestor = positionedAncestor->parent();
522     if (positionedAncestor && (!positionedAncestor->isPositionedContainer() || positionedAncestor->stackingNode()->isStackingContext()))
523         positionedAncestor = 0;
524 
525     if (!posZOrderList)
526         posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>());
527     else if (posZOrderList->find(this) != kNotFound)
528         return;
529 
530     // The current node will appear in the z-order lists after promotion, so
531     // for a meaningful comparison, we must insert it in the z-order lists
532     // before promotion if it does not appear there already.
533     if (!positionedAncestor) {
534         posZOrderList->prepend(this);
535         return;
536     }
537 
538     for (size_t index = 0; index < posZOrderList->size(); index++) {
539         if (posZOrderList->at(index)->layer() == positionedAncestor) {
540             posZOrderList->insert(index + 1, this);
541             return;
542         }
543     }
544 }
545 
collectAfterPromotionZOrderList(RenderLayerStackingNode * ancestorStackingNode,OwnPtr<Vector<RenderLayerStackingNode * >> & posZOrderList,OwnPtr<Vector<RenderLayerStackingNode * >> & negZOrderList)546 void RenderLayerStackingNode::collectAfterPromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
547     OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
548 {
549     ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, ForceLayerToStackingContainer);
550 }
551 
552 // Compute what positive and negative z-order lists would look like before and
553 // after promotion, so we can later ensure that proper stacking order is
554 // preserved between the two sets of lists.
555 //
556 // A few examples:
557 // c = currentLayer
558 // - = negative z-order child of currentLayer
559 // + = positive z-order child of currentLayer
560 // a = positioned ancestor of currentLayer
561 // x = any other RenderLayer in the list
562 //
563 // (a) xxxxx-----++a+++x
564 // (b) xxx-----c++++++xx
565 //
566 // Normally the current layer would be painted in the normal flow list if it
567 // doesn't already appear in the positive z-order list. However, in the case
568 // that the layer has a positioned ancestor, it will paint directly after the
569 // positioned ancestor. In example (a), the current layer would be painted in
570 // the middle of its own positive z-order children, so promoting would cause a
571 // change in paint order (since a promoted layer will paint all of its positive
572 // z-order children strictly after it paints itself).
573 //
574 // In example (b), it is ok to promote the current layer only if it does not
575 // have a background. If it has a background, the background gets painted before
576 // the layer's negative z-order children, so again, a promotion would cause a
577 // change in paint order (causing the background to get painted after the
578 // negative z-order children instead of before).
579 //
computePaintOrderList(PaintOrderListType type,Vector<RefPtr<Node>> & list)580 void RenderLayerStackingNode::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list)
581 {
582     OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderList;
583     OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderList;
584 
585     RenderLayerStackingNode* stackingNode = ancestorStackingNode();
586     if (!stackingNode)
587         return;
588 
589     switch (type) {
590     case BeforePromote:
591         collectBeforePromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
592         break;
593     case AfterPromote:
594         collectAfterPromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
595         break;
596     }
597 
598     if (negZOrderList) {
599         for (size_t index = 0; index < negZOrderList->size(); ++index)
600             list.append(negZOrderList->at(index)->renderer()->node());
601     }
602 
603     if (posZOrderList) {
604         for (size_t index = 0; index < posZOrderList->size(); ++index)
605             list.append(posZOrderList->at(index)->renderer()->node());
606     }
607 }
608 
descendantsAreContiguousInStackingOrder() const609 bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const
610 {
611     if (isStackingContext() || !ancestorStackingContainerNode())
612         return true;
613 
614     ASSERT(!m_descendantsAreContiguousInStackingOrderDirty);
615     return m_descendantsAreContiguousInStackingOrder;
616 }
617 
setNeedsToBeStackingContainer(bool needsToBeStackingContainer)618 bool RenderLayerStackingNode::setNeedsToBeStackingContainer(bool needsToBeStackingContainer)
619 {
620     if (this->needsToBeStackingContainer() == needsToBeStackingContainer)
621         return false;
622 
623     // Count the total number of RenderLayers which need to be stacking
624     // containers some point. This should be recorded at most once per
625     // RenderLayer, so we check m_needsToBeStackingContainerHasBeenRecorded.
626     if (layer()->acceleratedCompositingForOverflowScrollEnabled() && !m_needsToBeStackingContainerHasBeenRecorded) {
627         blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", RenderLayer::NeedsToBeStackingContainerBucket, RenderLayer::CompositedScrollingHistogramMax);
628         m_needsToBeStackingContainerHasBeenRecorded = true;
629     }
630 
631     m_needsToBeStackingContainer = needsToBeStackingContainer;
632 
633     return true;
634 }
635 
ancestorStackingContainerNode() const636 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContainerNode() const
637 {
638     RenderLayer* ancestor = layer()->parent();
639     while (ancestor && !ancestor->stackingNode()->isStackingContainer())
640         ancestor = ancestor->parent();
641     if (ancestor)
642         return ancestor->stackingNode();
643     return 0;
644 }
645 
ancestorStackingNode() const646 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const
647 {
648     RenderLayer* ancestor = layer()->parent();
649     while (ancestor && !ancestor->stackingNode()->isStackingContext())
650         ancestor = ancestor->parent();
651     if (ancestor)
652         return ancestor->stackingNode();
653     return 0;
654 }
655 
renderer() const656 RenderLayerModelObject* RenderLayerStackingNode::renderer() const
657 {
658     return m_layer->renderer();
659 }
660 
661 } // namespace WebCore
662