Index: third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
index 59904bed5ccb7cb5d06908f4e97181cf876b5e1b..bac781200112071fb6b756715ae4cd241da0b944 100644 |
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
@@ -65,60 +65,42 @@ static LayoutRect computeBottomDelta(const LayoutPoint& location, |
} |
bool BoxPaintInvalidator::incrementallyInvalidatePaint() { |
- const LayoutRect& oldRect = m_context.oldBounds.rect; |
- const LayoutRect& newRect = m_context.newBounds.rect; |
- DCHECK(oldRect.location() == newRect.location()); |
- LayoutRect rightDelta = |
- computeRightDelta(newRect.location(), oldRect.size(), newRect.size(), 0); |
- LayoutRect bottomDelta = |
- computeBottomDelta(newRect.location(), oldRect.size(), newRect.size(), 0); |
- |
- if (m_box.styleRef().hasBorder() || m_box.styleRef().hasBackground()) { |
- LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldRect.size()); |
+ LayoutRect rightDelta; |
+ LayoutRect bottomDelta; |
+ if (m_box.isLayoutView()) { |
+ // This corresponds to the special case in computePaintInvalidationReason() |
+ // for LayoutView in non-rootLayerScrolling mode. In rootLayerScrolling |
+ // mode, we'll do full paint invalidation (see crbug.com/660156). |
+ DCHECK(!RuntimeEnabledFeatures::rootLayerScrollingEnabled()); |
+ DCHECK(m_context.oldBounds.location() == m_context.newBounds.location()); |
+ rightDelta = computeRightDelta(m_context.newBounds.location(), |
+ m_context.oldBounds.size(), |
+ m_context.newBounds.size(), 0); |
+ bottomDelta = computeBottomDelta(m_context.newBounds.location(), |
+ m_context.oldBounds.size(), |
+ m_context.newBounds.size(), 0); |
+ } else { |
+ LayoutSize oldBorderBoxSize = |
+ computePreviousBorderBoxSize(m_context.oldBounds.size()); |
LayoutSize newBorderBoxSize = m_box.size(); |
DCHECK(m_context.oldLocation == m_context.newLocation); |
- rightDelta.unite(computeRightDelta(m_context.newLocation, oldBorderBoxSize, |
- newBorderBoxSize, m_box.borderRight())); |
- bottomDelta.unite(computeBottomDelta(m_context.newLocation, |
- oldBorderBoxSize, newBorderBoxSize, |
- m_box.borderBottom())); |
+ rightDelta = computeRightDelta(m_context.newLocation, oldBorderBoxSize, |
+ newBorderBoxSize, m_box.borderRight()); |
+ bottomDelta = computeBottomDelta(m_context.newLocation, oldBorderBoxSize, |
+ newBorderBoxSize, m_box.borderBottom()); |
} |
if (rightDelta.isEmpty() && bottomDelta.isEmpty()) |
return false; |
- invalidatePaintRectClippedByOldAndNewBounds(rightDelta); |
- invalidatePaintRectClippedByOldAndNewBounds(bottomDelta); |
- return true; |
-} |
- |
-void BoxPaintInvalidator::invalidatePaintRectClippedByOldAndNewBounds( |
- const LayoutRect& rect) { |
- if (rect.isEmpty()) |
- return; |
- |
ObjectPaintInvalidator objectPaintInvalidator(m_box); |
- LayoutRect rectClippedByOldBounds = |
- intersection(rect, m_context.oldBounds.rect); |
- LayoutRect rectClippedByNewBounds = |
- intersection(rect, m_context.newBounds.rect); |
- // Invalidate only once if the clipped rects equal. |
- if (rectClippedByOldBounds == rectClippedByNewBounds) { |
- objectPaintInvalidator.invalidatePaintUsingContainer( |
- *m_context.paintInvalidationContainer, rectClippedByOldBounds, |
- PaintInvalidationIncremental); |
- return; |
- } |
- // Invalidate the bigger one if one contains another. Otherwise invalidate |
- // both. |
- if (!rectClippedByNewBounds.contains(rectClippedByOldBounds)) |
- objectPaintInvalidator.invalidatePaintUsingContainer( |
- *m_context.paintInvalidationContainer, rectClippedByOldBounds, |
- PaintInvalidationIncremental); |
- if (!rectClippedByOldBounds.contains(rectClippedByNewBounds)) |
- objectPaintInvalidator.invalidatePaintUsingContainer( |
- *m_context.paintInvalidationContainer, rectClippedByNewBounds, |
- PaintInvalidationIncremental); |
+ objectPaintInvalidator.invalidatePaintUsingContainer( |
+ *m_context.paintInvalidationContainer, rightDelta, |
+ PaintInvalidationIncremental); |
+ objectPaintInvalidator.invalidatePaintUsingContainer( |
+ *m_context.paintInvalidationContainer, bottomDelta, |
+ PaintInvalidationIncremental); |
+ return true; |
} |
PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
@@ -145,6 +127,8 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
: PaintInvalidationDelayedFull; |
} |
+ DCHECK(reason == PaintInvalidationIncremental); |
+ |
if (m_box.isLayoutView()) { |
const LayoutView& layoutView = toLayoutView(m_box); |
// In normal compositing mode, root background doesn't need to be |
@@ -158,28 +142,6 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
return reason; |
} |
- if (reason == PaintInvalidationIncremental && |
- m_context.oldBounds.rect != m_context.newBounds.rect) { |
- if (m_context.newBounds.coversExtraPixels || |
- m_context.oldBounds.coversExtraPixels) { |
- // Incremental invalidation is not applicable because the difference |
- // between oldBounds and newBounds may not cover all changed pixels along |
- // the edges. |
- return PaintInvalidationBoundsChange; |
- } |
- |
- // If the transform is not identity or translation, incremental invalidation |
- // is not applicable because the difference between oldBounds and newBounds |
- // doesn't cover all area needing invalidation. |
- // TODO(crbug.com/426111): Should also consider ancestor transforms |
- // since paintInvalidationContainer. Combine this logic into the above |
- // boundsCoversExtraPixels logic. |
- if (m_context.paintInvalidationContainer != m_box && m_box.hasLayer() && |
- m_box.layer()->transform() && |
- !m_box.layer()->transform()->isIdentityOrTranslation()) |
- return PaintInvalidationBoundsChange; |
- } |
- |
const ComputedStyle& style = m_box.styleRef(); |
if (style.backgroundLayers().thisOrNextLayersUseContentBox() || |
style.maskLayers().thisOrNextLayersUseContentBox() || |
@@ -189,14 +151,6 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
return PaintInvalidationContentBoxChange; |
} |
- if (!style.hasBackground() && !style.hasBoxDecorations()) { |
- if (reason == PaintInvalidationIncremental && |
- m_context.oldBounds.rect != m_context.newBounds.rect && |
- m_box.hasNonCompositedScrollbars()) |
- return PaintInvalidationBorderBoxChange; |
- return reason; |
- } |
- |
if (style.backgroundLayers().thisOrNextLayersHaveLocalAttachment()) { |
if (previousBoxSizesMap().get(&m_box).layoutOverflowRect != |
m_box.layoutOverflowRect()) |
@@ -204,18 +158,35 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
} |
LayoutSize oldBorderBoxSize = |
- computePreviousBorderBoxSize(m_context.oldBounds.rect.size()); |
+ computePreviousBorderBoxSize(m_context.oldBounds.size()); |
LayoutSize newBorderBoxSize = m_box.size(); |
+ bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; |
+ |
+ if (!borderBoxChanged && m_context.oldBounds == m_context.newBounds) |
+ return PaintInvalidationNone; |
+ |
+ // If either border box changed or bounds changed, and old or new border box |
+ // doesn't equal old or new bounds, incremental invalidation is not |
+ // applicable. This captures the following cases: |
+ // - pixel snapping of paint invalidation bounds, |
+ // - scale, rotate, skew etc. transforms, |
+ // - visual overflows. |
+ if (m_context.oldBounds != |
+ LayoutRect(m_context.oldLocation, oldBorderBoxSize) || |
+ m_context.newBounds != |
+ LayoutRect(m_context.newLocation, newBorderBoxSize)) { |
+ return borderBoxChanged ? PaintInvalidationBorderBoxChange |
+ : PaintInvalidationBoundsChange; |
+ } |
- if (oldBorderBoxSize == newBorderBoxSize) |
- return reason; |
+ DCHECK(borderBoxChanged); |
- // See another hasNonCompositedScrollbars() callsite above. |
if (m_box.hasNonCompositedScrollbars()) |
return PaintInvalidationBorderBoxChange; |
if (style.hasVisualOverflowingEffect() || style.hasAppearance() || |
- style.hasFilterInducingProperty() || style.resize() != RESIZE_NONE) |
+ style.hasFilterInducingProperty() || style.resize() != RESIZE_NONE || |
+ style.hasMask()) |
return PaintInvalidationBorderBoxChange; |
if (style.hasBorderRadius()) |
@@ -228,7 +199,7 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange()) |
return PaintInvalidationBorderBoxChange; |
- return reason; |
+ return PaintInvalidationIncremental; |
} |
PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() { |
@@ -262,12 +233,15 @@ PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() { |
} |
bool BoxPaintInvalidator::needsToSavePreviousBoxSizes() { |
- LayoutSize paintInvalidationSize = m_context.newBounds.rect.size(); |
+ LayoutSize paintInvalidationSize = m_context.newBounds.size(); |
// Don't save old box sizes if the paint rect is empty because we'll |
// full invalidate once the paint rect becomes non-empty. |
if (paintInvalidationSize.isEmpty()) |
return false; |
+ if (m_box.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) |
+ return false; |
+ |
const ComputedStyle& style = m_box.styleRef(); |
// If we use border-box sizing we need to track changes in the size of the |
@@ -275,13 +249,6 @@ bool BoxPaintInvalidator::needsToSavePreviousBoxSizes() { |
if (style.boxSizing() == BoxSizingBorderBox) |
return true; |
- // We need the old box sizes only when the box has background, decorations, or |
- // masks. |
- // Main LayoutView paints base background, thus interested in box size. |
- if (!m_box.isLayoutView() && !style.hasBackground() && |
- !style.hasBoxDecorations() && !style.hasMask()) |
- return false; |
- |
// No need to save old border box size if we can use size of the old paint |
// rect as the old border box size in the next invalidation. |
if (paintInvalidationSize != m_box.size()) |
@@ -310,11 +277,6 @@ void BoxPaintInvalidator::savePreviousBoxSizesIfNeeded() { |
LayoutSize BoxPaintInvalidator::computePreviousBorderBoxSize( |
const LayoutSize& previousBoundsSize) { |
- // PreviousBorderBoxSize is only valid when there is background or box |
- // decorations. |
- DCHECK(m_box.styleRef().hasBackground() || |
- m_box.styleRef().hasBoxDecorations()); |
- |
auto it = previousBoxSizesMap().find(&m_box); |
if (it != previousBoxSizesMap().end()) |
return it->value.borderBoxSize; |