2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
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>
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.
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.
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
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.
45 #include "core/rendering/RenderLayerStackingNode.h"
47 #include "core/rendering/RenderLayer.h"
48 #include "core/rendering/RenderLayerCompositor.h"
49 #include "core/rendering/RenderView.h"
50 #include "public/platform/Platform.h"
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.
57 RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer)
59 , m_descendantsAreContiguousInStackingOrder(false)
60 , m_descendantsAreContiguousInStackingOrderDirty(true)
61 , m_normalFlowListDirty(true)
62 , m_needsToBeStackingContainer(false)
63 , m_needsToBeStackingContainerHasBeenRecorded(false)
65 , m_layerListMutationAllowed(true)
69 m_isNormalFlowOnly = shouldBeNormalFlowOnly();
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();
76 RenderLayerStackingNode::~RenderLayerStackingNode()
79 if (!renderer()->documentBeingDestroyed()) {
80 ASSERT(!isInStackingParentZOrderLists());
81 ASSERT(!isInStackingParentNormalFlowList());
83 updateStackingParentForZOrderLists(0);
84 updateStackingParentForNormalFlowList(0);
89 bool RenderLayerStackingNode::isStackingContext(const RenderStyle* style) const
91 return !style->hasAutoZIndex() || layer()->isRootLayer();
94 // Helper for the sorting of layers by z-index.
95 static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStackingNode* second)
97 return first->zIndex() < second->zIndex();
100 RenderLayerCompositor* RenderLayerStackingNode::compositor() const
102 if (!renderer()->view())
104 return renderer()->view()->compositor();
107 void RenderLayerStackingNode::dirtyNormalFlowListCanBePromotedToStackingContainer()
109 m_descendantsAreContiguousInStackingOrderDirty = true;
111 if (m_normalFlowListDirty || !normalFlowList())
114 for (size_t index = 0; index < normalFlowList()->size(); ++index)
115 normalFlowList()->at(index)->dirtyNormalFlowListCanBePromotedToStackingContainer();
118 void RenderLayerStackingNode::dirtySiblingStackingNodeCanBePromotedToStackingContainer()
120 RenderLayerStackingNode* stackingNode = ancestorStackingNode();
124 if (!stackingNode->zOrderListsDirty() && stackingNode->posZOrderList()) {
125 for (size_t index = 0; index < stackingNode->posZOrderList()->size(); ++index)
126 stackingNode->posZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
129 stackingNode->dirtyNormalFlowListCanBePromotedToStackingContainer();
131 if (!stackingNode->zOrderListsDirty() && stackingNode->negZOrderList()) {
132 for (size_t index = 0; index < stackingNode->negZOrderList()->size(); ++index)
133 stackingNode->negZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
137 void RenderLayerStackingNode::dirtyZOrderLists()
139 ASSERT(m_layerListMutationAllowed);
140 ASSERT(isStackingContainer());
143 updateStackingParentForZOrderLists(0);
147 m_posZOrderList->clear();
149 m_negZOrderList->clear();
150 m_zOrderListsDirty = true;
152 m_descendantsAreContiguousInStackingOrderDirty = true;
154 if (!renderer()->documentBeingDestroyed()) {
155 compositor()->setNeedsUpdateCompositingRequirementsState();
156 compositor()->setCompositingLayersNeedRebuild();
157 if (renderer()->acceleratedCompositingForOverflowScrollEnabled())
158 compositor()->setNeedsToRecomputeCompositingRequirements();
162 void RenderLayerStackingNode::dirtyStackingContainerZOrderLists()
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();
170 RenderLayerStackingNode* stackingContainerNode = ancestorStackingContainerNode();
171 if (stackingContainerNode)
172 stackingContainerNode->dirtyZOrderLists();
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
179 RenderLayerStackingNode* stackingNode = ancestorStackingNode();
180 if (stackingNode && stackingNode != stackingContainerNode)
181 stackingNode->dirtyZOrderLists();
184 void RenderLayerStackingNode::dirtyNormalFlowList()
186 ASSERT(m_layerListMutationAllowed);
189 updateStackingParentForNormalFlowList(0);
192 if (m_normalFlowList)
193 m_normalFlowList->clear();
194 m_normalFlowListDirty = true;
196 if (!renderer()->documentBeingDestroyed()) {
197 compositor()->setCompositingLayersNeedRebuild();
198 if (renderer()->acceleratedCompositingForOverflowScrollEnabled())
199 compositor()->setNeedsToRecomputeCompositingRequirements();
203 void RenderLayerStackingNode::rebuildZOrderLists()
205 ASSERT(m_layerListMutationAllowed);
206 ASSERT(isDirtyStackingContainer());
207 rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
210 updateStackingParentForZOrderLists(this);
213 m_zOrderListsDirty = false;
216 void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList,
217 OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer,
218 CollectLayersBehavior collectLayersBehavior)
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);
225 // Sort the two lists.
227 std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
230 std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
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.
242 posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>);
243 posZOrderList->append(layer->stackingNode());
249 void RenderLayerStackingNode::updateNormalFlowList()
251 if (!m_normalFlowListDirty)
254 ASSERT(m_layerListMutationAllowed);
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());
266 updateStackingParentForNormalFlowList(this);
269 m_normalFlowListDirty = false;
272 void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer,
273 const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior)
275 if (layer()->isInTopLayer())
278 layer()->updateDescendantDependentFlags();
280 bool isStacking = false;
281 bool isNormalFlow = false;
283 switch (collectLayersBehavior) {
284 case ForceLayerToStackingContainer:
285 ASSERT(nodeToForceAsStackingContainer);
286 if (this == nodeToForceAsStackingContainer) {
288 isNormalFlow = false;
290 isStacking = isStackingContext();
291 isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
294 case OverflowScrollCanBeStackingContainers:
295 ASSERT(!nodeToForceAsStackingContainer);
296 isStacking = isStackingContainer();
297 isNormalFlow = isNormalFlowOnly();
299 case OnlyStackingContextsCanBeStackingContainers:
300 isStacking = isStackingContext();
301 isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
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;
310 // Create the buffer if it doesn't exist yet.
312 buffer = adoptPtr(new Vector<RenderLayerStackingNode*>);
314 // Append ourselves at the end of the appropriate buffer.
315 buffer->append(this);
318 // Recur into our children to collect more layers, but only if we don't establish
319 // a stacking context/container.
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);
330 bool RenderLayerStackingNode::isInStackingParentZOrderLists() const
332 if (!m_stackingParent || m_stackingParent->zOrderListsDirty())
335 if (m_stackingParent->posZOrderList() && m_stackingParent->posZOrderList()->find(this) != kNotFound)
338 if (m_stackingParent->negZOrderList() && m_stackingParent->negZOrderList()->find(this) != kNotFound)
344 bool RenderLayerStackingNode::isInStackingParentNormalFlowList() const
346 if (!m_stackingParent || m_stackingParent->normalFlowListDirty())
349 return (m_stackingParent->normalFlowList() && m_stackingParent->normalFlowList()->find(this) != kNotFound);
352 void RenderLayerStackingNode::updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent)
354 if (m_posZOrderList) {
355 for (size_t i = 0; i < m_posZOrderList->size(); ++i)
356 m_posZOrderList->at(i)->setStackingParent(stackingParent);
359 if (m_negZOrderList) {
360 for (size_t i = 0; i < m_negZOrderList->size(); ++i)
361 m_negZOrderList->at(i)->setStackingParent(stackingParent);
365 void RenderLayerStackingNode::updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent)
367 if (m_normalFlowList) {
368 for (size_t i = 0; i < m_normalFlowList->size(); ++i)
369 m_normalFlowList->at(i)->setStackingParent(stackingParent);
374 void RenderLayerStackingNode::updateLayerListsIfNeeded()
377 updateNormalFlowList();
379 if (!layer()->reflectionInfo())
382 RenderLayer* reflectionLayer = layer()->reflectionInfo()->reflectionLayer();
383 reflectionLayer->stackingNode()->updateZOrderLists();
384 reflectionLayer->stackingNode()->updateNormalFlowList();
387 void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle)
389 bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false;
390 EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
391 int oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
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())
399 dirtyStackingContainerZOrderLists();
401 if (isStackingContainer())
406 compositor()->setNeedsUpdateCompositingRequirementsState();
409 bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const
411 return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !layer()->needsCompositedScrolling();
414 bool RenderLayerStackingNode::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const
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();
431 return couldBeNormalFlow && !preventsElementFromBeingNormalFlow;
434 void RenderLayerStackingNode::updateIsNormalFlowOnly()
436 bool isNormalFlowOnly = shouldBeNormalFlowOnly();
437 if (isNormalFlowOnly == this->isNormalFlowOnly())
440 m_isNormalFlowOnly = isNormalFlowOnly;
441 if (RenderLayer* p = layer()->parent())
442 p->stackingNode()->dirtyNormalFlowList();
443 dirtyStackingContainerZOrderLists();
446 bool RenderLayerStackingNode::needsToBeStackingContainer() const
448 return layer()->scrollableArea() && layer()->scrollableArea()->adjustForForceCompositedScrollingMode(m_needsToBeStackingContainer);
451 // Determine whether the current layer can be promoted to a stacking container.
452 // We do this by computing what positive and negative z-order lists would look
453 // like before and after promotion, and ensuring that proper stacking order is
454 // preserved between the two sets of lists.
455 void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder()
457 TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder");
459 if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !renderer()->acceleratedCompositingForOverflowScrollEnabled())
462 if (!layer()->scrollsOverflow())
465 RenderLayerStackingNode* stackingNode = ancestorStackingNode();
469 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
470 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
471 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
472 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
474 collectBeforePromotionZOrderList(stackingNode, posZOrderListBeforePromote, negZOrderListBeforePromote);
475 collectAfterPromotionZOrderList(stackingNode, posZOrderListAfterPromote, negZOrderListAfterPromote);
477 size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size());
479 m_descendantsAreContiguousInStackingOrderDirty = false;
480 m_descendantsAreContiguousInStackingOrder = false;
482 const RenderLayerStackingNode* nodeAfterPromote = 0;
483 for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
484 const RenderLayerStackingNode* nodeBeforePromote = i < negZOrderListBeforePromote->size()
485 ? negZOrderListBeforePromote->at(i)
486 : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size());
487 nodeAfterPromote = i < negZOrderListAfterPromote->size()
488 ? negZOrderListAfterPromote->at(i)
489 : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size());
491 if (nodeBeforePromote != nodeAfterPromote && (nodeAfterPromote != this || renderer()->hasBackground()))
495 nodeAfterPromote = 0;
496 for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
497 const RenderLayerStackingNode* nodeBeforePromote = i < posZOrderListBeforePromote->size()
498 ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1)
499 : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1);
500 nodeAfterPromote = i < posZOrderListAfterPromote->size()
501 ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1)
502 : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1);
504 if (nodeBeforePromote != nodeAfterPromote && nodeAfterPromote != this)
508 m_descendantsAreContiguousInStackingOrder = true;
511 void RenderLayerStackingNode::collectBeforePromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
512 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
514 ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, OnlyStackingContextsCanBeStackingContainers);
516 const RenderLayer* currentLayer = layer();
517 const RenderLayer* positionedAncestor = currentLayer->parent();
518 while (positionedAncestor && !positionedAncestor->isPositionedContainer() && !positionedAncestor->stackingNode()->isStackingContext())
519 positionedAncestor = positionedAncestor->parent();
520 if (positionedAncestor && (!positionedAncestor->isPositionedContainer() || positionedAncestor->stackingNode()->isStackingContext()))
521 positionedAncestor = 0;
524 posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>());
525 else if (posZOrderList->find(this) != kNotFound)
528 // The current node will appear in the z-order lists after promotion, so
529 // for a meaningful comparison, we must insert it in the z-order lists
530 // before promotion if it does not appear there already.
531 if (!positionedAncestor) {
532 posZOrderList->prepend(this);
536 for (size_t index = 0; index < posZOrderList->size(); index++) {
537 if (posZOrderList->at(index)->layer() == positionedAncestor) {
538 posZOrderList->insert(index + 1, this);
544 void RenderLayerStackingNode::collectAfterPromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
545 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
547 ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, ForceLayerToStackingContainer);
550 // Compute what positive and negative z-order lists would look like before and
551 // after promotion, so we can later ensure that proper stacking order is
552 // preserved between the two sets of lists.
556 // - = negative z-order child of currentLayer
557 // + = positive z-order child of currentLayer
558 // a = positioned ancestor of currentLayer
559 // x = any other RenderLayer in the list
561 // (a) xxxxx-----++a+++x
562 // (b) xxx-----c++++++xx
564 // Normally the current layer would be painted in the normal flow list if it
565 // doesn't already appear in the positive z-order list. However, in the case
566 // that the layer has a positioned ancestor, it will paint directly after the
567 // positioned ancestor. In example (a), the current layer would be painted in
568 // the middle of its own positive z-order children, so promoting would cause a
569 // change in paint order (since a promoted layer will paint all of its positive
570 // z-order children strictly after it paints itself).
572 // In example (b), it is ok to promote the current layer only if it does not
573 // have a background. If it has a background, the background gets painted before
574 // the layer's negative z-order children, so again, a promotion would cause a
575 // change in paint order (causing the background to get painted after the
576 // negative z-order children instead of before).
578 void RenderLayerStackingNode::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list)
580 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderList;
581 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderList;
583 RenderLayerStackingNode* stackingNode = ancestorStackingNode();
589 collectBeforePromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
592 collectAfterPromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
597 for (size_t index = 0; index < negZOrderList->size(); ++index)
598 list.append(negZOrderList->at(index)->renderer()->node());
602 for (size_t index = 0; index < posZOrderList->size(); ++index)
603 list.append(posZOrderList->at(index)->renderer()->node());
607 bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const
609 if (isStackingContext() || !ancestorStackingContainerNode())
612 ASSERT(!m_descendantsAreContiguousInStackingOrderDirty);
613 return m_descendantsAreContiguousInStackingOrder;
616 bool RenderLayerStackingNode::setNeedsToBeStackingContainer(bool needsToBeStackingContainer)
618 if (this->needsToBeStackingContainer() == needsToBeStackingContainer)
621 // Count the total number of RenderLayers which need to be stacking
622 // containers some point. This should be recorded at most once per
623 // RenderLayer, so we check m_needsToBeStackingContainerHasBeenRecorded.
624 if (renderer()->acceleratedCompositingForOverflowScrollEnabled() && !m_needsToBeStackingContainerHasBeenRecorded) {
625 blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", NeedsToBeStackingContainerBucket, CompositedScrollingHistogramMax);
626 m_needsToBeStackingContainerHasBeenRecorded = true;
629 m_needsToBeStackingContainer = needsToBeStackingContainer;
634 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContainerNode() const
636 RenderLayer* ancestor = layer()->parent();
637 while (ancestor && !ancestor->stackingNode()->isStackingContainer())
638 ancestor = ancestor->parent();
640 return ancestor->stackingNode();
644 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const
646 RenderLayer* ancestor = layer()->parent();
647 while (ancestor && !ancestor->stackingNode()->isStackingContext())
648 ancestor = ancestor->parent();
650 return ancestor->stackingNode();
654 RenderLayerModelObject* RenderLayerStackingNode::renderer() const
656 return m_layer->renderer();
659 } // namespace WebCore