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;
}
Esempio n. 4
0
// 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);
}
Esempio n. 7
0
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);
}
Esempio n. 8
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);
  }
}
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();
}