OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |