This source file includes following definitions.
- m_stackingParent
- compareZIndex
- compositor
- dirtyNormalFlowListCanBePromotedToStackingContainer
- dirtySiblingStackingNodeCanBePromotedToStackingContainer
- dirtyZOrderLists
- dirtyStackingContainerZOrderLists
- dirtyNormalFlowList
- rebuildZOrderLists
- rebuildZOrderLists
- updateNormalFlowList
- collectLayers
- isInStackingParentZOrderLists
- isInStackingParentNormalFlowList
- updateStackingParentForZOrderLists
- updateStackingParentForNormalFlowList
- updateLayerListsIfNeeded
- updateStackingNodesAfterStyleChange
- shouldBeNormalFlowOnly
- shouldBeNormalFlowOnlyIgnoringCompositedScrolling
- updateIsNormalFlowOnly
- needsToBeStackingContainer
- updateDescendantsAreContiguousInStackingOrder
- collectBeforePromotionZOrderList
- collectAfterPromotionZOrderList
- computePaintOrderList
- descendantsAreContiguousInStackingOrder
- setNeedsToBeStackingContainer
- ancestorStackingContainerNode
- ancestorStackingNode
- renderer
#include "config.h"
#include "core/rendering/RenderLayerStackingNode.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "public/platform/Platform.h"
namespace WebCore {
RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer)
: m_layer(layer)
, m_descendantsAreContiguousInStackingOrder(false)
, m_descendantsAreContiguousInStackingOrderDirty(true)
, m_normalFlowListDirty(true)
, m_needsToBeStackingContainer(false)
, m_needsToBeStackingContainerHasBeenRecorded(false)
#if !ASSERT_DISABLED
, m_layerListMutationAllowed(true)
, m_stackingParent(0)
#endif
{
m_isNormalFlowOnly = shouldBeNormalFlowOnly();
m_zOrderListsDirty = isStackingContainer();
}
RenderLayerStackingNode::~RenderLayerStackingNode()
{
#if !ASSERT_DISABLED
if (!renderer()->documentBeingDestroyed()) {
ASSERT(!isInStackingParentZOrderLists());
ASSERT(!isInStackingParentNormalFlowList());
updateStackingParentForZOrderLists(0);
updateStackingParentForNormalFlowList(0);
}
#endif
}
static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStackingNode* second)
{
return first->zIndex() < second->zIndex();
}
RenderLayerCompositor* RenderLayerStackingNode::compositor() const
{
if (!renderer()->view())
return 0;
return renderer()->view()->compositor();
}
void RenderLayerStackingNode::dirtyNormalFlowListCanBePromotedToStackingContainer()
{
m_descendantsAreContiguousInStackingOrderDirty = true;
if (m_normalFlowListDirty || !normalFlowList())
return;
for (size_t index = 0; index < normalFlowList()->size(); ++index)
normalFlowList()->at(index)->dirtyNormalFlowListCanBePromotedToStackingContainer();
}
void RenderLayerStackingNode::dirtySiblingStackingNodeCanBePromotedToStackingContainer()
{
RenderLayerStackingNode* stackingNode = ancestorStackingNode();
if (!stackingNode)
return;
if (!stackingNode->zOrderListsDirty() && stackingNode->posZOrderList()) {
for (size_t index = 0; index < stackingNode->posZOrderList()->size(); ++index)
stackingNode->posZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
}
stackingNode->dirtyNormalFlowListCanBePromotedToStackingContainer();
if (!stackingNode->zOrderListsDirty() && stackingNode->negZOrderList()) {
for (size_t index = 0; index < stackingNode->negZOrderList()->size(); ++index)
stackingNode->negZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
}
}
void RenderLayerStackingNode::dirtyZOrderLists()
{
ASSERT(m_layerListMutationAllowed);
ASSERT(isStackingContainer());
#if !ASSERT_DISABLED
updateStackingParentForZOrderLists(0);
#endif
if (m_posZOrderList)
m_posZOrderList->clear();
if (m_negZOrderList)
m_negZOrderList->clear();
m_zOrderListsDirty = true;
m_descendantsAreContiguousInStackingOrderDirty = true;
if (!renderer()->documentBeingDestroyed()) {
compositor()->setNeedsUpdateCompositingRequirementsState();
compositor()->setCompositingLayersNeedRebuild();
if (renderer()->acceleratedCompositingForOverflowScrollEnabled())
compositor()->setNeedsToRecomputeCompositingRequirements();
}
}
void RenderLayerStackingNode::dirtyStackingContainerZOrderLists()
{
dirtySiblingStackingNodeCanBePromotedToStackingContainer();
RenderLayerStackingNode* stackingContainerNode = ancestorStackingContainerNode();
if (stackingContainerNode)
stackingContainerNode->dirtyZOrderLists();
RenderLayerStackingNode* stackingNode = ancestorStackingNode();
if (stackingNode && stackingNode != stackingContainerNode)
stackingNode->dirtyZOrderLists();
}
void RenderLayerStackingNode::dirtyNormalFlowList()
{
ASSERT(m_layerListMutationAllowed);
#if !ASSERT_DISABLED
updateStackingParentForNormalFlowList(0);
#endif
if (m_normalFlowList)
m_normalFlowList->clear();
m_normalFlowListDirty = true;
if (!renderer()->documentBeingDestroyed()) {
compositor()->setCompositingLayersNeedRebuild();
if (renderer()->acceleratedCompositingForOverflowScrollEnabled())
compositor()->setNeedsToRecomputeCompositingRequirements();
}
}
void RenderLayerStackingNode::rebuildZOrderLists()
{
ASSERT(m_layerListMutationAllowed);
ASSERT(isDirtyStackingContainer());
rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
#if !ASSERT_DISABLED
updateStackingParentForZOrderLists(this);
#endif
m_zOrderListsDirty = false;
}
void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList,
OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer,
CollectLayersBehavior collectLayersBehavior)
{
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
child->stackingNode()->collectLayers(posZOrderList, negZOrderList, nodeToForceAsStackingContainer, collectLayersBehavior);
}
if (posZOrderList)
std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
if (negZOrderList)
std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
if (layer()->isRootLayer()) {
RenderObject* view = renderer()->view();
for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0;
if (childElement && childElement->isInTopLayer()) {
RenderLayer* layer = toRenderLayerModelObject(child)->layer();
if (!posZOrderList)
posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>);
posZOrderList->append(layer->stackingNode());
}
}
}
}
void RenderLayerStackingNode::updateNormalFlowList()
{
if (!m_normalFlowListDirty)
return;
ASSERT(m_layerListMutationAllowed);
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
if (child->stackingNode()->isNormalFlowOnly() && (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)) {
if (!m_normalFlowList)
m_normalFlowList = adoptPtr(new Vector<RenderLayerStackingNode*>);
m_normalFlowList->append(child->stackingNode());
}
}
#if !ASSERT_DISABLED
updateStackingParentForNormalFlowList(this);
#endif
m_normalFlowListDirty = false;
}
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;
}
if (!isNormalFlow && !layer()->isOutOfFlowRenderFlowThread()) {
OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
if (!buffer)
buffer = adoptPtr(new Vector<RenderLayerStackingNode*>);
buffer->append(this);
}
if (!isStacking) {
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
child->stackingNode()->collectLayers(posBuffer, negBuffer, nodeToForceAsStackingContainer, collectLayersBehavior);
}
}
}
#if !ASSERT_DISABLED
bool RenderLayerStackingNode::isInStackingParentZOrderLists() const
{
if (!m_stackingParent || m_stackingParent->zOrderListsDirty())
return false;
if (m_stackingParent->posZOrderList() && m_stackingParent->posZOrderList()->find(this) != kNotFound)
return true;
if (m_stackingParent->negZOrderList() && m_stackingParent->negZOrderList()->find(this) != kNotFound)
return true;
return false;
}
bool RenderLayerStackingNode::isInStackingParentNormalFlowList() const
{
if (!m_stackingParent || m_stackingParent->normalFlowListDirty())
return false;
return (m_stackingParent->normalFlowList() && m_stackingParent->normalFlowList()->find(this) != kNotFound);
}
void RenderLayerStackingNode::updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent)
{
if (m_posZOrderList) {
for (size_t i = 0; i < m_posZOrderList->size(); ++i)
m_posZOrderList->at(i)->setStackingParent(stackingParent);
}
if (m_negZOrderList) {
for (size_t i = 0; i < m_negZOrderList->size(); ++i)
m_negZOrderList->at(i)->setStackingParent(stackingParent);
}
}
void RenderLayerStackingNode::updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent)
{
if (m_normalFlowList) {
for (size_t i = 0; i < m_normalFlowList->size(); ++i)
m_normalFlowList->at(i)->setStackingParent(stackingParent);
}
}
#endif
void RenderLayerStackingNode::updateLayerListsIfNeeded()
{
updateZOrderLists();
updateNormalFlowList();
if (!layer()->reflectionInfo())
return;
RenderLayer* reflectionLayer = layer()->reflectionInfo()->reflectionLayer();
reflectionLayer->stackingNode()->updateZOrderLists();
reflectionLayer->stackingNode()->updateNormalFlowList();
}
void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle)
{
bool wasStackingContext = oldStyle ? !oldStyle->hasAutoZIndex() : false;
EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
int oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
bool isStackingContext = this->isStackingContext();
if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == zIndex())
return;
dirtyStackingContainerZOrderLists();
if (isStackingContainer())
dirtyZOrderLists();
else
clearZOrderLists();
compositor()->setNeedsUpdateCompositingRequirementsState();
}
bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const
{
return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !layer()->needsCompositedScrolling();
}
bool RenderLayerStackingNode::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const
{
const bool couldBeNormalFlow = renderer()->hasOverflowClip()
|| renderer()->hasReflection()
|| renderer()->hasMask()
|| renderer()->isCanvas()
|| renderer()->isVideo()
|| renderer()->isEmbeddedObject()
|| renderer()->isRenderIFrame()
|| (renderer()->style()->specifiesColumns() && !layer()->isRootLayer());
const bool preventsElementFromBeingNormalFlow = renderer()->isPositioned()
|| renderer()->hasTransform()
|| renderer()->hasClipPath()
|| renderer()->hasFilter()
|| renderer()->hasBlendMode()
|| layer()->isTransparent();
return couldBeNormalFlow && !preventsElementFromBeingNormalFlow;
}
void RenderLayerStackingNode::updateIsNormalFlowOnly()
{
bool isNormalFlowOnly = shouldBeNormalFlowOnly();
if (isNormalFlowOnly == this->isNormalFlowOnly())
return;
m_isNormalFlowOnly = isNormalFlowOnly;
if (RenderLayer* p = layer()->parent())
p->stackingNode()->dirtyNormalFlowList();
dirtyStackingContainerZOrderLists();
}
bool RenderLayerStackingNode::needsToBeStackingContainer() const
{
return layer()->scrollableArea() && layer()->scrollableArea()->adjustForForceCompositedScrollingMode(m_needsToBeStackingContainer);
}
void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder()
{
TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder");
if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !renderer()->acceleratedCompositingForOverflowScrollEnabled())
return;
if (!layer()->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;
}
void RenderLayerStackingNode::collectBeforePromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
{
ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, OnlyStackingContextsCanBeStackingContainers);
const RenderLayer* currentLayer = layer();
const RenderLayer* positionedAncestor = currentLayer->parent();
while (positionedAncestor && !positionedAncestor->isPositionedContainer() && !positionedAncestor->stackingNode()->isStackingContext())
positionedAncestor = positionedAncestor->parent();
if (positionedAncestor && (!positionedAncestor->isPositionedContainer() || positionedAncestor->stackingNode()->isStackingContext()))
positionedAncestor = 0;
if (!posZOrderList)
posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>());
else if (posZOrderList->find(this) != kNotFound)
return;
if (!positionedAncestor) {
posZOrderList->prepend(this);
return;
}
for (size_t index = 0; index < posZOrderList->size(); index++) {
if (posZOrderList->at(index)->layer() == positionedAncestor) {
posZOrderList->insert(index + 1, this);
return;
}
}
}
void RenderLayerStackingNode::collectAfterPromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
{
ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, ForceLayerToStackingContainer);
}
void RenderLayerStackingNode::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list)
{
OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderList;
OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderList;
RenderLayerStackingNode* stackingNode = ancestorStackingNode();
if (!stackingNode)
return;
switch (type) {
case BeforePromote:
collectBeforePromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
break;
case AfterPromote:
collectAfterPromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
break;
}
if (negZOrderList) {
for (size_t index = 0; index < negZOrderList->size(); ++index)
list.append(negZOrderList->at(index)->renderer()->node());
}
if (posZOrderList) {
for (size_t index = 0; index < posZOrderList->size(); ++index)
list.append(posZOrderList->at(index)->renderer()->node());
}
}
bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const
{
if (isStackingContext() || !ancestorStackingContainerNode())
return true;
ASSERT(!m_descendantsAreContiguousInStackingOrderDirty);
return m_descendantsAreContiguousInStackingOrder;
}
bool RenderLayerStackingNode::setNeedsToBeStackingContainer(bool needsToBeStackingContainer)
{
if (this->needsToBeStackingContainer() == needsToBeStackingContainer)
return false;
if (renderer()->acceleratedCompositingForOverflowScrollEnabled() && !m_needsToBeStackingContainerHasBeenRecorded) {
blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", NeedsToBeStackingContainerBucket, CompositedScrollingHistogramMax);
m_needsToBeStackingContainerHasBeenRecorded = true;
}
m_needsToBeStackingContainer = needsToBeStackingContainer;
return true;
}
RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContainerNode() const
{
RenderLayer* ancestor = layer()->parent();
while (ancestor && !ancestor->stackingNode()->isStackingContainer())
ancestor = ancestor->parent();
if (ancestor)
return ancestor->stackingNode();
return 0;
}
RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const
{
RenderLayer* ancestor = layer()->parent();
while (ancestor && !ancestor->stackingNode()->isStackingContext())
ancestor = ancestor->parent();
if (ancestor)
return ancestor->stackingNode();
return 0;
}
RenderLayerModelObject* RenderLayerStackingNode::renderer() const
{
return m_layer->renderer();
}
}