| Index: Source/core/rendering/RenderLayer.cpp
|
| diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
|
| index 26f38033c20aa1af9f8a188b5dedb715329b760e..ff7f6731d270830ec0fd86a3cbcb862b15549fcc 100644
|
| --- a/Source/core/rendering/RenderLayer.cpp
|
| +++ b/Source/core/rendering/RenderLayer.cpp
|
| @@ -134,8 +134,8 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
|
| , m_hasOutOfFlowPositionedDescendantDirty(true)
|
| , m_hasUnclippedDescendant(false)
|
| , m_needsCompositedScrolling(false)
|
| - , m_descendantsAreContiguousInStackingOrder(false)
|
| - , m_descendantsAreContiguousInStackingOrderDirty(true)
|
| + , m_canBePromotedToStackingContainer(false)
|
| + , m_canBePromotedToStackingContainerDirty(true)
|
| , m_isRootLayer(renderer->isRenderView())
|
| , m_usedTransparency(false)
|
| , m_paintingInsideReflection(false)
|
| @@ -505,153 +505,65 @@ bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
|
| return settings && settings->acceleratedCompositingForOverflowScrollEnabled();
|
| }
|
|
|
| -// If we are a stacking container, then this function will determine if our
|
| -// descendants for a contiguous block in stacking order. This is required in
|
| -// order for an element to be safely promoted to a stacking container. It is safe
|
| -// to become a stacking container if this change would not alter the stacking
|
| -// order of layers on the page. That can only happen if a non-descendant appear
|
| -// between us and our descendants in stacking order. Here's an example:
|
| -//
|
| -// this
|
| -// / | \.
|
| -// A B C
|
| -// /\ | /\.
|
| -// 0 -8 D 2 7
|
| -// |
|
| -// 5
|
| -//
|
| -// I've labeled our normal flow descendants A, B, C, and D, our stacking
|
| -// container descendants with their z indices, and us with 'this' (we're a
|
| -// stacking container and our zIndex doesn't matter here). These nodes appear in
|
| -// three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal
|
| -// flow layers don't overlap). So if we arrange these lists in order we get our
|
| -// stacking order:
|
| -//
|
| -// [-8], [A-D], [0, 2, 5, 7]--> pos z-order.
|
| -// | |
|
| -// Neg z-order. <-+ +--> Normal flow descendants.
|
| -//
|
| -// We can then assign new, 'stacking' order indices to these elements as follows:
|
| -//
|
| -// [-8], [A-D], [0, 2, 5, 7]
|
| -// 'Stacking' indices: -1 0 1 2 3 4
|
| -//
|
| -// Note that the normal flow descendants can share an index because they don't
|
| -// stack/overlap. Now our problem becomes very simple: a layer can safely become
|
| -// a stacking container if the stacking-order indices of it and its descendants
|
| -// appear in a contiguous block in the list of stacking indices. This problem
|
| -// can be solved very efficiently by calculating the min/max stacking indices in
|
| -// the subtree, and the number stacking container descendants. Once we have this
|
| -// information, we know that the subtree's indices form a contiguous block if:
|
| -//
|
| -// maxStackIndex - minStackIndex == numSCDescendants
|
| -//
|
| -// So for node A in the example above we would have:
|
| -// maxStackIndex = 1
|
| -// minStackIndex = -1
|
| -// numSCDecendants = 2
|
| -//
|
| -// and so,
|
| -// maxStackIndex - minStackIndex == numSCDescendants
|
| -// ===> 1 - (-1) == 2
|
| -// ===> 2 == 2
|
| -//
|
| -// Since this is true, A can safely become a stacking container.
|
| -// Now, for node C we have:
|
| -//
|
| -// maxStackIndex = 4
|
| -// minStackIndex = 0 <-- because C has stacking index 0.
|
| -// numSCDecendants = 2
|
| -//
|
| -// and so,
|
| -// maxStackIndex - minStackIndex == numSCDescendants
|
| -// ===> 4 - 0 == 2
|
| -// ===> 4 == 2
|
| -//
|
| -// Since this is false, C cannot be safely promoted to a stacking container. This
|
| -// happened because of the elements with z-index 5 and 0. Now if 5 had been a
|
| -// child of C rather than D, and A had no child with Z index 0, we would have had:
|
| -//
|
| -// maxStackIndex = 3
|
| -// minStackIndex = 0 <-- because C has stacking index 0.
|
| -// numSCDecendants = 3
|
| -//
|
| -// and so,
|
| -// maxStackIndex - minStackIndex == numSCDescendants
|
| -// ===> 3 - 0 == 3
|
| -// ===> 3 == 3
|
| -//
|
| -// And we would conclude that C could be promoted.
|
| -void RenderLayer::updateDescendantsAreContiguousInStackingOrder()
|
| +// 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 RenderLayer::updateCanBeStackingContainer()
|
| {
|
| - if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext() || !acceleratedCompositingForOverflowScrollEnabled())
|
| + TRACE_EVENT0("blink_rendering", "RenderLayer::updateCanBeStackingContainer");
|
| +
|
| + if (isStackingContext() || !m_canBePromotedToStackingContainerDirty || !acceleratedCompositingForOverflowScrollEnabled())
|
| return;
|
|
|
| - OwnPtr<Vector<RenderLayer*> > posZOrderList;
|
| - OwnPtr<Vector<RenderLayer*> > negZOrderList;
|
| - rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList);
|
| + FrameView* frameView = renderer()->view()->frameView();
|
| + if (!frameView || !frameView->containsScrollableArea(this))
|
| + return;
|
|
|
| - // Create a reverse lookup.
|
| - HashMap<const RenderLayer*, int> lookup;
|
| + RenderLayer* ancestorStackingContext = this->ancestorStackingContext();
|
| + if (!ancestorStackingContext)
|
| + return;
|
|
|
| - if (negZOrderList) {
|
| - int stackingOrderIndex = -1;
|
| - size_t listSize = negZOrderList->size();
|
| - for (size_t i = 0; i < listSize; ++i) {
|
| - RenderLayer* currentLayer = negZOrderList->at(listSize - i - 1);
|
| - if (!currentLayer->isStackingContext())
|
| - continue;
|
| - lookup.set(currentLayer, stackingOrderIndex--);
|
| - }
|
| - }
|
| + OwnPtr<Vector<RenderLayer*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayer*>);
|
| + OwnPtr<Vector<RenderLayer*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayer*>);
|
| + OwnPtr<Vector<RenderLayer*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayer*>);
|
| + OwnPtr<Vector<RenderLayer*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayer*>);
|
|
|
| - if (posZOrderList) {
|
| - size_t listSize = posZOrderList->size();
|
| - int stackingOrderIndex = 1;
|
| - for (size_t i = 0; i < listSize; ++i) {
|
| - RenderLayer* currentLayer = posZOrderList->at(i);
|
| - if (!currentLayer->isStackingContext())
|
| - continue;
|
| - lookup.set(currentLayer, stackingOrderIndex++);
|
| - }
|
| - }
|
| + collectBeforePromotionZOrderList(ancestorStackingContext, posZOrderListBeforePromote, negZOrderListBeforePromote);
|
| + collectAfterPromotionZOrderList(ancestorStackingContext, posZOrderListAfterPromote, negZOrderListAfterPromote);
|
|
|
| - int minIndex = 0;
|
| - int maxIndex = 0;
|
| - int count = 0;
|
| - bool firstIteration = true;
|
| - updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, maxIndex, count, firstIteration);
|
| + size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size());
|
|
|
| - m_descendantsAreContiguousInStackingOrderDirty = false;
|
| -}
|
| + m_canBePromotedToStackingContainerDirty = false;
|
| + m_canBePromotedToStackingContainer = false;
|
|
|
| -void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const HashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& count, bool firstIteration)
|
| -{
|
| - if (isStackingContext() && !firstIteration) {
|
| - if (lookup.contains(this)) {
|
| - minIndex = std::min(minIndex, lookup.get(this));
|
| - maxIndex = std::max(maxIndex, lookup.get(this));
|
| - count++;
|
| - }
|
| - return;
|
| - }
|
| + const RenderLayer* layerAfterPromote = 0;
|
| + for (size_t i = 0; i < maxIndex && layerAfterPromote != this; ++i) {
|
| + const RenderLayer* layerBeforePromote = i < negZOrderListBeforePromote->size()
|
| + ? negZOrderListBeforePromote->at(i)
|
| + : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size());
|
| + layerAfterPromote = i < negZOrderListAfterPromote->size()
|
| + ? negZOrderListAfterPromote->at(i)
|
| + : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size());
|
|
|
| - for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
|
| - int childMinIndex = 0;
|
| - int childMaxIndex = 0;
|
| - int childCount = 0;
|
| - child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, childMinIndex, childMaxIndex, childCount, false);
|
| - if (childCount) {
|
| - count += childCount;
|
| - minIndex = std::min(minIndex, childMinIndex);
|
| - maxIndex = std::max(maxIndex, childMaxIndex);
|
| - }
|
| + if (layerBeforePromote != layerAfterPromote && (layerAfterPromote != this || renderer()->hasBackground()))
|
| + return;
|
| }
|
|
|
| - if (!isStackingContext()) {
|
| - m_descendantsAreContiguousInStackingOrder = (maxIndex - minIndex) == count;
|
| - m_descendantsAreContiguousInStackingOrderDirty = false;
|
| + layerAfterPromote = 0;
|
| + for (size_t i = 0; i < maxIndex && layerAfterPromote != this; ++i) {
|
| + const RenderLayer* layerBeforePromote = i < posZOrderListBeforePromote->size()
|
| + ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1)
|
| + : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1);
|
| + layerAfterPromote = i < posZOrderListAfterPromote->size()
|
| + ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1)
|
| + : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1);
|
| +
|
| + if (layerBeforePromote != layerAfterPromote && layerAfterPromote != this)
|
| + return;
|
| }
|
| +
|
| + m_canBePromotedToStackingContainer = true;
|
| }
|
|
|
| static inline bool isPositionedContainer(const RenderLayer* layer)
|
| @@ -1085,8 +997,8 @@ bool RenderLayer::canBeStackingContainer() const
|
| if (isStackingContext() || !ancestorStackingContainer())
|
| return true;
|
|
|
| - ASSERT(!m_descendantsAreContiguousInStackingOrderDirty);
|
| - return m_descendantsAreContiguousInStackingOrder;
|
| + ASSERT(!m_canBePromotedToStackingContainerDirty);
|
| + return m_canBePromotedToStackingContainer;
|
| }
|
|
|
| void RenderLayer::setHasVisibleContent()
|
| @@ -2067,31 +1979,27 @@ bool RenderLayer::needsCompositedScrolling() const
|
|
|
| void RenderLayer::updateNeedsCompositedScrolling()
|
| {
|
| - if (RenderLayer* ancestor = ancestorStackingContext())
|
| - ancestor->updateDescendantsAreContiguousInStackingOrder();
|
| + updateCanBeStackingContainer();
|
|
|
| bool needsCompositedScrolling = false;
|
| + updateDescendantDependentFlags();
|
|
|
| - FrameView* frameView = renderer()->view()->frameView();
|
| - if (frameView && frameView->containsScrollableArea(this)) {
|
| - updateDescendantDependentFlags();
|
| -
|
| - bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEnabled()
|
| - && canBeStackingContainer()
|
| - && !hasUnclippedDescendant();
|
| + ASSERT(renderer()->view()->frameView() && renderer()->view()->frameView()->containsScrollableArea(this));
|
| + bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEnabled()
|
| + && canBeStackingContainer()
|
| + && !hasUnclippedDescendant();
|
|
|
| #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
|
| - needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style()->useTouchOverflowScrolling();
|
| + needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style()->useTouchOverflowScrolling();
|
| #else
|
| - needsCompositedScrolling = forceUseCompositedScrolling;
|
| + needsCompositedScrolling = forceUseCompositedScrolling;
|
| #endif
|
| - // We gather a boolean value for use with Google UMA histograms to
|
| - // quantify the actual effects of a set of patches attempting to
|
| - // relax composited scrolling requirements, thereby increasing the
|
| - // number of composited overflow divs.
|
| - if (acceleratedCompositingForOverflowScrollEnabled())
|
| - HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrolling", needsCompositedScrolling, 2);
|
| - }
|
| + // We gather a boolean value for use with Google UMA histograms to
|
| + // quantify the actual effects of a set of patches attempting to
|
| + // relax composited scrolling requirements, thereby increasing the
|
| + // number of composited overflow divs.
|
| + if (acceleratedCompositingForOverflowScrollEnabled())
|
| + HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrolling", needsCompositedScrolling, 2);
|
|
|
| setNeedsCompositedScrolling(needsCompositedScrolling);
|
| }
|
| @@ -5626,7 +5534,7 @@ void RenderLayer::dirtyZOrderLists()
|
| m_negZOrderList->clear();
|
| m_zOrderListsDirty = true;
|
|
|
| - m_descendantsAreContiguousInStackingOrderDirty = true;
|
| + m_canBePromotedToStackingContainerDirty = true;
|
|
|
| if (!renderer()->documentBeingDestroyed()) {
|
| compositor()->setNeedsUpdateCompositingRequirementsState();
|
|
|