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