Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp |
| index d8e1150dc64d8b6bf00742d45fed3309de9003f1..343d31601d4c069357d9a39c60ff0740988c0d92 100644 |
| --- a/third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp |
| +++ b/third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp |
| @@ -65,6 +65,11 @@ class OverlapMapContainer { |
| IntRect m_boundingBox; |
| }; |
| +struct OverlapMapContainers { |
| + OverlapMapContainer clipped; |
| + OverlapMapContainer unclipped; |
| +}; |
| + |
| class CompositingRequirementsUpdater::OverlapMap { |
| WTF_MAKE_NONCOPYABLE(OverlapMap); |
| @@ -76,7 +81,16 @@ class CompositingRequirementsUpdater::OverlapMap { |
| beginNewOverlapTestingContext(); |
| } |
| - void add(PaintLayer* layer, const IntRect& bounds) { |
| + // Each rect added is marked as clipped or unclipped. clipped rects may |
| + // overlap only with other clipped rects, but unclipped rects may overlap |
| + // with anything. |
| + // |
| + // This is used to model composited overflow scrolling, where PaintLayers |
| + // within the scroller are not clipped for overlap testing, whereas |
| + // PaintLayers not within it are. This is necessary because PaintLayerClipper |
| + // is not smart enough to understand not to clip composited overflow clips, |
| + // but still clip otherwise. |
| + void add(PaintLayer* layer, const IntRect& bounds, bool isClipped) { |
| DCHECK(!layer->isRootLayer()); |
| if (bounds.isEmpty()) |
| return; |
| @@ -85,18 +99,26 @@ class CompositingRequirementsUpdater::OverlapMap { |
| // contribute to overlap as soon as they have been recursively processed |
| // and popped off the stack. |
| DCHECK_GE(m_overlapStack.size(), 2ul); |
| - m_overlapStack[m_overlapStack.size() - 2].add(bounds); |
| + if (isClipped) |
| + m_overlapStack[m_overlapStack.size() - 2].clipped.add(bounds); |
| + else |
| + m_overlapStack[m_overlapStack.size() - 2].unclipped.add(bounds); |
| } |
| - bool overlapsLayers(const IntRect& bounds) const { |
| - return m_overlapStack.last().overlapsLayers(bounds); |
| + bool overlapsLayers(const IntRect& bounds, bool isClipped) const { |
| + bool clippedOverlap = m_overlapStack.last().clipped.overlapsLayers(bounds); |
| + if (isClipped) |
| + return clippedOverlap; |
| + // Unclipped is allowed to overlap clipped, but not vice-versa. |
| + return clippedOverlap || |
| + m_overlapStack.last().unclipped.overlapsLayers(bounds); |
| } |
| void beginNewOverlapTestingContext() { |
| // This effectively creates a new "clean slate" for overlap state. |
| // This is used when we know that a subtree or remaining set of |
| // siblings does not need to check overlap with things behind it. |
| - m_overlapStack.append(OverlapMapContainer()); |
| + m_overlapStack.append(OverlapMapContainers()); |
| } |
| void finishCurrentOverlapTestingContext() { |
| @@ -107,12 +129,15 @@ class CompositingRequirementsUpdater::OverlapMap { |
| // |
| // FIXME: we may be able to avoid this deep copy by rearranging how |
| // overlapMap state is managed. |
| - m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last()); |
| + m_overlapStack[m_overlapStack.size() - 2].clipped.unite( |
| + m_overlapStack.last().clipped); |
| + m_overlapStack[m_overlapStack.size() - 2].unclipped.unite( |
| + m_overlapStack.last().unclipped); |
| m_overlapStack.removeLast(); |
| } |
| private: |
| - Vector<OverlapMapContainer> m_overlapStack; |
| + Vector<OverlapMapContainers> m_overlapStack; |
| }; |
| class CompositingRequirementsUpdater::RecursionData { |
| @@ -233,6 +258,13 @@ void CompositingRequirementsUpdater::updateRecursive( |
| currentRecursionData.m_compositingAncestor->layoutObject()->isVideo()) |
| directReasons |= CompositingReasonVideoOverlay; |
| + bool hasCompositedScrollingAncestor = |
| + layer->ancestorScrollingLayer() && |
| + (m_compositingReasonFinder.directReasons( |
| + layer->ancestorScrollingLayer()) & |
| + CompositingReasonOverflowScrollingTouch); |
| + |
| + // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead. |
| if (currentRecursionData.m_hasCompositedScrollingAncestor && |
| layer->layoutObject()->styleRef().hasViewportConstrainedPosition()) |
| directReasons |= CompositingReasonScrollDependentPosition; |
| @@ -278,6 +310,7 @@ void CompositingRequirementsUpdater::updateRecursive( |
| ? CompositingReasonAssumedOverlap |
| : CompositingReasonNone; |
| + // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead. |
| if (currentRecursionData.m_hasCompositedScrollingAncestor) { |
| Vector<size_t> unclippedDescendantsToRemove; |
| for (size_t i = 0; i < unclippedDescendants.size(); i++) { |
| @@ -310,14 +343,16 @@ void CompositingRequirementsUpdater::updateRecursive( |
| } |
| } |
| - const IntRect& absBounds = layer->clippedAbsoluteBoundingBox(); |
| + const IntRect& absBounds = hasCompositedScrollingAncestor |
| + ? layer->unclippedAbsoluteBoundingBox() |
| + : layer->clippedAbsoluteBoundingBox(); |
| absoluteDescendantBoundingBox = absBounds; |
| - |
| if (currentRecursionData.m_testingOverlap && |
| !requiresCompositingOrSquashing(directReasons)) { |
| - overlapCompositingReason = overlapMap.overlapsLayers(absBounds) |
| - ? CompositingReasonOverlap |
| - : CompositingReasonNone; |
| + bool overlaps = |
| + overlapMap.overlapsLayers(absBounds, !hasCompositedScrollingAncestor); |
| + overlapCompositingReason = |
| + overlaps ? CompositingReasonOverlap : CompositingReasonNone; |
|
Ian Vollick
2016/10/19 20:16:31
I think I follow. If we're below the composited sc
chrishtr
2016/10/19 21:44:51
Exactly, it will promote. (though you have to add
|
| } |
| reasonsToComposite |= overlapCompositingReason; |
| @@ -379,7 +414,7 @@ void CompositingRequirementsUpdater::updateRecursive( |
| // the negative z-index child's bounds to the new overlap context. |
| overlapMap.beginNewOverlapTestingContext(); |
| overlapMap.add(curNode->layer(), |
| - curNode->layer()->clippedAbsoluteBoundingBox()); |
| + curNode->layer()->clippedAbsoluteBoundingBox(), true); |
| overlapMap.finishCurrentOverlapTestingContext(); |
| } |
| } |
| @@ -449,7 +484,7 @@ void CompositingRequirementsUpdater::updateRecursive( |
| // for overlap. |
| if (childRecursionData.m_compositingAncestor && |
| !childRecursionData.m_compositingAncestor->isRootLayer()) |
| - overlapMap.add(layer, absBounds); |
| + overlapMap.add(layer, absBounds, !hasCompositedScrollingAncestor); |
| // Now check for reasons to become composited that depend on the state of |
| // descendant layers. |
| @@ -464,7 +499,8 @@ void CompositingRequirementsUpdater::updateRecursive( |
| // now, because the code is designed to push overlap information to the |
| // second-from-top context of the stack. |
| overlapMap.beginNewOverlapTestingContext(); |
| - overlapMap.add(layer, absoluteDescendantBoundingBox); |
| + overlapMap.add(layer, absoluteDescendantBoundingBox, |
| + !hasCompositedScrollingAncestor); |
| willBeCompositedOrSquashed = true; |
| } |