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 34c56d65e6562dc8b404d9aaa7d16690874965c0..f9558e30b369b12c909c3d3a96fa0b9eb44efb66 100644 |
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp |
@@ -6,6 +6,7 @@ |
#include "core/frame/Settings.h" |
#include "core/layout/LayoutView.h" |
+#include "core/layout/compositing/CompositedLayerMapping.h" |
#include "core/paint/ObjectPaintInvalidator.h" |
#include "core/paint/PaintInvalidator.h" |
#include "core/paint/PaintLayer.h" |
@@ -68,42 +69,26 @@ static LayoutRect computeBottomDelta(const LayoutPoint& location, |
return LayoutRect(); |
} |
-bool BoxPaintInvalidator::incrementallyInvalidatePaint() { |
- LayoutRect rightDelta; |
- LayoutRect bottomDelta; |
- if (m_box.isLayoutView() && |
- !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
- // This corresponds to the special case in computePaintInvalidationReason() |
- // for LayoutView in non-rootLayerScrolling mode. |
- DCHECK(m_context.oldVisualRect.location() == |
- m_context.newVisualRect.location()); |
- rightDelta = computeRightDelta(m_context.newVisualRect.location(), |
- m_context.oldVisualRect.size(), |
- m_context.newVisualRect.size(), 0); |
- bottomDelta = computeBottomDelta(m_context.newVisualRect.location(), |
- m_context.oldVisualRect.size(), |
- m_context.newVisualRect.size(), 0); |
- } else { |
- LayoutSize oldBorderBoxSize = |
- previousBorderBoxSize(m_context.oldVisualRect.size()); |
- LayoutSize newBorderBoxSize = m_box.size(); |
- DCHECK(m_context.oldLocation == m_context.newLocation); |
- rightDelta = computeRightDelta(m_context.newLocation, oldBorderBoxSize, |
- newBorderBoxSize, m_box.borderRight()); |
- bottomDelta = computeBottomDelta(m_context.newLocation, oldBorderBoxSize, |
- newBorderBoxSize, m_box.borderBottom()); |
- } |
+bool BoxPaintInvalidator::incrementallyInvalidatePaint( |
+ PaintInvalidationReason reason, |
+ const LayoutRect& oldRect, |
+ const LayoutRect& newRect) { |
+ DCHECK(oldRect.location() == newRect.location()); |
+ LayoutRect rightDelta = computeRightDelta( |
+ newRect.location(), oldRect.size(), newRect.size(), |
+ reason == PaintInvalidationIncremental ? m_box.borderRight() : 0); |
+ LayoutRect bottomDelta = computeBottomDelta( |
+ newRect.location(), oldRect.size(), newRect.size(), |
+ reason == PaintInvalidationIncremental ? m_box.borderBottom() : 0); |
if (rightDelta.isEmpty() && bottomDelta.isEmpty()) |
return false; |
ObjectPaintInvalidator objectPaintInvalidator(m_box); |
objectPaintInvalidator.invalidatePaintUsingContainer( |
- *m_context.paintInvalidationContainer, rightDelta, |
- PaintInvalidationIncremental); |
+ *m_context.paintInvalidationContainer, rightDelta, reason); |
objectPaintInvalidator.invalidatePaintUsingContainer( |
- *m_context.paintInvalidationContainer, bottomDelta, |
- PaintInvalidationIncremental); |
+ *m_context.paintInvalidationContainer, bottomDelta, reason); |
return true; |
} |
@@ -136,15 +121,9 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
previousContentBoxRect() != m_box.contentBoxRect()) |
return PaintInvalidationContentBoxChange; |
- if (style.backgroundLayers().thisOrNextLayersHaveLocalAttachment() && |
- previousLayoutOverflowRect() != m_box.layoutOverflowRect()) |
- return PaintInvalidationLayoutOverflowBoxChange; |
- |
- LayoutSize oldBorderBoxSize = |
- previousBorderBoxSize(m_context.oldVisualRect.size()); |
+ LayoutSize oldBorderBoxSize = previousBorderBoxSize(); |
LayoutSize newBorderBoxSize = m_box.size(); |
bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; |
- |
if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) |
return PaintInvalidationNone; |
@@ -182,15 +161,124 @@ PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { |
return PaintInvalidationIncremental; |
} |
+bool BoxPaintInvalidator::backgroundGeometryDependsOnLayoutOverflowRect() { |
+ return !m_box.isDocumentElement() && !m_box.backgroundStolenForBeingBody() && |
+ m_box.styleRef() |
+ .backgroundLayers() |
+ .thisOrNextLayersHaveLocalAttachment(); |
+} |
+ |
+// Background positioning in layout overflow rect doesn't mean it will |
+// paint onto the scrolling contents layer because some conditions prevent |
+// it from that. We may also treat non-local solid color backgrounds as local |
+// and paint onto the scrolling contents layer. |
+// See PaintLayer::canPaintBackgroundOntoScrollingContentsLayer(). |
+bool BoxPaintInvalidator::backgroundPaintsOntoScrollingContentsLayer() { |
+ if (m_box.isDocumentElement() || m_box.backgroundStolenForBeingBody()) |
+ return false; |
+ if (!m_box.hasLayer()) |
+ return false; |
+ if (auto* mapping = m_box.layer()->compositedLayerMapping()) |
+ return mapping->backgroundPaintsOntoScrollingContentsLayer(); |
+ return false; |
+} |
+ |
+bool BoxPaintInvalidator::shouldFullyInvalidateBackgroundOnLayoutOverflowChange( |
+ const LayoutRect& oldLayoutOverflow, |
+ const LayoutRect& newLayoutOverflow) { |
+ DCHECK(oldLayoutOverflow != newLayoutOverflow); |
+ if (newLayoutOverflow.isEmpty() || oldLayoutOverflow.isEmpty()) |
+ return true; |
+ if (newLayoutOverflow.location() != oldLayoutOverflow.location()) |
+ return true; |
+ if (newLayoutOverflow.width() != oldLayoutOverflow.width() && |
+ m_box.mustInvalidateFillLayersPaintOnHeightChange( |
+ m_box.styleRef().backgroundLayers())) |
+ return true; |
+ if (newLayoutOverflow.height() != oldLayoutOverflow.height() && |
+ m_box.mustInvalidateFillLayersPaintOnHeightChange( |
+ m_box.styleRef().backgroundLayers())) |
+ return true; |
+ return false; |
+} |
+ |
+void BoxPaintInvalidator::invalidateScrollingContentsBackgroundIfNeeded() { |
+ bool paintsOntoScrollingContentsLayer = |
+ backgroundPaintsOntoScrollingContentsLayer(); |
+ if (!paintsOntoScrollingContentsLayer && |
+ !backgroundGeometryDependsOnLayoutOverflowRect()) |
+ return; |
+ |
+ const LayoutRect& oldLayoutOverflow = previousLayoutOverflowRect(); |
+ LayoutRect newLayoutOverflow = m_box.layoutOverflowRect(); |
+ |
+ bool shouldFullyInvalidateOnScrollingContentsLayer = false; |
+ if (m_box.backgroundChangedSinceLastPaintInvalidation()) { |
+ if (!paintsOntoScrollingContentsLayer) { |
+ // The box should have been set needing full invalidation on style change. |
+ DCHECK(m_box.shouldDoFullPaintInvalidation()); |
+ return; |
+ } |
+ shouldFullyInvalidateOnScrollingContentsLayer = true; |
+ } else { |
+ // Check change of layout overflow for incremental invalidation. |
+ if (!m_box.hasPreviousBoxGeometries() || |
+ newLayoutOverflow == oldLayoutOverflow) |
+ return; |
+ if (!paintsOntoScrollingContentsLayer) { |
+ if (shouldFullyInvalidateBackgroundOnLayoutOverflowChange( |
+ oldLayoutOverflow, newLayoutOverflow)) { |
+ m_box.getMutableForPainting().setShouldDoFullPaintInvalidation( |
+ PaintInvalidationLayoutOverflowBoxChange); |
+ } |
+ return; |
+ } |
+ shouldFullyInvalidateOnScrollingContentsLayer = |
+ shouldFullyInvalidateBackgroundOnLayoutOverflowChange( |
+ oldLayoutOverflow, newLayoutOverflow); |
+ } |
+ |
+ if (shouldFullyInvalidateOnScrollingContentsLayer) { |
+ ObjectPaintInvalidatorWithContext(m_box, m_context) |
+ .fullyInvalidatePaint( |
+ PaintInvalidationBackgroundOnScrollingContentsLayer, |
+ oldLayoutOverflow, newLayoutOverflow); |
+ } else { |
+ incrementallyInvalidatePaint( |
+ PaintInvalidationBackgroundOnScrollingContentsLayer, oldLayoutOverflow, |
+ newLayoutOverflow); |
+ } |
+ |
+ m_context.paintingLayer->setNeedsRepaint(); |
+ // Currently we use CompositedLayerMapping as the DisplayItemClient to paint |
+ // background on the scrolling contents layer. |
+ ObjectPaintInvalidator(m_box).invalidateDisplayItemClient( |
+ *m_box.layer()->compositedLayerMapping()->scrollingContentsLayer(), |
+ PaintInvalidationBackgroundOnScrollingContentsLayer); |
+} |
+ |
PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() { |
+ invalidateScrollingContentsBackgroundIfNeeded(); |
+ |
PaintInvalidationReason reason = computePaintInvalidationReason(); |
if (reason == PaintInvalidationIncremental) { |
- if (incrementallyInvalidatePaint()) { |
+ bool invalidated; |
+ if (m_box.isLayoutView() && |
+ !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
+ invalidated = incrementallyInvalidatePaint( |
+ reason, m_context.oldVisualRect, m_context.newVisualRect); |
+ } else { |
+ invalidated = incrementallyInvalidatePaint( |
+ reason, LayoutRect(m_context.oldLocation, previousBorderBoxSize()), |
+ LayoutRect(m_context.newLocation, m_box.size())); |
+ } |
+ if (invalidated) { |
m_context.paintingLayer->setNeedsRepaint(); |
m_box.invalidateDisplayItemClients(reason); |
} else { |
reason = PaintInvalidationNone; |
} |
+ |
// Though we have done incremental invalidation, we still need to call |
// ObjectPaintInvalidator with PaintInvalidationNone to do any other |
// required operations. |
@@ -237,8 +325,9 @@ bool BoxPaintInvalidator::needsToSavePreviousBoxGeometries() { |
// Background and mask layers can depend on other boxes than border box. See |
// crbug.com/490533 |
if (style.backgroundLayers().thisOrNextLayersUseContentBox() || |
- style.backgroundLayers().thisOrNextLayersHaveLocalAttachment() || |
- style.maskLayers().thisOrNextLayersUseContentBox()) |
+ style.maskLayers().thisOrNextLayersUseContentBox() || |
+ backgroundGeometryDependsOnLayoutOverflowRect() || |
+ backgroundPaintsOntoScrollingContentsLayer()) |
return true; |
return false; |
@@ -255,14 +344,13 @@ void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { |
return; |
} |
- PreviousBoxGeometries Geometries = {m_box.size(), m_box.contentBoxRect(), |
+ PreviousBoxGeometries geometries = {m_box.size(), m_box.contentBoxRect(), |
m_box.layoutOverflowRect()}; |
- previousBoxGeometriesMap().set(&m_box, Geometries); |
+ previousBoxGeometriesMap().set(&m_box, geometries); |
m_box.getMutableForPainting().setHasPreviousBoxGeometries(true); |
} |
-LayoutSize BoxPaintInvalidator::previousBorderBoxSize( |
- const LayoutSize& previousVisualRectSize) { |
+LayoutSize BoxPaintInvalidator::previousBorderBoxSize() { |
DCHECK(m_box.hasPreviousBoxGeometries() == |
previousBoxGeometriesMap().contains(&m_box)); |
if (m_box.hasPreviousBoxGeometries()) |
@@ -270,7 +358,7 @@ LayoutSize BoxPaintInvalidator::previousBorderBoxSize( |
// We didn't save the old border box size because it was the same as the size |
// of oldVisualRect. |
- return previousVisualRectSize; |
+ return m_context.oldVisualRect.size(); |
} |
LayoutRect BoxPaintInvalidator::previousContentBoxRect() { |