void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer, const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior) { if (layer()->isInTopLayer()) return; layer()->updateDescendantDependentFlags(); bool isStacking = false; bool isNormalFlow = false; switch (collectLayersBehavior) { case ForceLayerToStackingContainer: ASSERT(nodeToForceAsStackingContainer); if (this == nodeToForceAsStackingContainer) { isStacking = true; isNormalFlow = false; } else { isStacking = isStackingContext(); isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling(); } break; case OverflowScrollCanBeStackingContainers: ASSERT(!nodeToForceAsStackingContainer); 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. if (!isNormalFlow && !layer()->isOutOfFlowRenderFlowThread()) { // Determine which buffer the child should be in. OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; // Create the buffer if it doesn't exist yet. if (!buffer) buffer = adoptPtr(new Vector<RenderLayerStackingNode*>); // Append ourselves at the end of the appropriate buffer. buffer->append(this); } // Recur into our children to collect more layers, but only if we don't establish // a stacking context/container. if (!isStacking) { for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { // Ignore reflections. if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child) child->stackingNode()->collectLayers(posBuffer, negBuffer, nodeToForceAsStackingContainer, collectLayersBehavior); } } }
bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const { if (isStackingContext() || !ancestorStackingContainerNode()) return true; ASSERT(!m_descendantsAreContiguousInStackingOrderDirty); return m_descendantsAreContiguousInStackingOrder; }
// Determine whether the current layer can be promoted to a stacking container. // We do this by computing what positive and negative z-order lists would look // like before and after promotion, and ensuring that proper stacking order is // preserved between the two sets of lists. void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder() { TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder"); const RenderLayer* currentLayer = layer(); if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !currentLayer->acceleratedCompositingForOverflowScrollEnabled()) return; if (!currentLayer->scrollsOverflow()) return; RenderLayerStackingNode* stackingNode = ancestorStackingNode(); if (!stackingNode) return; OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>); OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>); OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>); OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>); collectBeforePromotionZOrderList(stackingNode, posZOrderListBeforePromote, negZOrderListBeforePromote); collectAfterPromotionZOrderList(stackingNode, posZOrderListAfterPromote, negZOrderListAfterPromote); size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size()); m_descendantsAreContiguousInStackingOrderDirty = false; m_descendantsAreContiguousInStackingOrder = false; const RenderLayerStackingNode* nodeAfterPromote = 0; for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) { const RenderLayerStackingNode* nodeBeforePromote = i < negZOrderListBeforePromote->size() ? negZOrderListBeforePromote->at(i) : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size()); nodeAfterPromote = i < negZOrderListAfterPromote->size() ? negZOrderListAfterPromote->at(i) : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size()); if (nodeBeforePromote != nodeAfterPromote && (nodeAfterPromote != this || renderer()->hasBackground())) return; } nodeAfterPromote = 0; for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) { const RenderLayerStackingNode* nodeBeforePromote = i < posZOrderListBeforePromote->size() ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1) : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1); nodeAfterPromote = i < posZOrderListAfterPromote->size() ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1) : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1); if (nodeBeforePromote != nodeAfterPromote && nodeAfterPromote != this) return; } m_descendantsAreContiguousInStackingOrder = true; }
// FIXME: This should not require PaintLayer. There is currently a cycle where // in order to determine if we isStacked() we have to ask the paint // layer about some of its state. PaintLayerStackingNode::PaintLayerStackingNode(PaintLayer* layer) : m_layer(layer) #if DCHECK_IS_ON() , m_layerListMutationAllowed(true), m_stackingParent(0) #endif { m_isStacked = layoutObject()->styleRef().isStacked(); // Non-stacking contexts should have empty z-order lists. As this is already // the case, there is no need to dirty / recompute these lists. m_zOrderListsDirty = isStackingContext(); }
// FIXME: This should not require RenderLayer. There is currently a cycle where // in order to determine if we shoulBeNormalFlowOnly() we have to ask the render // layer about some of its state. RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer) : m_layer(layer) , m_normalFlowListDirty(true) #if ASSERT_ENABLED , m_layerListMutationAllowed(true) , m_stackingParent(0) #endif { m_isNormalFlowOnly = shouldBeNormalFlowOnly(); // Non-stacking contexts should have empty z-order lists. As this is already the case, // there is no need to dirty / recompute these lists. m_zOrderListsDirty = isStackingContext(); }
void RenderLayerStackingNode::dirtyZOrderLists() { ASSERT(m_layerListMutationAllowed); ASSERT(isStackingContext()); #if ASSERT_ENABLED updateStackingParentForZOrderLists(0); #endif if (m_posZOrderList) m_posZOrderList->clear(); if (m_negZOrderList) m_negZOrderList->clear(); m_zOrderListsDirty = true; if (!renderer()->documentBeingDestroyed()) compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree); }
void PaintLayerStackingNode::dirtyZOrderLists() { #if DCHECK_IS_ON() DCHECK(m_layerListMutationAllowed); #endif DCHECK(isStackingContext()); #if ENABLE(ASSERT) updateStackingParentForZOrderLists(0); #endif if (m_posZOrderList) m_posZOrderList->clear(); if (m_negZOrderList) m_negZOrderList->clear(); m_zOrderListsDirty = true; if (!layoutObject()->documentBeingDestroyed()) compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree); }
void PaintLayerStackingNode::collectLayers( std::unique_ptr<Vector<PaintLayerStackingNode*>>& posBuffer, std::unique_ptr<Vector<PaintLayerStackingNode*>>& negBuffer) { if (layer()->isInTopLayer()) return; if (isStacked()) { std::unique_ptr<Vector<PaintLayerStackingNode*>>& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; if (!buffer) buffer = wrapUnique(new Vector<PaintLayerStackingNode*>); buffer->append(this); } if (!isStackingContext()) { for (PaintLayer* child = layer()->firstChild(); child; child = child->nextSibling()) child->stackingNode()->collectLayers(posBuffer, negBuffer); } }
void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle) { bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false; EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE; int oldZIndex = oldStyle ? oldStyle->zIndex() : 0; // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could // likely be folded along with the rest. bool isStackingContext = this->isStackingContext(); if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == zIndex()) return; dirtyStackingContainerZOrderLists(); if (isStackingContainer()) dirtyZOrderLists(); else clearZOrderLists(); compositor()->setNeedsUpdateCompositingRequirementsState(); }
void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer) { if (layer()->isInTopLayer()) return; layer()->updateDescendantDependentFlags(); if (!isNormalFlowOnly()) { OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; if (!buffer) buffer = adoptPtr(new Vector<RenderLayerStackingNode*>); buffer->append(this); } if (!isStackingContext()) { for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child) child->stackingNode()->collectLayers(posBuffer, negBuffer); } } }
// FIXME: Rename shouldBeNormalFlowOnly to something more accurate now that CSS // 2.1 defines the term "normal flow". bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const { return !isStackingContext() && !renderer()->isPositioned(); }