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

Side by Side Diff: third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp

Issue 2498823002: Paint invalidation of local attachment backgrounds (Closed)
Patch Set: - Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/BoxPaintInvalidator.h" 5 #include "core/paint/BoxPaintInvalidator.h"
6 6
7 #include "core/frame/Settings.h" 7 #include "core/frame/Settings.h"
8 #include "core/layout/LayoutView.h" 8 #include "core/layout/LayoutView.h"
9 #include "core/layout/compositing/CompositedLayerMapping.h"
9 #include "core/paint/ObjectPaintInvalidator.h" 10 #include "core/paint/ObjectPaintInvalidator.h"
10 #include "core/paint/PaintInvalidator.h" 11 #include "core/paint/PaintInvalidator.h"
11 #include "core/paint/PaintLayer.h" 12 #include "core/paint/PaintLayer.h"
12 #include "core/paint/PaintLayerScrollableArea.h" 13 #include "core/paint/PaintLayerScrollableArea.h"
13 #include "platform/geometry/LayoutRect.h" 14 #include "platform/geometry/LayoutRect.h"
14 15
15 namespace blink { 16 namespace blink {
16 17
17 struct PreviousBoxGeometries { 18 struct PreviousBoxGeometries {
18 LayoutSize borderBoxSize; 19 LayoutSize borderBoxSize;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 newSize.width(), delta + extraHeight); 62 newSize.width(), delta + extraHeight);
62 } 63 }
63 if (delta < 0) { 64 if (delta < 0) {
64 return LayoutRect(location.x(), 65 return LayoutRect(location.x(),
65 location.y() + newSize.height() - extraHeight, 66 location.y() + newSize.height() - extraHeight,
66 oldSize.width(), -delta + extraHeight); 67 oldSize.width(), -delta + extraHeight);
67 } 68 }
68 return LayoutRect(); 69 return LayoutRect();
69 } 70 }
70 71
71 bool BoxPaintInvalidator::incrementallyInvalidatePaint() { 72 bool BoxPaintInvalidator::incrementallyInvalidatePaint(
72 LayoutRect rightDelta; 73 PaintInvalidationReason reason,
73 LayoutRect bottomDelta; 74 const LayoutRect& oldRect,
74 if (m_box.isLayoutView() && 75 const LayoutRect& newRect) {
75 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { 76 DCHECK(oldRect.location() == newRect.location());
76 // This corresponds to the special case in computePaintInvalidationReason() 77 LayoutRect rightDelta = computeRightDelta(
77 // for LayoutView in non-rootLayerScrolling mode. 78 newRect.location(), oldRect.size(), newRect.size(),
78 DCHECK(m_context.oldVisualRect.location() == 79 reason == PaintInvalidationIncremental ? m_box.borderRight() : 0);
79 m_context.newVisualRect.location()); 80 LayoutRect bottomDelta = computeBottomDelta(
80 rightDelta = computeRightDelta(m_context.newVisualRect.location(), 81 newRect.location(), oldRect.size(), newRect.size(),
81 m_context.oldVisualRect.size(), 82 reason == PaintInvalidationIncremental ? m_box.borderBottom() : 0);
82 m_context.newVisualRect.size(), 0);
83 bottomDelta = computeBottomDelta(m_context.newVisualRect.location(),
84 m_context.oldVisualRect.size(),
85 m_context.newVisualRect.size(), 0);
86 } else {
87 LayoutSize oldBorderBoxSize =
88 previousBorderBoxSize(m_context.oldVisualRect.size());
89 LayoutSize newBorderBoxSize = m_box.size();
90 DCHECK(m_context.oldLocation == m_context.newLocation);
91 rightDelta = computeRightDelta(m_context.newLocation, oldBorderBoxSize,
92 newBorderBoxSize, m_box.borderRight());
93 bottomDelta = computeBottomDelta(m_context.newLocation, oldBorderBoxSize,
94 newBorderBoxSize, m_box.borderBottom());
95 }
96 83
97 if (rightDelta.isEmpty() && bottomDelta.isEmpty()) 84 if (rightDelta.isEmpty() && bottomDelta.isEmpty())
98 return false; 85 return false;
99 86
100 ObjectPaintInvalidator objectPaintInvalidator(m_box); 87 ObjectPaintInvalidator objectPaintInvalidator(m_box);
101 objectPaintInvalidator.invalidatePaintUsingContainer( 88 objectPaintInvalidator.invalidatePaintUsingContainer(
102 *m_context.paintInvalidationContainer, rightDelta, 89 *m_context.paintInvalidationContainer, rightDelta, reason);
103 PaintInvalidationIncremental);
104 objectPaintInvalidator.invalidatePaintUsingContainer( 90 objectPaintInvalidator.invalidatePaintUsingContainer(
105 *m_context.paintInvalidationContainer, bottomDelta, 91 *m_context.paintInvalidationContainer, bottomDelta, reason);
106 PaintInvalidationIncremental);
107 return true; 92 return true;
108 } 93 }
109 94
110 PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() { 95 PaintInvalidationReason BoxPaintInvalidator::computePaintInvalidationReason() {
111 PaintInvalidationReason reason = 96 PaintInvalidationReason reason =
112 ObjectPaintInvalidatorWithContext(m_box, m_context) 97 ObjectPaintInvalidatorWithContext(m_box, m_context)
113 .computePaintInvalidationReason(); 98 .computePaintInvalidationReason();
114 99
115 if (reason != PaintInvalidationIncremental) 100 if (reason != PaintInvalidationIncremental)
116 return reason; 101 return reason;
(...skipping 12 matching lines...) Expand all
129 } 114 }
130 115
131 const ComputedStyle& style = m_box.styleRef(); 116 const ComputedStyle& style = m_box.styleRef();
132 117
133 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || 118 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() ||
134 style.maskLayers().thisOrNextLayersUseContentBox() || 119 style.maskLayers().thisOrNextLayersUseContentBox() ||
135 style.boxSizing() == BoxSizingBorderBox) && 120 style.boxSizing() == BoxSizingBorderBox) &&
136 previousContentBoxRect() != m_box.contentBoxRect()) 121 previousContentBoxRect() != m_box.contentBoxRect())
137 return PaintInvalidationContentBoxChange; 122 return PaintInvalidationContentBoxChange;
138 123
139 if (style.backgroundLayers().thisOrNextLayersHaveLocalAttachment() && 124 LayoutSize oldBorderBoxSize = previousBorderBoxSize();
140 previousLayoutOverflowRect() != m_box.layoutOverflowRect())
141 return PaintInvalidationLayoutOverflowBoxChange;
142
143 LayoutSize oldBorderBoxSize =
144 previousBorderBoxSize(m_context.oldVisualRect.size());
145 LayoutSize newBorderBoxSize = m_box.size(); 125 LayoutSize newBorderBoxSize = m_box.size();
146 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; 126 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize;
147
148 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) 127 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect)
149 return PaintInvalidationNone; 128 return PaintInvalidationNone;
150 129
151 // If either border box changed or bounds changed, and old or new border box 130 // If either border box changed or bounds changed, and old or new border box
152 // doesn't equal old or new bounds, incremental invalidation is not 131 // doesn't equal old or new bounds, incremental invalidation is not
153 // applicable. This captures the following cases: 132 // applicable. This captures the following cases:
154 // - pixel snapping of paint invalidation bounds, 133 // - pixel snapping of paint invalidation bounds,
155 // - scale, rotate, skew etc. transforms, 134 // - scale, rotate, skew etc. transforms,
156 // - visual overflows. 135 // - visual overflows.
157 if (m_context.oldVisualRect != 136 if (m_context.oldVisualRect !=
(...skipping 17 matching lines...) Expand all
175 if (oldBorderBoxSize.width() != newBorderBoxSize.width() && 154 if (oldBorderBoxSize.width() != newBorderBoxSize.width() &&
176 m_box.mustInvalidateBackgroundOrBorderPaintOnWidthChange()) 155 m_box.mustInvalidateBackgroundOrBorderPaintOnWidthChange())
177 return PaintInvalidationBorderBoxChange; 156 return PaintInvalidationBorderBoxChange;
178 if (oldBorderBoxSize.height() != newBorderBoxSize.height() && 157 if (oldBorderBoxSize.height() != newBorderBoxSize.height() &&
179 m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange()) 158 m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange())
180 return PaintInvalidationBorderBoxChange; 159 return PaintInvalidationBorderBoxChange;
181 160
182 return PaintInvalidationIncremental; 161 return PaintInvalidationIncremental;
183 } 162 }
184 163
164 bool BoxPaintInvalidator::backgroundGeometryDependsOnLayoutOverflowRect() {
165 return m_box.styleRef()
166 .backgroundLayers()
167 .thisOrNextLayersHaveLocalAttachment();
168 }
169
170 // Background positioning in layout overflow rect doesn't mean it will
171 // paint onto the scrolling contents layer because some conditions prevent
172 // it from that. We may also treat non-local solid color backgrounds as local
173 // and paint onto the scrolling contents layer.
174 // See PaintLayer::canPaintBackgroundOntoScrollingContentsLayer().
175 bool BoxPaintInvalidator::backgroundPaintsOntoScrollingContentsLayer() {
176 if (!m_box.hasLayer())
177 return false;
178 if (auto* mapping = m_box.layer()->compositedLayerMapping())
179 return mapping->backgroundPaintsOntoScrollingContentsLayer();
180 return false;
181 }
182
183 bool BoxPaintInvalidator::shouldFullyInvalidateBackgroundOnLayoutOverflowChange(
184 const LayoutRect& oldLayoutOverflow,
185 const LayoutRect& newLayoutOverflow) {
186 DCHECK(oldLayoutOverflow != newLayoutOverflow);
187 if (newLayoutOverflow.isEmpty() || oldLayoutOverflow.isEmpty())
188 return true;
189 if (newLayoutOverflow.location() != oldLayoutOverflow.location())
190 return true;
191 if (newLayoutOverflow.width() != oldLayoutOverflow.width() &&
192 m_box.mustInvalidateFillLayersPaintOnHeightChange(
chrishtr 2016/11/17 20:42:36 This part seems to be new in this CL. What is it f
Xianzhu 2016/11/17 23:36:41 Previously we always fully invalidated the scrolli
193 m_box.styleRef().backgroundLayers()))
194 return true;
195 if (newLayoutOverflow.height() != oldLayoutOverflow.height() &&
196 m_box.mustInvalidateFillLayersPaintOnHeightChange(
197 m_box.styleRef().backgroundLayers()))
198 return true;
199 return false;
200 }
201
202 void BoxPaintInvalidator::invalidateScrollingContentsBackgroundIfNeeded() {
203 bool paintsOntoScrollingContentsLayer =
204 backgroundPaintsOntoScrollingContentsLayer();
205 if (!paintsOntoScrollingContentsLayer &&
206 !backgroundGeometryDependsOnLayoutOverflowRect())
207 return;
208
209 const LayoutRect& oldLayoutOverflow = previousLayoutOverflowRect();
210 LayoutRect newLayoutOverflow = m_box.layoutOverflowRect();
211
212 bool shouldFullyInvalidateOnScrollingContentsLayer = false;
213 if (m_box.backgroundChangedSinceLastPaintInvalidation()) {
214 if (!paintsOntoScrollingContentsLayer) {
215 // The box should have been set needing full invalidation on style change.
216 DCHECK(m_box.shouldDoFullPaintInvalidation());
217 return;
218 }
219 shouldFullyInvalidateOnScrollingContentsLayer = true;
220 } else {
221 // Check change of layout overflow for incremental invalidation.
222 if (!m_box.hasPreviousBoxGeometries() ||
223 newLayoutOverflow == oldLayoutOverflow)
224 return;
225 if (!paintsOntoScrollingContentsLayer) {
226 if (m_box.isLayoutView() &&
chrishtr 2016/11/17 20:42:36 Where did the implementation of 226-234 used to be
Xianzhu 2016/11/17 23:36:41 See my last comment. The LayoutView condition is
227 !RuntimeEnabledFeatures::rootLayerScrollingEnabled())
228 return;
229 if (shouldFullyInvalidateBackgroundOnLayoutOverflowChange(
230 oldLayoutOverflow, newLayoutOverflow)) {
231 m_box.getMutableForPainting().setShouldDoFullPaintInvalidation(
232 PaintInvalidationLayoutOverflowBoxChange);
233 }
234 return;
235 }
236 shouldFullyInvalidateOnScrollingContentsLayer =
237 shouldFullyInvalidateBackgroundOnLayoutOverflowChange(
238 oldLayoutOverflow, newLayoutOverflow);
239 }
240
241 if (shouldFullyInvalidateOnScrollingContentsLayer ||
242 oldLayoutOverflow.isEmpty() || newLayoutOverflow.isEmpty()) {
chrishtr 2016/11/17 20:42:36 Maybe move line 242 up and use the condition to se
Xianzhu 2016/11/17 23:36:41 Just noticed I already had the conditions in shoul
243 ObjectPaintInvalidatorWithContext(m_box, m_context)
244 .fullyInvalidatePaint(
245 PaintInvalidationBackgroundOnScrollingContentsLayer,
246 oldLayoutOverflow, newLayoutOverflow);
247 } else {
248 incrementallyInvalidatePaint(
249 PaintInvalidationBackgroundOnScrollingContentsLayer, oldLayoutOverflow,
250 newLayoutOverflow);
251 }
252
253 m_context.paintingLayer->setNeedsRepaint();
254 // Currently we use CompositedLayerMapping as the DisplayItemClient to paint
255 // background on the scrolling contents layer.
256 ObjectPaintInvalidator(m_box).invalidateDisplayItemClient(
257 *m_box.layer()->compositedLayerMapping()->scrollingContentsLayer(),
258 PaintInvalidationBackgroundOnScrollingContentsLayer);
259 }
260
185 PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() { 261 PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() {
262 invalidateScrollingContentsBackgroundIfNeeded();
263
186 PaintInvalidationReason reason = computePaintInvalidationReason(); 264 PaintInvalidationReason reason = computePaintInvalidationReason();
187 if (reason == PaintInvalidationIncremental) { 265 if (reason == PaintInvalidationIncremental) {
188 if (incrementallyInvalidatePaint()) { 266 bool invalidated;
267 if (m_box.isLayoutView() &&
268 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
269 invalidated = incrementallyInvalidatePaint(
270 reason, m_context.oldVisualRect, m_context.newVisualRect);
271 } else {
272 invalidated = incrementallyInvalidatePaint(
273 reason, LayoutRect(m_context.oldLocation, previousBorderBoxSize()),
274 LayoutRect(m_context.newLocation, m_box.size()));
275 }
276 if (invalidated) {
189 m_context.paintingLayer->setNeedsRepaint(); 277 m_context.paintingLayer->setNeedsRepaint();
190 m_box.invalidateDisplayItemClients(reason); 278 m_box.invalidateDisplayItemClients(reason);
191 } else { 279 } else {
192 reason = PaintInvalidationNone; 280 reason = PaintInvalidationNone;
193 } 281 }
282
194 // Though we have done incremental invalidation, we still need to call 283 // Though we have done incremental invalidation, we still need to call
195 // ObjectPaintInvalidator with PaintInvalidationNone to do any other 284 // ObjectPaintInvalidator with PaintInvalidationNone to do any other
196 // required operations. 285 // required operations.
197 reason = std::max( 286 reason = std::max(
198 reason, 287 reason,
199 ObjectPaintInvalidatorWithContext(m_box, m_context) 288 ObjectPaintInvalidatorWithContext(m_box, m_context)
200 .invalidatePaintIfNeededWithComputedReason(PaintInvalidationNone)); 289 .invalidatePaintIfNeededWithComputedReason(PaintInvalidationNone));
201 } else { 290 } else {
202 reason = ObjectPaintInvalidatorWithContext(m_box, m_context) 291 reason = ObjectPaintInvalidatorWithContext(m_box, m_context)
203 .invalidatePaintIfNeededWithComputedReason(reason); 292 .invalidatePaintIfNeededWithComputedReason(reason);
(...skipping 26 matching lines...) Expand all
230 return true; 319 return true;
231 320
232 // No need to save old border box size if we can use size of the old paint 321 // No need to save old border box size if we can use size of the old paint
233 // rect as the old border box size in the next invalidation. 322 // rect as the old border box size in the next invalidation.
234 if (paintInvalidationSize != m_box.size()) 323 if (paintInvalidationSize != m_box.size())
235 return true; 324 return true;
236 325
237 // Background and mask layers can depend on other boxes than border box. See 326 // Background and mask layers can depend on other boxes than border box. See
238 // crbug.com/490533 327 // crbug.com/490533
239 if (style.backgroundLayers().thisOrNextLayersUseContentBox() || 328 if (style.backgroundLayers().thisOrNextLayersUseContentBox() ||
240 style.backgroundLayers().thisOrNextLayersHaveLocalAttachment() || 329 style.maskLayers().thisOrNextLayersUseContentBox() ||
241 style.maskLayers().thisOrNextLayersUseContentBox()) 330 backgroundGeometryDependsOnLayoutOverflowRect() ||
331 backgroundPaintsOntoScrollingContentsLayer())
242 return true; 332 return true;
243 333
244 return false; 334 return false;
245 } 335 }
246 336
247 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { 337 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() {
248 DCHECK(m_box.hasPreviousBoxGeometries() == 338 DCHECK(m_box.hasPreviousBoxGeometries() ==
249 previousBoxGeometriesMap().contains(&m_box)); 339 previousBoxGeometriesMap().contains(&m_box));
250 if (!needsToSavePreviousBoxGeometries()) { 340 if (!needsToSavePreviousBoxGeometries()) {
251 if (m_box.hasPreviousBoxGeometries()) { 341 if (m_box.hasPreviousBoxGeometries()) {
252 previousBoxGeometriesMap().remove(&m_box); 342 previousBoxGeometriesMap().remove(&m_box);
253 m_box.getMutableForPainting().setHasPreviousBoxGeometries(false); 343 m_box.getMutableForPainting().setHasPreviousBoxGeometries(false);
254 } 344 }
255 return; 345 return;
256 } 346 }
257 347
258 PreviousBoxGeometries Geometries = {m_box.size(), m_box.contentBoxRect(), 348 PreviousBoxGeometries geometries = {m_box.size(), m_box.contentBoxRect(),
259 m_box.layoutOverflowRect()}; 349 m_box.layoutOverflowRect()};
260 previousBoxGeometriesMap().set(&m_box, Geometries); 350 previousBoxGeometriesMap().set(&m_box, geometries);
261 m_box.getMutableForPainting().setHasPreviousBoxGeometries(true); 351 m_box.getMutableForPainting().setHasPreviousBoxGeometries(true);
262 } 352 }
263 353
264 LayoutSize BoxPaintInvalidator::previousBorderBoxSize( 354 LayoutSize BoxPaintInvalidator::previousBorderBoxSize() {
265 const LayoutSize& previousVisualRectSize) {
266 DCHECK(m_box.hasPreviousBoxGeometries() == 355 DCHECK(m_box.hasPreviousBoxGeometries() ==
267 previousBoxGeometriesMap().contains(&m_box)); 356 previousBoxGeometriesMap().contains(&m_box));
268 if (m_box.hasPreviousBoxGeometries()) 357 if (m_box.hasPreviousBoxGeometries())
269 return previousBoxGeometriesMap().get(&m_box).borderBoxSize; 358 return previousBoxGeometriesMap().get(&m_box).borderBoxSize;
270 359
271 // We didn't save the old border box size because it was the same as the size 360 // We didn't save the old border box size because it was the same as the size
272 // of oldVisualRect. 361 // of oldVisualRect.
273 return previousVisualRectSize; 362 return m_context.oldVisualRect.size();
274 } 363 }
275 364
276 LayoutRect BoxPaintInvalidator::previousContentBoxRect() { 365 LayoutRect BoxPaintInvalidator::previousContentBoxRect() {
277 DCHECK(m_box.hasPreviousBoxGeometries() == 366 DCHECK(m_box.hasPreviousBoxGeometries() ==
278 previousBoxGeometriesMap().contains(&m_box)); 367 previousBoxGeometriesMap().contains(&m_box));
279 return m_box.hasPreviousBoxGeometries() 368 return m_box.hasPreviousBoxGeometries()
280 ? previousBoxGeometriesMap().get(&m_box).contentBoxRect 369 ? previousBoxGeometriesMap().get(&m_box).contentBoxRect
281 : LayoutRect(); 370 : LayoutRect();
282 } 371 }
283 372
284 LayoutRect BoxPaintInvalidator::previousLayoutOverflowRect() { 373 LayoutRect BoxPaintInvalidator::previousLayoutOverflowRect() {
285 DCHECK(m_box.hasPreviousBoxGeometries() == 374 DCHECK(m_box.hasPreviousBoxGeometries() ==
286 previousBoxGeometriesMap().contains(&m_box)); 375 previousBoxGeometriesMap().contains(&m_box));
287 return m_box.hasPreviousBoxGeometries() 376 return m_box.hasPreviousBoxGeometries()
288 ? previousBoxGeometriesMap().get(&m_box).layoutOverflowRect 377 ? previousBoxGeometriesMap().get(&m_box).layoutOverflowRect
289 : LayoutRect(); 378 : LayoutRect();
290 } 379 }
291 380
292 } // namespace blink 381 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698