static bool shouldCreateSubsequence(const PaintLayer& paintLayer, GraphicsContext& context, const PaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) { // Caching is not needed during printing. if (context.printing()) return false; // Don't create subsequence for a composited layer because if it can be cached, // we can skip the whole painting in GraphicsLayer::paint() with CachedDisplayItemList. // This also avoids conflict of PaintLayer::previousXXX() when paintLayer is composited // scrolling and is painted twice for GraphicsLayers of container and scrolling contents. if (paintLayer.compositingState() == PaintsIntoOwnBacking) return false; // Don't create subsequence during special painting to avoid cache conflict with normal painting. if (paintingInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers) return false; if (paintFlags & (PaintLayerPaintingReflection | PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingOverlayScrollbars | PaintLayerUncachedClipRects)) return false; // Create subsequence for only stacking contexts whose painting are atomic. if (!paintLayer.stackingNode()->isStackingContext()) return false; // The layer doesn't have children. Subsequence caching is not worth because normally the actual painting will be cheap. if (!PaintLayerStackingNodeIterator(*paintLayer.stackingNode(), AllChildren).next()) return false; return true; }
void GraphicsLayerTreeBuilder::rebuild(PaintLayer& layer, AncestorInfo info) { // Make the layer compositing if necessary, and set up clipping and content layers. // Note that we can only do work here that is independent of whether the descendant layers // have been processed. computeCompositingRequirements() will already have done the paint invalidation if necessary. layer.stackingNode()->updateLayerListsIfNeeded(); const bool hasCompositedLayerMapping = layer.hasCompositedLayerMapping(); CompositedLayerMapping* currentCompositedLayerMapping = layer.compositedLayerMapping(); // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers. // Otherwise children continue to append to the child list of the enclosing layer. GraphicsLayerVector layerChildren; AncestorInfo infoForChildren(info); if (hasCompositedLayerMapping) { infoForChildren.childLayersOfEnclosingCompositedLayer = &layerChildren; infoForChildren.enclosingCompositedLayer = &layer; } #if ENABLE(ASSERT) LayerListMutationDetector mutationChecker(layer.stackingNode()); #endif if (layer.stackingNode()->isStackingContext()) { PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NegativeZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer()) infoForChildren.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->foregroundLayer()); } PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NormalFlowChildren | PositiveZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); if (hasCompositedLayerMapping) { bool parented = false; if (layer.layoutObject()->isLayoutPart()) parented = PaintLayerCompositor::attachFrameContentLayersToIframeLayer(toLayoutPart(layer.layoutObject())); if (!parented) currentCompositedLayerMapping->setSublayers(layerChildren); if (shouldAppendLayer(layer)) info.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->childForSuperlayers()); } if (layer.scrollParent() && layer.scrollParent()->hasCompositedLayerMapping() && layer.scrollParent()->compositedLayerMapping()->needsToReparentOverflowControls() && layer.scrollParent()->getScrollableArea()->topmostScrollChild() == &layer) info.childLayersOfEnclosingCompositedLayer->append(layer.scrollParent()->compositedLayerMapping()->detachLayerForOverflowControls(*info.enclosingCompositedLayer)); }
static void checkIsClippingStackingContextAndContainer(LayoutBoxModelObject& obj) { EXPECT_TRUE(obj.canContainFixedPositionObjects()); EXPECT_TRUE(obj.hasClipRelatedProperty()); EXPECT_TRUE(obj.style()->containsPaint()); // TODO(leviw): Ideally, we wouldn't require a paint layer to handle the clipping // and stacking performed by paint containment. ASSERT(obj.layer()); PaintLayer* layer = obj.layer(); EXPECT_TRUE(layer->stackingNode() && layer->stackingNode()->isStackingContext()); }
void PaintLayerStackingNode::rebuildZOrderLists() { #if DCHECK_IS_ON() DCHECK(m_layerListMutationAllowed); #endif DCHECK(isDirtyStackingContext()); for (PaintLayer* child = layer()->firstChild(); child; child = child->nextSibling()) child->stackingNode()->collectLayers(m_posZOrderList, m_negZOrderList); // Sort the two lists. if (m_posZOrderList) std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex); if (m_negZOrderList) std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex); // Append layers for top layer elements after normal layer collection, to // ensure they are on top regardless of z-indexes. The layoutObjects of top // layer elements are children of the view, sorted in top layer stacking // order. if (layer()->isRootLayer()) { LayoutBlockFlow* rootBlock = layoutObject()->view(); // If the viewport is paginated, everything (including "top-layer" elements) // gets redirected to the flow thread. So that's where we have to look, in // that case. if (LayoutBlockFlow* multiColumnFlowThread = rootBlock->multiColumnFlowThread()) rootBlock = multiColumnFlowThread; for (LayoutObject* child = rootBlock->firstChild(); child; child = child->nextSibling()) { Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0; if (childElement && childElement->isInTopLayer()) { PaintLayer* layer = toLayoutBoxModelObject(child)->layer(); // Create the buffer if it doesn't exist yet. if (!m_posZOrderList) m_posZOrderList = wrapUnique(new Vector<PaintLayerStackingNode*>); m_posZOrderList->append(layer->stackingNode()); } } } #if ENABLE(ASSERT) updateStackingParentForZOrderLists(this); #endif m_zOrderListsDirty = false; }
PaintLayerStackingNode* PaintLayerStackingNodeReverseIterator::next() { if (m_remainingChildren & NegativeZOrderChildren) { Vector<PaintLayerStackingNode*>* negZOrderList = m_root.negZOrderList(); if (negZOrderList && m_index >= 0) return negZOrderList->at(m_index--); m_remainingChildren &= ~NegativeZOrderChildren; setIndexToLastItem(); } if (m_remainingChildren & NormalFlowChildren) { for (; m_currentNormalFlowChild; m_currentNormalFlowChild = m_currentNormalFlowChild->previousSibling()) { if (!m_currentNormalFlowChild->stackingNode()->isStacked() && !m_currentNormalFlowChild->isReflection()) { PaintLayer* normalFlowChild = m_currentNormalFlowChild; m_currentNormalFlowChild = m_currentNormalFlowChild->previousSibling(); return normalFlowChild->stackingNode(); } } m_remainingChildren &= ~NormalFlowChildren; setIndexToLastItem(); } if (m_remainingChildren & PositiveZOrderChildren) { Vector<PaintLayerStackingNode*>* posZOrderList = m_root.posZOrderList(); if (posZOrderList && m_index >= 0) return posZOrderList->at(m_index--); m_remainingChildren &= ~PositiveZOrderChildren; setIndexToLastItem(); } return 0; }
PaintLayerStackingNode* PaintLayerStackingNode::ancestorStackingContextNode() const { for (PaintLayer* ancestor = layer()->parent(); ancestor; ancestor = ancestor->parent()) { PaintLayerStackingNode* stackingNode = ancestor->stackingNode(); if (stackingNode->isStackingContext()) return stackingNode; } return 0; }
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); } }
PaintLayerStackingNode* PaintLayerStackingNodeIterator::next() { if (m_remainingChildren & NegativeZOrderChildren) { Vector<PaintLayerStackingNode*>* negZOrderList = m_root.negZOrderList(); if (negZOrderList && m_index < negZOrderList->size()) return negZOrderList->at(m_index++); m_index = 0; m_remainingChildren &= ~NegativeZOrderChildren; } if (m_remainingChildren & NormalFlowChildren) { for (; m_currentNormalFlowChild; m_currentNormalFlowChild = m_currentNormalFlowChild->nextSibling()) { if (!m_currentNormalFlowChild->stackingNode()->isStacked() && !m_currentNormalFlowChild->isReflection()) { PaintLayer* normalFlowChild = m_currentNormalFlowChild; m_currentNormalFlowChild = m_currentNormalFlowChild->nextSibling(); return normalFlowChild->stackingNode(); } } // We reset the iterator in case we reuse it. m_currentNormalFlowChild = m_root.layer()->firstChild(); m_remainingChildren &= ~NormalFlowChildren; } if (m_remainingChildren & PositiveZOrderChildren) { Vector<PaintLayerStackingNode*>* posZOrderList = m_root.posZOrderList(); if (posZOrderList && m_index < posZOrderList->size()) return posZOrderList->at(m_index++); m_index = 0; m_remainingChildren &= ~PositiveZOrderChildren; } return 0; }