Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1249)

Unified Diff: Source/core/rendering/RenderLayer.cpp

Issue 14741004: NOT FOR REVIEW - Update comp-scrolling state at a well defined point in the pipeline. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Added annotations describing how this patch will be split. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerCompositor.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderLayer.cpp
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
index dffb6999ea46b40e65a624eb5517db9e241a1a2c..d3fe9e617cccd35ad35c8460104e2f2af2a763db 100644
--- a/Source/core/rendering/RenderLayer.cpp
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -69,6 +69,8 @@
#include "core/page/UseCounter.h"
#include "core/page/animation/AnimationController.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
+// PATCH 2
+#include "core/platform/chromium/TraceEvent.h"
#include "core/platform/FloatConversion.h"
#include "core/platform/HistogramSupport.h"
#include "core/platform/PlatformMouseEvent.h"
@@ -113,6 +115,8 @@
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include <wtf/MemoryInstrumentationVector.h>
#include <wtf/StdLibExtras.h>
+// PATCH 2
+#include <wtf/TemporaryChange.h>
#include <wtf/text/CString.h>
#include <wtf/UnusedParam.h>
@@ -143,10 +147,12 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
, m_hasSelfPaintingLayerDescendant(false)
, m_hasSelfPaintingLayerDescendantDirty(false)
, m_hasOutOfFlowPositionedDescendant(false)
- , m_hasOutOfFlowPositionedDescendantDirty(true)
+ // PATCH 1
+ , m_forceNeedsCompositedScrolling(DoNotForceCompositedScrolling)
, m_needsCompositedScrolling(false)
- , m_descendantsAreContiguousInStackingOrder(false)
- , m_descendantsAreContiguousInStackingOrderDirty(true)
+ // PATCH 3
+ , m_canBePromotedToStackingContainer(false)
+ , m_canBePromotedToStackingContainerDirty(true)
, m_isRootLayer(renderer->isRenderView())
, m_usedTransparency(false)
, m_paintingInsideReflection(false)
@@ -482,168 +488,196 @@ bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
&& renderer()->frame()->page()->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
+// PATCH 3
+static inline bool isPositionedContainer(const RenderLayer* layer)
+{
+ // FIXME: This is not in sync with containingBlock.
+ // RenderObject::canContainFixedPositionedObject() should probably be used
+ // instead.
+ RenderLayerModelObject* layerRenderer = layer->renderer();
+ return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTransform();
+}
+
+enum StackingOrderDirection { FromBackground, FromForeground };
+
+// We'd like to be able to iterate through a single paint order list, but for
+// efficiency's sake, we hang onto two lists instead (namely, the pos and neg
+// z-order lists produced by CollectLayers). This function allows us to index
+// into these two lists as if they were one. It also allows us to index into
+// this virtual list either from the start or from the end (i.e., in either
+// stacking order direction).
+static const RenderLayer* getStackingOrderElementAt(const Vector<RenderLayer*>* posZOrderList, const Vector<RenderLayer*>* negZOrderList, const StackingOrderDirection direction, const size_t index)
+{
+ size_t negZOrderListSize = negZOrderList ? negZOrderList->size() : 0;
+
+ if (direction == FromBackground) {
+ if (index < negZOrderListSize)
+ return negZOrderList->at(index);
+
+ return posZOrderList->at(index - negZOrderListSize);
+ }
+
+ size_t posZOrderListSize = posZOrderList ? posZOrderList->size() : 0;
+
+ if (index < posZOrderListSize)
+ return posZOrderList->at(posZOrderListSize - index - 1);
+
+ return negZOrderList->at(negZOrderListSize - (index - posZOrderListSize) - 1);
+}
+
+// After promotion, the paint order consists of
+// a) the non-descendants which precede the promoted layer,
+// b) the promoted layer, and
+// c) the non-descendants which succeed the promoted layer.
//
-// So for node A in the example above we would have:
-// maxStackIndex = 1
-// minStackIndex = -1
-// numSCDecendants = 2
+// If the current layer's descendants form a contiguous block in paint order
+// before promotion, the paint order will consist of
+// a) the non-descendants which precede the current layer and its descendants,
+// b) the current layer and its descendants
+// c) The non-descendants which succeed the current layer and its descendants.
//
-// and so,
-// maxStackIndex - minStackIndex == numSCDescendants
-// ===> 1 - (-1) == 2
-// ===> 2 == 2
+// Sub-lists (a) and (c) should be identical in both paint order lists if
+// and only if the descendants form a contiguous block. In fact, this is the
+// only check we need to perform since the order of the descendants with
+// respect to each other cannot be affected by promotion (i.e., we don't
+// need to worry about sub-list (b)).
//
-// Since this is true, A can safely become a stacking container.
-// Now, for node C we have:
+// Some examples:
+// C = currentLayer
+// - = negative z-order child of currentLayer
+// + = positive z-order child of currentLayer
+// A = positioned ancestor of currentLayer
+// x = any other RenderLayer in the list
//
-// maxStackIndex = 4
-// minStackIndex = 0 <-- because C has stacking index 0.
-// numSCDecendants = 2
+// original | zOrderListBeforePromote | zOrderListAfterPromote
+// zOrderListBeforePromote | after inserting C as above |
+// ---------------------------------------------------------------------------------------
+// (1) x---+++x | x---C+++x | xCx
+// (2) x---+A++x | x---+AC++x | xACx
+// (3) x-x--+++x | x-x--C+++x | xxCx
+// (4) xxA++x | xxAC++x | xxACx
//
-// and so,
-// maxStackIndex - minStackIndex == numSCDescendants
-// ===> 4 - 0 == 2
-// ===> 4 == 2
+// In example (1), we compare sub-list (a) by marching from the left of both
+// lists (zOrderListBeforePromote after inserting C and
+// zOrderListAfterPromote). The first mismatch is at index 1 when we hit '-'
+// and 'C'. That means we have neg z-order descendants. This is a problem if
+// we have a background. Before promotion, this bg would get painted with
+// the current layer (i.e., after the neg z-order descendants), but after
+// promotion the bg would get painted before them. This is a stacking order
+// violation and we can't promote. However, if we don't have a background,
+// we would continue on to the second pass. When comparing from the right,
+// we mismatch on '+' and 'C'. Since we hit 'C' on zOrderListAfterPromote,
+// we know that the children are contiguous, and we will promote.
//
-// 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:
+// In example (2), when marching from the left, we'll hit a mismatch again
+// on the second element we look at. This time, since this element is an 'A'
+// in zOrderListAfterPromote, this indicates that there is an extra layer
+// (the 'A') mixed in with the children. This could cause a change in paint
+// order if we promote, so we decide not to and break out of the loop. Note
+// that if the current layer has a background, this would provide a second
+// reason not to opt in, since again we have negative z-order children who
+// would change paint order with respect to our background if we promoted.
//
-// maxStackIndex = 3
-// minStackIndex = 0 <-- because C has stacking index 0.
-// numSCDecendants = 3
+// In example (3), the discontiguity of the negative z-order children causes
+// us to fail early in our "FromBackground" pass when we try to compare '-'
+// from zOrderListBeforePromote with 'x' in zOrderListAfterPromote.
//
-// and so,
-// maxStackIndex - minStackIndex == numSCDescendants
-// ===> 3 - 0 == 3
-// ===> 3 == 3
+// Finally in example (4), we would match 'xxAC' from the left, then stop
+// since we hit 'C'. Then we would match 'x' from the right, and mismatch
+// on '+' and 'C'. Since we're at 'C' on the zOrderListAfterPromote, we
+// conclude that all the children are contiguous. Since there are no
+// negative z-order children, a background layer is irrelevant in this case.
+// We will opt in, keeping paint order constant.
+static bool compareLayerListsBeforeAndAfterPromote(const RenderLayer* currentLayer,
+ const Vector<RenderLayer*>* posZOrderListBeforePromote,
+ const Vector<RenderLayer*>* negZOrderListBeforePromote,
+ const Vector<RenderLayer*>* posZOrderListAfterPromote,
+ const Vector<RenderLayer*>* negZOrderListAfterPromote,
+ const size_t sizeBeforePromote,
+ const size_t sizeAfterPromote,
+ const StackingOrderDirection direction)
+{
+ for (size_t index = 0; index < sizeBeforePromote && index < sizeAfterPromote; index++) {
+ const RenderLayer* layerBeforePromote = getStackingOrderElementAt(posZOrderListBeforePromote, negZOrderListBeforePromote, direction, index);
+ const RenderLayer* layerAfterPromote = getStackingOrderElementAt(posZOrderListAfterPromote, negZOrderListAfterPromote, direction, index);
+
+ if (layerBeforePromote != layerAfterPromote) {
+ // If we find a mismatch, the only situation where we haven't
+ // necessarily changed paint order yet is if layerAfterPromote
+ // is currentLayer.
+ if (layerAfterPromote != currentLayer)
+ return false;
+
+ // Also, if the current layer has a background, then any
+ // negative z-order children will get between the background
+ // and the rest of the layer.
+ if (direction == FromBackground && currentLayer->renderer()->hasBackground())
+ return false;
+ }
+
+ // To compare the sub-lists (a) and (c) from the comment above, we only
+ // need to march until we hit the currentLayer in the
+ // zOrderListAfterPromote from each direction.
+ if (layerAfterPromote == currentLayer)
+ break;
+ }
+
+ return true;
+}
+
+// Determine whether the current layer can be promoted to a stacking container,
+// given its closest stacking context ancestor. 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.
//
-// And we would conclude that C could be promoted.
-void RenderLayer::updateDescendantsAreContiguousInStackingOrder()
+// For more details on how the lists will be compared, see the comment and
+// examples for compareLayerListsBeforeAndAfterPromote().
+void RenderLayer::updateCanBeStackingContainer(RenderLayer* ancestorStackingContext)
{
- if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext() || !acceleratedCompositingForOverflowScrollEnabled())
- return;
+ TRACE_EVENT0("blink", "RenderLayer::updateCanBeStackingContainer");
- ASSERT(!m_normalFlowListDirty);
- ASSERT(!m_zOrderListsDirty);
+ ASSERT(!isStackingContext());
- OwnPtr<Vector<RenderLayer*> > posZOrderList;
- OwnPtr<Vector<RenderLayer*> > negZOrderList;
- rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList);
+ if (!m_canBePromotedToStackingContainerDirty || !acceleratedCompositingForOverflowScrollEnabled())
+ return;
- // Create a reverse lookup.
- HashMap<const RenderLayer*, int> lookup;
+ FrameView* frameView = renderer()->view()->frameView();
+ if (!frameView || !frameView->containsScrollableArea(this))
+ 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;
+ OwnPtr<Vector<RenderLayer*> > negZOrderListBeforePromote;
+ OwnPtr<Vector<RenderLayer*> > posZOrderListAfterPromote;
+ OwnPtr<Vector<RenderLayer*> > negZOrderListAfterPromote;
+ size_t posZOrderListSizeBeforePromote, negZOrderListSizeBeforePromote, posZOrderListSizeAfterPromote, negZOrderListSizeAfterPromote;
- 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 sizeBeforePromote = 0;
+ if (posZOrderListBeforePromote)
+ sizeBeforePromote += posZOrderListBeforePromote->size();
+ if (negZOrderListBeforePromote)
+ sizeBeforePromote += negZOrderListBeforePromote->size();
- m_descendantsAreContiguousInStackingOrderDirty = false;
-}
+ size_t sizeAfterPromote = 0;
+ if (posZOrderListAfterPromote)
+ sizeAfterPromote += posZOrderListAfterPromote->size();
+ if (negZOrderListAfterPromote)
+ sizeAfterPromote += negZOrderListAfterPromote->size();
-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;
- }
+ bool canPromote = compareLayerListsBeforeAndAfterPromote(this, posZOrderListBeforePromote.get(), negZOrderListBeforePromote.get(),
+ posZOrderListAfterPromote.get(), negZOrderListAfterPromote.get(),
+ sizeBeforePromote, sizeAfterPromote, FromBackground)
+ && compareLayerListsBeforeAndAfterPromote(this, posZOrderListBeforePromote.get(), negZOrderListBeforePromote.get(),
+ posZOrderListAfterPromote.get(), negZOrderListAfterPromote.get(),
+ sizeBeforePromote, sizeAfterPromote, FromForeground);
- 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);
- }
- }
+ bool didUpdate = (canPromote != m_canBePromotedToStackingContainer);
- if (!isStackingContext()) {
- bool newValue = maxIndex - minIndex == count;
- bool didUpdate = newValue != m_descendantsAreContiguousInStackingOrder;
- m_descendantsAreContiguousInStackingOrder = newValue;
- if (didUpdate)
- updateNeedsCompositedScrolling();
- }
-}
-
-static inline bool isPositionedContainer(const RenderLayer* layer)
-{
- // FIXME: This is not in sync with containingBlock.
- // RenderObject::canContainFixedPositionedObject() should probably be used
- // instead.
- RenderLayerModelObject* layerRenderer = layer->renderer();
- return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTransform();
+ m_canBePromotedToStackingContainer = canPromote;
+ m_canBePromotedToStackingContainerDirty = false;
}
void RenderLayer::collectBeforePromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListBeforePromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListBeforePromote)
@@ -1062,7 +1096,8 @@ bool RenderLayer::canBeStackingContainer() const
if (isStackingContext() || !ancestorStackingContainer())
return true;
- return m_descendantsAreContiguousInStackingOrder;
+ // PATCH 3
hartmanng 2013/05/02 14:04:01 There should be an assert in here, right?
+ return m_canBePromotedToStackingContainer;
}
void RenderLayer::setHasVisibleContent()
@@ -1118,56 +1153,65 @@ void RenderLayer::setAncestorChainHasVisibleDescendant()
}
}
-void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks)
+// PATCH 2 - requires a full tree walk. We *only* want to do this once after a style change,
+// so it must be tied to the phase work.
+void RenderLayer::updateHasOutOfFlowPositionedDescendant(HashSet<const RenderObject*>* containingBlocks)
{
- if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
- const bool hadVisibleDescendant = m_hasVisibleDescendant;
- const bool hadOutOfFlowPositionedDescendant = m_hasOutOfFlowPositionedDescendant;
+ const bool hadOutOfFlowPositionedDescendant = hasOutOfFlowPositionedDescendant();
+ m_hasOutOfFlowPositionedDescendant = false;
+
+ HashSet<const RenderObject*> childContainingBlocks;
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ childContainingBlocks.clear();
+ child->updateHasOutOfFlowPositionedDescendant(&childContainingBlocks);
+
+ const bool childIsOutOfFlowPositioned = child->renderer()
+ && child->renderer()->isOutOfFlowPositioned()
+ && (child->hasVisibleDescendant() || child->hasVisibleContent());
+
+ if (childIsOutOfFlowPositioned)
+ childContainingBlocks.add(child->renderer()->containingBlock());
+
+ size_t numContainingBlocks = childContainingBlocks.size();
+ childContainingBlocks.remove(renderer());
+
+ if (containingBlocks && !childContainingBlocks.isEmpty()) {
+ HashSet<const RenderObject*>::const_iterator it = childContainingBlocks.begin();
+ for (; it != childContainingBlocks.end(); ++it)
+ containingBlocks->add(*it);
+ }
+ m_hasOutOfFlowPositionedDescendant |= !childContainingBlocks.isEmpty();
+ }
+
+ if (m_hasOutOfFlowPositionedDescendant != hadOutOfFlowPositionedDescendant)
+ compositor()->setNeedsUpdateCompositingRequirementsState();
+}
+
+void RenderLayer::updateDescendantDependentFlags()
+{
+ if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) {
m_hasVisibleDescendant = false;
m_hasSelfPaintingLayerDescendant = false;
- m_hasOutOfFlowPositionedDescendant = false;
- HashSet<const RenderObject*> childOutOfFlowDescendantContainingBlocks;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
- childOutOfFlowDescendantContainingBlocks.clear();
- child->updateDescendantDependentFlags(&childOutOfFlowDescendantContainingBlocks);
-
- bool childIsOutOfFlowPositioned = child->renderer() && child->renderer()->isOutOfFlowPositioned();
- if (childIsOutOfFlowPositioned)
- childOutOfFlowDescendantContainingBlocks.add(child->renderer()->containingBlock());
-
- if (outOfFlowDescendantContainingBlocks) {
- HashSet<const RenderObject*>::const_iterator it = childOutOfFlowDescendantContainingBlocks.begin();
- for (; it != childOutOfFlowDescendantContainingBlocks.end(); ++it)
- outOfFlowDescendantContainingBlocks->add(*it);
- }
+ child->updateDescendantDependentFlags();
bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
- bool hasOutOfFlowPositionedDescendant = hasVisibleDescendant && (!childOutOfFlowDescendantContainingBlocks.isEmpty() || child->hasOutOfFlowPositionedDescendant());
m_hasVisibleDescendant |= hasVisibleDescendant;
m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
- m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
- if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && m_hasOutOfFlowPositionedDescendant)
+ if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant)
break;
}
- if (outOfFlowDescendantContainingBlocks && renderer())
- outOfFlowDescendantContainingBlocks->remove(renderer());
-
m_visibleDescendantStatusDirty = false;
m_hasSelfPaintingLayerDescendantDirty = false;
- m_hasOutOfFlowPositionedDescendantDirty = false;
-
- if (m_hasVisibleDescendant != hadVisibleDescendant || m_hasOutOfFlowPositionedDescendant != hadOutOfFlowPositionedDescendant)
- updateNeedsCompositedScrolling();
}
if (m_visibleContentStatusDirty) {
- const bool hadVisibleContent = m_hasVisibleContent;
if (renderer()->style()->visibility() == VISIBLE)
m_hasVisibleContent = true;
else {
@@ -1193,10 +1237,8 @@ void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* o
r = r->nextSibling();
}
}
- }
- m_visibleContentStatusDirty = false;
- if (hadVisibleContent != m_hasVisibleContent)
- updateNeedsCompositedScrolling();
+ }
+ m_visibleContentStatusDirty = false;
}
}
@@ -1767,16 +1809,7 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
// case where we're building up generated content layers. This is ok, since the lists will start
// off dirty in that case anyway.
child->dirtyStackingContainerZOrderLists();
-
- // Adding an out of flow positioned descendant can only affect
- // the opt-in decision for layers beneath and including our
- // containing block.
- RenderObject* containingBlock = child->renderer()->containingBlock();
- for (RenderLayer* layer = child; layer; layer = layer->parent()) {
- layer->updateNeedsCompositedScrolling();
- if (layer->renderer() == containingBlock)
- break;
- }
+ // PATCH 2
}
child->updateDescendantDependentFlags();
@@ -1787,7 +1820,8 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
setAncestorChainHasSelfPaintingLayerDescendant();
if (child->renderer() && (child->renderer()->isOutOfFlowPositioned() || child->hasOutOfFlowPositionedDescendant()))
- setAncestorChainHasOutOfFlowPositionedDescendant(child->renderer()->containingBlock());
+ // PATCH 2
+ compositor()->setNeedsUpdateCompositingRequirementsState();
compositor()->layerWasAdded(this, child);
}
@@ -1815,28 +1849,19 @@ RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
// reattachment process in removeOnlyThisLayer, the layer may already be disconnected
// from the main layer tree, so we need to null-check the |stackingContainer| value.
oldChild->dirtyStackingContainerZOrderLists();
-
- // This could affect whether or not a layer has an out of flow
- // positioned descendant so we need to schedule some updates.
- // Removing an out of flow positioned descendant can only affect
- // the opt-in decision for layers beneath and including the old child's
- // containing block.
- RenderObject* containingBlock = oldChild->renderer()->containingBlock();
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- layer->updateNeedsCompositedScrolling();
- if (layer->renderer() == containingBlock)
- break;
- }
+ // PATCH 2
}
- if ((oldChild->renderer() && oldChild->renderer()->isOutOfFlowPositioned()) || oldChild->hasOutOfFlowPositionedDescendant())
- dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
-
+ // PATCH 2
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
oldChild->setParent(0);
oldChild->updateDescendantDependentFlags();
+ // PATCH 2
+ if ((oldChild->renderer() && oldChild->renderer()->isOutOfFlowPositioned()) || oldChild->hasOutOfFlowPositionedDescendant())
+ compositor()->setNeedsUpdateCompositingRequirementsState();
+
if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
dirtyAncestorChainVisibleDescendantStatus();
@@ -2051,26 +2076,41 @@ bool RenderLayer::usesCompositedScrolling() const
bool RenderLayer::needsCompositedScrolling() const
{
+ // PATCH 1
+ switch (m_forceNeedsCompositedScrolling) {
+ case DoNotForceCompositedScrolling:
+ return m_needsCompositedScrolling;
+ case ForceCompositedScrollingOn:
+ return true;
+ case ForceCompositedScrollingOff:
+ return false;
+ }
+
return m_needsCompositedScrolling;
}
+// PATCH 1
void RenderLayer::updateNeedsCompositedScrolling()
{
bool needsCompositedScrolling = false;
FrameView* frameView = renderer()->view()->frameView();
- if (frameView && frameView->containsScrollableArea(this)) {
- updateDescendantDependentFlags();
+ if (frameView && frameView->containsScrollableArea(this) && acceleratedCompositingForOverflowScrollEnabled()) {
+ if (isStackingContext()) {
+ needsCompositedScrolling = true;
+ } else {
+ RenderLayer* stackingContext = ancestorStackingContext();
+ updateCanBeStackingContainer(stackingContext);
- bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEnabled()
- && canBeStackingContainer()
- && !hasOutOfFlowPositionedDescendant();
+ bool forceUseCompositedScrolling = canBeStackingContainer() && !hasOutOfFlowPositionedDescendant();
#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
@@ -2084,6 +2124,23 @@ void RenderLayer::updateNeedsCompositedScrolling()
m_needsCompositedScrolling = needsCompositedScrolling;
+ // Note, the z-order lists may need to be rebuilt, but our code guarantees
+ // that we have not affected stacking, so we will not dirty
+ // m_canBePromotedToStackingContainer for either us or our stacking context
+ // or container.
+ didUpdateNeedsCompositedScrolling();
+}
+
+// PATCH 1
+void RenderLayer::setForceNeedsCompositedScrolling(RenderLayer::ForceNeedsCompositedScrollingMode mode)
+{
+ m_forceNeedsCompositedScrolling = mode;
+ didUpdateNeedsCompositedScrolling();
+}
+
+// PATCH 1
+void RenderLayer::didUpdateNeedsCompositedScrolling()
+{
updateIsNormalFlowOnly();
updateSelfPaintingLayer();
@@ -5607,7 +5664,10 @@ void RenderLayer::dirtyZOrderLists()
m_negZOrderList->clear();
m_zOrderListsDirty = true;
- m_descendantsAreContiguousInStackingOrderDirty = true;
+ // PATCH 3
+ m_canBePromotedToStackingContainerDirty = true;
+ // PATCH 2
+ compositor()->setNeedsUpdateCompositingRequirementsState();
if (!renderer()->documentBeingDestroyed()) {
compositor()->setCompositingLayersNeedRebuild();
@@ -5702,6 +5762,7 @@ void RenderLayer::updateNormalFlowList()
m_normalFlowListDirty = false;
}
+// PATCH 2
void RenderLayer::collectLayers(bool includeHiddenLayers, CollectLayersBehavior behavior, OwnPtr<Vector<RenderLayer*> >& posBuffer, OwnPtr<Vector<RenderLayer*> >& negBuffer, const RenderLayer* layerToForceAsStackingContainer)
{
if (isInTopLayer())
@@ -5712,18 +5773,28 @@ void RenderLayer::collectLayers(bool includeHiddenLayers, CollectLayersBehavior
bool isStacking = false;
switch (behavior) {
- case StopAtStackingContexts:
- isStacking = (this == layerToForceAsStackingContainer) || isStackingContext();
- break;
+ case StopAtStackingContexts:
+ isStacking = (this == layerToForceAsStackingContainer) || isStackingContext();
+ break;
- case StopAtStackingContainers:
- isStacking = (this == layerToForceAsStackingContainer) || isStackingContainer();
- break;
+ case StopAtStackingContainers:
+ isStacking = (this == layerToForceAsStackingContainer) || isStackingContainer();
+ break;
+ }
+
+ // This value could be affected by opt in. What we really need to know is
+ // are you normal flow only, regardless of your opt in status. This is very
+ // similar to asking if a layer is a stacking context rather than a
+ // stacking container.
+ bool isNormalFlowWithoutCompositedScrolling = isNormalFlowOnly();
+ if (this != layerToForceAsStackingContainer && behavior == StopAtStackingContexts) {
+ TemporaryChange<ForceNeedsCompositedScrollingMode> forceOff(m_forceNeedsCompositedScrolling, ForceCompositedScrollingOff);
+ isNormalFlowWithoutCompositedScrolling = shouldBeNormalFlowOnly();
}
// Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStacking));
- if (includeHiddenLayer && !isNormalFlowOnly() && !isOutOfFlowRenderFlowThread()) {
+ if (includeHiddenLayer && !isNormalFlowWithoutCompositedScrolling && !isOutOfFlowRenderFlowThread()) {
// Determine which buffer the child should be in.
OwnPtr<Vector<RenderLayer*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
@@ -5746,9 +5817,9 @@ void RenderLayer::collectLayers(bool includeHiddenLayers, CollectLayersBehavior
}
}
+// PATCH 2
void RenderLayer::updateLayerListsIfNeeded()
{
- bool shouldUpdateDescendantsAreContiguousInStackingOrder = acceleratedCompositingForOverflowScrollEnabled() && isStackingContext() && (m_zOrderListsDirty || m_normalFlowListDirty) && m_descendantsAreContiguousInStackingOrderDirty;
updateZOrderLists();
updateNormalFlowList();
@@ -5756,14 +5827,6 @@ void RenderLayer::updateLayerListsIfNeeded()
reflectionLayer->updateZOrderLists();
reflectionLayer->updateNormalFlowList();
}
-
- if (shouldUpdateDescendantsAreContiguousInStackingOrder) {
- updateDescendantsAreContiguousInStackingOrder();
- // The above function can cause us to update m_needsCompositedScrolling
- // and dirty our layer lists. Refresh them if necessary.
- updateZOrderLists();
- updateNormalFlowList();
- }
}
void RenderLayer::repaintIncludingDescendants()
@@ -5943,9 +6006,8 @@ void RenderLayer::updateVisibilityAfterStyleChange(const RenderStyle* oldStyle)
return;
if (renderer()->style()->visibility() == VISIBLE)
- setAncestorChainHasOutOfFlowPositionedDescendant(renderer()->containingBlock());
- else
- dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+ // PATCH 2
+ compositor()->setNeedsUpdateCompositingRequirementsState();
}
void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
@@ -5967,7 +6029,8 @@ void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldS
else
clearZOrderLists();
- updateNeedsCompositedScrolling();
+ // PATCH 2
+ compositor()->setNeedsUpdateCompositingRequirementsState();
}
static bool overflowRequiresScrollbar(EOverflow overflow)
@@ -6016,46 +6079,11 @@ void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
}
-void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant(RenderObject* containingBlock)
-{
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
- break;
-
- layer->m_hasOutOfFlowPositionedDescendantDirty = false;
- layer->m_hasOutOfFlowPositionedDescendant = true;
- layer->updateNeedsCompositedScrolling();
-
- if (layer->renderer() && layer->renderer() == containingBlock)
- break;
- }
-}
-
-void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
-{
- if (m_hasOutOfFlowPositionedDescendant) {
- m_hasOutOfFlowPositionedDescendantDirty = true;
- // FIXME It would be nice to avoid this when we clean up render layer
- // updating. We shouldn't have to update the composited scrolling state
- // nearly as frequently if all the updates happen in a single, well
- // defined phase.
- updateNeedsCompositedScrolling();
- }
-
- if (parent())
- parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
-}
-
+// PATCH 2
void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
{
- bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
- bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned();
- if (parent() && isOutOfFlowPositioned != wasOutOfFlowPositioned) {
- if (isOutOfFlowPositioned)
- parent()->setAncestorChainHasOutOfFlowPositionedDescendant(renderer()->containingBlock());
- else
- parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
- }
+ if (!oldStyle || (renderer()->style()->position() != oldStyle->position()))
+ compositor()->setNeedsUpdateCompositingRequirementsState();
}
static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
@@ -6213,7 +6241,8 @@ void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
updatedScrollableAreaSet = frameView->removeScrollableArea(this);
if (updatedScrollableAreaSet)
- updateNeedsCompositedScrolling();
+ // PATCH 2
+ compositor()->setNeedsUpdateCompositingRequirementsState();
}
void RenderLayer::updateScrollCornerStyle()
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerCompositor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698