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/ObjectPaintInvalidator.h" | 5 #include "core/paint/ObjectPaintInvalidator.h" |
6 | 6 |
7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
8 #include "core/frame/LocalFrame.h" | 8 #include "core/frame/LocalFrame.h" |
9 #include "core/layout/LayoutBlockFlow.h" | 9 #include "core/layout/LayoutBlockFlow.h" |
10 #include "core/layout/LayoutView.h" | 10 #include "core/layout/LayoutView.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 // TODO(trchen): Use std::function<void, LayoutObject&> when available. | 41 // TODO(trchen): Use std::function<void, LayoutObject&> when available. |
42 template <typename LayoutObjectTraversalFunctor> | 42 template <typename LayoutObjectTraversalFunctor> |
43 void traverseNonCompositingDescendantsInPaintOrder( | 43 void traverseNonCompositingDescendantsInPaintOrder( |
44 const LayoutObject&, | 44 const LayoutObject&, |
45 const LayoutObjectTraversalFunctor&); | 45 const LayoutObjectTraversalFunctor&); |
46 | 46 |
47 template <typename LayoutObjectTraversalFunctor> | 47 template <typename LayoutObjectTraversalFunctor> |
48 void traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationContai
ner( | 48 void traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationContai
ner( |
49 const LayoutObject& object, | 49 const LayoutObject& object, |
50 const LayoutObjectTraversalFunctor& functor) { | 50 const LayoutObjectTraversalFunctor& functor) { |
51 // |object| is a paint invalidation container but is not a stacking context, s
o the paint | 51 // |object| is a paint invalidation container but is not a stacking context, |
52 // invalidation container of stacked descendants don't belong to |object| but
belong to | 52 // so the paint invalidation container of stacked descendants don't belong to |
53 // an ancestor. This function traverses all such descendants. | 53 // |object| but belong to an ancestor. This function traverses all such |
| 54 // descendants. |
54 DCHECK(object.isPaintInvalidationContainer() && | 55 DCHECK(object.isPaintInvalidationContainer() && |
55 !object.styleRef().isStackingContext()); | 56 !object.styleRef().isStackingContext()); |
56 | 57 |
57 LayoutObject* descendant = object.nextInPreOrder(&object); | 58 LayoutObject* descendant = object.nextInPreOrder(&object); |
58 while (descendant) { | 59 while (descendant) { |
59 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) { | 60 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) { |
60 // Case 1: The descendant is not stacked (or is stacked but has not been | 61 // Case 1: The descendant is not stacked (or is stacked but has not been |
61 // allocated a layer yet during style change), so either it's a paint inva
lidation | 62 // allocated a layer yet during style change), so either it's a paint |
62 // container in the same situation as |object|, or its paint invalidation | 63 // invalidation container in the same situation as |object|, or its paint |
63 // container is in such situation. Keep searching until a stacked layer is
found. | 64 // invalidation container is in such situation. Keep searching until a |
| 65 // stacked layer is found. |
64 descendant = descendant->nextInPreOrder(&object); | 66 descendant = descendant->nextInPreOrder(&object); |
65 } else if (!descendant->isPaintInvalidationContainer()) { | 67 } else if (!descendant->isPaintInvalidationContainer()) { |
66 // Case 2: The descendant is stacked and is not composited. | 68 // Case 2: The descendant is stacked and is not composited. |
67 // The invalidation container of its subtree is our ancestor, | 69 // The invalidation container of its subtree is our ancestor, |
68 // thus recur into the subtree. | 70 // thus recur into the subtree. |
69 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor); | 71 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor); |
70 descendant = descendant->nextInPreOrderAfterChildren(&object); | 72 descendant = descendant->nextInPreOrderAfterChildren(&object); |
71 } else if (descendant->styleRef().isStackingContext()) { | 73 } else if (descendant->styleRef().isStackingContext()) { |
72 // Case 3: The descendant is an invalidation container and is a stacking c
ontext. | 74 // Case 3: The descendant is an invalidation container and is a stacking |
73 // No objects in the subtree can have invalidation container outside of it
, | 75 // context. No objects in the subtree can have invalidation container |
74 // thus skip the whole subtree. | 76 // outside of it, thus skip the whole subtree. |
75 descendant = descendant->nextInPreOrderAfterChildren(&object); | 77 descendant = descendant->nextInPreOrderAfterChildren(&object); |
76 } else { | 78 } else { |
77 // Case 4: The descendant is an invalidation container but not a stacking
context. | 79 // Case 4: The descendant is an invalidation container but not a stacking |
78 // This is the same situation as |object|, thus keep searching. | 80 // context. This is the same situation as |object|, thus keep searching. |
79 descendant = descendant->nextInPreOrder(&object); | 81 descendant = descendant->nextInPreOrder(&object); |
80 } | 82 } |
81 } | 83 } |
82 } | 84 } |
83 | 85 |
84 template <typename LayoutObjectTraversalFunctor> | 86 template <typename LayoutObjectTraversalFunctor> |
85 void traverseNonCompositingDescendantsInPaintOrder( | 87 void traverseNonCompositingDescendantsInPaintOrder( |
86 const LayoutObject& object, | 88 const LayoutObject& object, |
87 const LayoutObjectTraversalFunctor& functor) { | 89 const LayoutObjectTraversalFunctor& functor) { |
88 functor(object); | 90 functor(object); |
89 LayoutObject* descendant = object.nextInPreOrder(&object); | 91 LayoutObject* descendant = object.nextInPreOrder(&object); |
90 while (descendant) { | 92 while (descendant) { |
91 if (!descendant->isPaintInvalidationContainer()) { | 93 if (!descendant->isPaintInvalidationContainer()) { |
92 functor(*descendant); | 94 functor(*descendant); |
93 descendant = descendant->nextInPreOrder(&object); | 95 descendant = descendant->nextInPreOrder(&object); |
94 } else if (descendant->styleRef().isStackingContext()) { | 96 } else if (descendant->styleRef().isStackingContext()) { |
95 // The descendant is an invalidation container and is a stacking context. | 97 // The descendant is an invalidation container and is a stacking context. |
96 // No objects in the subtree can have invalidation container outside of it
, | 98 // No objects in the subtree can have invalidation container outside of |
97 // thus skip the whole subtree. | 99 // it, thus skip the whole subtree. |
98 descendant = descendant->nextInPreOrderAfterChildren(&object); | 100 descendant = descendant->nextInPreOrderAfterChildren(&object); |
99 } else { | 101 } else { |
100 // If a paint invalidation container is not a stacking context, | 102 // If a paint invalidation container is not a stacking context, |
101 // some of its descendants may belong to the parent container. | 103 // some of its descendants may belong to the parent container. |
102 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta
iner( | 104 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta
iner( |
103 *descendant, functor); | 105 *descendant, functor); |
104 descendant = descendant->nextInPreOrderAfterChildren(&object); | 106 descendant = descendant->nextInPreOrderAfterChildren(&object); |
105 } | 107 } |
106 } | 108 } |
107 } | 109 } |
108 | 110 |
109 void ObjectPaintInvalidator:: | 111 void ObjectPaintInvalidator:: |
110 invalidateDisplayItemClientsIncludingNonCompositingDescendants( | 112 invalidateDisplayItemClientsIncludingNonCompositingDescendants( |
111 PaintInvalidationReason reason) { | 113 PaintInvalidationReason reason) { |
112 // This is valid because we want to invalidate the client in the display item
list of the current backing. | 114 // This is valid because we want to invalidate the client in the display item |
| 115 // list of the current backing. |
113 DisableCompositingQueryAsserts disabler; | 116 DisableCompositingQueryAsserts disabler; |
114 | 117 |
115 slowSetPaintingLayerNeedsRepaint(); | 118 slowSetPaintingLayerNeedsRepaint(); |
116 traverseNonCompositingDescendantsInPaintOrder( | 119 traverseNonCompositingDescendantsInPaintOrder( |
117 m_object, [reason](const LayoutObject& object) { | 120 m_object, [reason](const LayoutObject& object) { |
118 if (object.hasLayer() && | 121 if (object.hasLayer() && |
119 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) | 122 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) |
120 toLayoutBoxModelObject(object).layer()->setNeedsRepaint(); | 123 toLayoutBoxModelObject(object).layer()->setNeedsRepaint(); |
121 object.invalidateDisplayItemClients(reason); | 124 object.invalidateDisplayItemClients(reason); |
122 }); | 125 }); |
123 } | 126 } |
124 | 127 |
125 DISABLE_CFI_PERF | 128 DISABLE_CFI_PERF |
126 void ObjectPaintInvalidator::invalidatePaintOfPreviousPaintInvalidationRect( | 129 void ObjectPaintInvalidator::invalidatePaintOfPreviousPaintInvalidationRect( |
127 const LayoutBoxModelObject& paintInvalidationContainer, | 130 const LayoutBoxModelObject& paintInvalidationContainer, |
128 PaintInvalidationReason reason) { | 131 PaintInvalidationReason reason) { |
129 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's needsRe
paint is set. | 132 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's |
130 // Don't set the flag here because getting enclosingSelfPaintLayer has cost an
d the caller can use | 133 // needsRepaint is set. Don't set the flag here because getting |
131 // various ways (e.g. PaintInvalidatinState::enclosingSelfPaintingLayer()) to
reduce the cost. | 134 // enclosingSelfPaintLayer has cost and the caller can use various ways (e.g. |
| 135 // PaintInvalidatinState::enclosingSelfPaintingLayer()) to reduce the cost. |
132 DCHECK(!m_object.paintingLayer() || m_object.paintingLayer()->needsRepaint()); | 136 DCHECK(!m_object.paintingLayer() || m_object.paintingLayer()->needsRepaint()); |
133 | 137 |
134 // These disablers are valid because we want to use the current compositing/in
validation status. | 138 // These disablers are valid because we want to use the current |
| 139 // compositing/invalidation status. |
135 DisablePaintInvalidationStateAsserts invalidationDisabler; | 140 DisablePaintInvalidationStateAsserts invalidationDisabler; |
136 DisableCompositingQueryAsserts compositingDisabler; | 141 DisableCompositingQueryAsserts compositingDisabler; |
137 | 142 |
138 LayoutRect invalidationRect = m_object.previousPaintInvalidationRect(); | 143 LayoutRect invalidationRect = m_object.previousPaintInvalidationRect(); |
139 invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, | 144 invalidatePaintUsingContainer(paintInvalidationContainer, invalidationRect, |
140 reason); | 145 reason); |
141 m_object.invalidateDisplayItemClients(reason); | 146 m_object.invalidateDisplayItemClients(reason); |
142 | 147 |
143 // This method may be used to invalidate paint of an object changing paint inv
alidation container. | 148 // This method may be used to invalidate paint of an object changing paint |
144 // Clear previous paint invalidation rect on the original paint invalidation c
ontainer to avoid | 149 // invalidation container. Clear previous paint invalidation rect on the |
145 // under-invalidation if the new paint invalidation rect on the new paint inva
lidation container | 150 // original paint invalidation container to avoid under-invalidation if the |
146 // happens to be the same as the old one. | 151 // new paint invalidation rect on the new paint invalidation container happens |
| 152 // to be the same as the old one. |
147 m_object.getMutableForPainting().clearPreviousPaintInvalidationRects(); | 153 m_object.getMutableForPainting().clearPreviousPaintInvalidationRects(); |
148 } | 154 } |
149 | 155 |
150 void ObjectPaintInvalidator:: | 156 void ObjectPaintInvalidator:: |
151 invalidatePaintIncludingNonCompositingDescendants() { | 157 invalidatePaintIncludingNonCompositingDescendants() { |
152 // Since we're only painting non-composited layers, we know that they all shar
e the same paintInvalidationContainer. | 158 // Since we're only painting non-composited layers, we know that they all |
| 159 // share the same paintInvalidationContainer. |
153 const LayoutBoxModelObject& paintInvalidationContainer = | 160 const LayoutBoxModelObject& paintInvalidationContainer = |
154 m_object.containerForPaintInvalidation(); | 161 m_object.containerForPaintInvalidation(); |
155 traverseNonCompositingDescendantsInPaintOrder( | 162 traverseNonCompositingDescendantsInPaintOrder( |
156 m_object, [&paintInvalidationContainer](const LayoutObject& object) { | 163 m_object, [&paintInvalidationContainer](const LayoutObject& object) { |
157 if (object.hasLayer()) | 164 if (object.hasLayer()) |
158 toLayoutBoxModelObject(object).layer()->setNeedsRepaint(); | 165 toLayoutBoxModelObject(object).layer()->setNeedsRepaint(); |
159 ObjectPaintInvalidator(object) | 166 ObjectPaintInvalidator(object) |
160 .invalidatePaintOfPreviousPaintInvalidationRect( | 167 .invalidatePaintOfPreviousPaintInvalidationRect( |
161 paintInvalidationContainer, PaintInvalidationSubtree); | 168 paintInvalidationContainer, PaintInvalidationSubtree); |
162 }); | 169 }); |
(...skipping 18 matching lines...) Expand all Loading... |
181 invalidatePaintIncludingNonSelfPaintingLayerDescendants( | 188 invalidatePaintIncludingNonSelfPaintingLayerDescendants( |
182 const LayoutBoxModelObject& paintInvalidationContainer) { | 189 const LayoutBoxModelObject& paintInvalidationContainer) { |
183 slowSetPaintingLayerNeedsRepaint(); | 190 slowSetPaintingLayerNeedsRepaint(); |
184 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal( | 191 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal( |
185 paintInvalidationContainer); | 192 paintInvalidationContainer); |
186 } | 193 } |
187 | 194 |
188 void ObjectPaintInvalidator::invalidateDisplayItemClient( | 195 void ObjectPaintInvalidator::invalidateDisplayItemClient( |
189 const DisplayItemClient& client, | 196 const DisplayItemClient& client, |
190 PaintInvalidationReason reason) { | 197 PaintInvalidationReason reason) { |
191 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's needsRe
paint is set. | 198 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's |
192 // Don't set the flag here because getting enclosingSelfPaintLayer has cost an
d the caller can use | 199 // needsRepaint is set. Don't set the flag here because getting |
193 // various ways (e.g. PaintInvalidatinState::enclosingSelfPaintingLayer()) to
reduce the cost. | 200 // enclosingSelfPaintLayer has cost and the caller can use various ways (e.g. |
| 201 // PaintInvalidatinState::enclosingSelfPaintingLayer()) to reduce the cost. |
194 DCHECK(!m_object.paintingLayer() || m_object.paintingLayer()->needsRepaint()); | 202 DCHECK(!m_object.paintingLayer() || m_object.paintingLayer()->needsRepaint()); |
195 | 203 |
196 client.setDisplayItemsUncached(reason); | 204 client.setDisplayItemsUncached(reason); |
197 | 205 |
198 if (FrameView* frameView = m_object.frameView()) | 206 if (FrameView* frameView = m_object.frameView()) |
199 frameView->trackObjectPaintInvalidation(client, reason); | 207 frameView->trackObjectPaintInvalidation(client, reason); |
200 } | 208 } |
201 | 209 |
202 template <typename T> | 210 template <typename T> |
203 void addJsonObjectForRect(TracedValue* value, const char* name, const T& rect) { | 211 void addJsonObjectForRect(TracedValue* value, const char* name, const T& rect) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 return; | 244 return; |
237 | 245 |
238 if (HostWindow* window = frameView->getHostWindow()) | 246 if (HostWindow* window = frameView->getHostWindow()) |
239 window->invalidateRect(frameView->contentsToRootFrame(paintRect)); | 247 window->invalidateRect(frameView->contentsToRootFrame(paintRect)); |
240 } | 248 } |
241 | 249 |
242 void ObjectPaintInvalidator::setBackingNeedsPaintInvalidationInRect( | 250 void ObjectPaintInvalidator::setBackingNeedsPaintInvalidationInRect( |
243 const LayoutBoxModelObject& paintInvalidationContainer, | 251 const LayoutBoxModelObject& paintInvalidationContainer, |
244 const LayoutRect& rect, | 252 const LayoutRect& rect, |
245 PaintInvalidationReason reason) { | 253 PaintInvalidationReason reason) { |
246 // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible c
rash here, | 254 // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible |
247 // so assert but check that the layer is composited. | 255 // crash here, so assert but check that the layer is composited. |
248 DCHECK(paintInvalidationContainer.compositingState() != NotComposited); | 256 DCHECK(paintInvalidationContainer.compositingState() != NotComposited); |
249 | 257 |
250 PaintLayer& layer = *paintInvalidationContainer.layer(); | 258 PaintLayer& layer = *paintInvalidationContainer.layer(); |
251 if (layer.groupedMapping()) { | 259 if (layer.groupedMapping()) { |
252 if (GraphicsLayer* squashingLayer = | 260 if (GraphicsLayer* squashingLayer = |
253 layer.groupedMapping()->squashingLayer()) { | 261 layer.groupedMapping()->squashingLayer()) { |
254 // Note: the subpixel accumulation of layer() does not need to be added he
re. It is already taken into account. | 262 // Note: the subpixel accumulation of layer() does not need to be added |
| 263 // here. It is already taken into account. |
255 squashingLayer->setNeedsDisplayInRect(enclosingIntRect(rect), reason, | 264 squashingLayer->setNeedsDisplayInRect(enclosingIntRect(rect), reason, |
256 m_object); | 265 m_object); |
257 } | 266 } |
258 } else if (m_object.compositedScrollsWithRespectTo( | 267 } else if (m_object.compositedScrollsWithRespectTo( |
259 paintInvalidationContainer)) { | 268 paintInvalidationContainer)) { |
260 layer.compositedLayerMapping()->setScrollingContentsNeedDisplayInRect( | 269 layer.compositedLayerMapping()->setScrollingContentsNeedDisplayInRect( |
261 rect, reason, m_object); | 270 rect, reason, m_object); |
262 } else if (paintInvalidationContainer.usesCompositedScrolling()) { | 271 } else if (paintInvalidationContainer.usesCompositedScrolling()) { |
263 if (layer.compositedLayerMapping() | 272 if (layer.compositedLayerMapping() |
264 ->backgroundPaintsOntoScrollingContentsLayer()) { | 273 ->backgroundPaintsOntoScrollingContentsLayer()) { |
265 // TODO(flackr): Get a correct rect in the context of the scrolling conten
ts layer to update | 274 // TODO(flackr): Get a correct rect in the context of the scrolling |
266 // rather than updating the entire rect. | 275 // contents layer to update rather than updating the entire rect. |
267 const LayoutRect& scrollingContentsRect = | 276 const LayoutRect& scrollingContentsRect = |
268 toLayoutBox(m_object).layoutOverflowRect(); | 277 toLayoutBox(m_object).layoutOverflowRect(); |
269 layer.compositedLayerMapping()->setScrollingContentsNeedDisplayInRect( | 278 layer.compositedLayerMapping()->setScrollingContentsNeedDisplayInRect( |
270 scrollingContentsRect, reason, m_object); | 279 scrollingContentsRect, reason, m_object); |
271 layer.setNeedsRepaint(); | 280 layer.setNeedsRepaint(); |
272 invalidateDisplayItemClient( | 281 invalidateDisplayItemClient( |
273 *layer.compositedLayerMapping()->scrollingContentsLayer(), reason); | 282 *layer.compositedLayerMapping()->scrollingContentsLayer(), reason); |
274 } | 283 } |
275 layer.compositedLayerMapping()->setNonScrollingContentsNeedDisplayInRect( | 284 layer.compositedLayerMapping()->setNonScrollingContentsNeedDisplayInRect( |
276 rect, reason, m_object); | 285 rect, reason, m_object); |
277 } else { | 286 } else { |
278 // Otherwise invalidate everything. | 287 // Otherwise invalidate everything. |
279 layer.compositedLayerMapping()->setContentsNeedDisplayInRect(rect, reason, | 288 layer.compositedLayerMapping()->setContentsNeedDisplayInRect(rect, reason, |
280 m_object); | 289 m_object); |
281 } | 290 } |
282 } | 291 } |
283 | 292 |
284 void ObjectPaintInvalidator::invalidatePaintUsingContainer( | 293 void ObjectPaintInvalidator::invalidatePaintUsingContainer( |
285 const LayoutBoxModelObject& paintInvalidationContainer, | 294 const LayoutBoxModelObject& paintInvalidationContainer, |
286 const LayoutRect& dirtyRect, | 295 const LayoutRect& dirtyRect, |
287 PaintInvalidationReason invalidationReason) { | 296 PaintInvalidationReason invalidationReason) { |
288 // TODO(wangxianzhu): Enable the following assert after paint invalidation for
spv2 is ready. | 297 // TODO(wangxianzhu): Enable the following assert after paint invalidation for |
| 298 // spv2 is ready. |
289 // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 299 // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
290 | 300 |
291 if (paintInvalidationContainer.frameView()->shouldThrottleRendering()) | 301 if (paintInvalidationContainer.frameView()->shouldThrottleRendering()) |
292 return; | 302 return; |
293 | 303 |
294 DCHECK(gDisablePaintInvalidationStateAsserts || | 304 DCHECK(gDisablePaintInvalidationStateAsserts || |
295 m_object.document().lifecycle().state() == | 305 m_object.document().lifecycle().state() == |
296 (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() | 306 (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() |
297 ? DocumentLifecycle::InPrePaint | 307 ? DocumentLifecycle::InPrePaint |
298 : DocumentLifecycle::InPaintInvalidation)); | 308 : DocumentLifecycle::InPaintInvalidation)); |
299 | 309 |
300 if (dirtyRect.isEmpty()) | 310 if (dirtyRect.isEmpty()) |
301 return; | 311 return; |
302 | 312 |
303 RELEASE_ASSERT(m_object.isRooted()); | 313 RELEASE_ASSERT(m_object.isRooted()); |
304 | 314 |
305 // FIXME: Unify "devtools.timeline.invalidationTracking" and "blink.invalidati
on". crbug.com/413527. | 315 // FIXME: Unify "devtools.timeline.invalidationTracking" and |
| 316 // "blink.invalidation". crbug.com/413527. |
306 TRACE_EVENT_INSTANT1( | 317 TRACE_EVENT_INSTANT1( |
307 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), | 318 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), |
308 "PaintInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data", | 319 "PaintInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data", |
309 InspectorPaintInvalidationTrackingEvent::data( | 320 InspectorPaintInvalidationTrackingEvent::data( |
310 &m_object, paintInvalidationContainer)); | 321 &m_object, paintInvalidationContainer)); |
311 TRACE_EVENT2( | 322 TRACE_EVENT2( |
312 TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), | 323 TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), |
313 "LayoutObject::invalidatePaintUsingContainer()", "object", | 324 "LayoutObject::invalidatePaintUsingContainer()", "object", |
314 m_object.debugName().ascii(), "info", | 325 m_object.debugName().ascii(), "info", |
315 jsonObjectForPaintInvalidationInfo( | 326 jsonObjectForPaintInvalidationInfo( |
316 dirtyRect, paintInvalidationReasonToString(invalidationReason))); | 327 dirtyRect, paintInvalidationReasonToString(invalidationReason))); |
317 | 328 |
318 // This conditional handles situations where non-rooted (and hence non-composi
ted) frames are | 329 // This conditional handles situations where non-rooted (and hence |
319 // painted, such as SVG images. | 330 // non-composited) frames are painted, such as SVG images. |
320 if (!paintInvalidationContainer.isPaintInvalidationContainer()) | 331 if (!paintInvalidationContainer.isPaintInvalidationContainer()) |
321 invalidatePaintRectangleOnWindow(paintInvalidationContainer, | 332 invalidatePaintRectangleOnWindow(paintInvalidationContainer, |
322 enclosingIntRect(dirtyRect)); | 333 enclosingIntRect(dirtyRect)); |
323 | 334 |
324 if (paintInvalidationContainer.view()->usesCompositing() && | 335 if (paintInvalidationContainer.view()->usesCompositing() && |
325 paintInvalidationContainer.isPaintInvalidationContainer()) | 336 paintInvalidationContainer.isPaintInvalidationContainer()) |
326 setBackingNeedsPaintInvalidationInRect(paintInvalidationContainer, | 337 setBackingNeedsPaintInvalidationInRect(paintInvalidationContainer, |
327 dirtyRect, invalidationReason); | 338 dirtyRect, invalidationReason); |
328 } | 339 } |
329 | 340 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 PaintInvalidationIncremental); | 412 PaintInvalidationIncremental); |
402 } | 413 } |
403 | 414 |
404 return true; | 415 return true; |
405 } | 416 } |
406 | 417 |
407 void ObjectPaintInvalidatorWithContext::fullyInvalidatePaint( | 418 void ObjectPaintInvalidatorWithContext::fullyInvalidatePaint( |
408 PaintInvalidationReason reason, | 419 PaintInvalidationReason reason, |
409 const LayoutRect& oldBounds, | 420 const LayoutRect& oldBounds, |
410 const LayoutRect& newBounds) { | 421 const LayoutRect& newBounds) { |
411 // The following logic avoids invalidating twice if one set of bounds contains
the other. | 422 // The following logic avoids invalidating twice if one set of bounds contains |
| 423 // the other. |
412 if (!newBounds.contains(oldBounds)) { | 424 if (!newBounds.contains(oldBounds)) { |
413 LayoutRect invalidationRect = oldBounds; | 425 LayoutRect invalidationRect = oldBounds; |
414 invalidatePaintUsingContainer(*m_context.paintInvalidationContainer, | 426 invalidatePaintUsingContainer(*m_context.paintInvalidationContainer, |
415 invalidationRect, reason); | 427 invalidationRect, reason); |
416 | 428 |
417 if (invalidationRect.contains(newBounds)) | 429 if (invalidationRect.contains(newBounds)) |
418 return; | 430 return; |
419 } | 431 } |
420 | 432 |
421 invalidatePaintUsingContainer(*m_context.paintInvalidationContainer, | 433 invalidatePaintUsingContainer(*m_context.paintInvalidationContainer, |
422 newBounds, reason); | 434 newBounds, reason); |
423 } | 435 } |
424 | 436 |
425 PaintInvalidationReason | 437 PaintInvalidationReason |
426 ObjectPaintInvalidatorWithContext::computePaintInvalidationReason() { | 438 ObjectPaintInvalidatorWithContext::computePaintInvalidationReason() { |
427 // This is before any early return to ensure the background obscuration status
is saved. | 439 // This is before any early return to ensure the background obscuration status |
| 440 // is saved. |
428 bool backgroundObscurationChanged = false; | 441 bool backgroundObscurationChanged = false; |
429 bool backgroundObscured = m_object.backgroundIsKnownToBeObscured(); | 442 bool backgroundObscured = m_object.backgroundIsKnownToBeObscured(); |
430 if (backgroundObscured != m_object.previousBackgroundObscured()) { | 443 if (backgroundObscured != m_object.previousBackgroundObscured()) { |
431 m_object.getMutableForPainting().setPreviousBackgroundObscured( | 444 m_object.getMutableForPainting().setPreviousBackgroundObscured( |
432 backgroundObscured); | 445 backgroundObscured); |
433 backgroundObscurationChanged = true; | 446 backgroundObscurationChanged = true; |
434 } | 447 } |
435 | 448 |
436 if (m_context.forcedSubtreeInvalidationFlags & | 449 if (m_context.forcedSubtreeInvalidationFlags & |
437 PaintInvalidatorContext::ForcedSubtreeFullInvalidation) | 450 PaintInvalidatorContext::ForcedSubtreeFullInvalidation) |
438 return PaintInvalidationSubtree; | 451 return PaintInvalidationSubtree; |
439 | 452 |
440 if (m_object.shouldDoFullPaintInvalidation()) | 453 if (m_object.shouldDoFullPaintInvalidation()) |
441 return m_object.fullPaintInvalidationReason(); | 454 return m_object.fullPaintInvalidationReason(); |
442 | 455 |
443 if (m_context.oldBounds.isEmpty() && m_context.newBounds.isEmpty()) | 456 if (m_context.oldBounds.isEmpty() && m_context.newBounds.isEmpty()) |
444 return PaintInvalidationNone; | 457 return PaintInvalidationNone; |
445 | 458 |
446 if (backgroundObscurationChanged) | 459 if (backgroundObscurationChanged) |
447 return PaintInvalidationBackgroundObscurationChange; | 460 return PaintInvalidationBackgroundObscurationChange; |
448 | 461 |
449 if (m_object.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) | 462 if (m_object.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) |
450 return PaintInvalidationNone; | 463 return PaintInvalidationNone; |
451 | 464 |
452 const ComputedStyle& style = m_object.styleRef(); | 465 const ComputedStyle& style = m_object.styleRef(); |
453 | 466 |
454 // The outline may change shape because of position change of descendants. For
simplicity, | 467 // The outline may change shape because of position change of descendants. For |
455 // just force full paint invalidation if this object is marked for checking pa
int invalidation | 468 // simplicity, just force full paint invalidation if this object is marked for |
456 // for any reason. | 469 // checking paint invalidation for any reason. |
457 // TODO(wangxianzhu): Optimize this. | 470 // TODO(wangxianzhu): Optimize this. |
458 if (style.hasOutline()) | 471 if (style.hasOutline()) |
459 return PaintInvalidationOutline; | 472 return PaintInvalidationOutline; |
460 | 473 |
461 bool locationChanged = m_context.newLocation != m_context.oldLocation; | 474 bool locationChanged = m_context.newLocation != m_context.oldLocation; |
462 | 475 |
463 // If the bounds are the same then we know that none of the statements below | 476 // If the bounds are the same then we know that none of the statements below |
464 // can match, so we can early out. However, we can't return PaintInvalidationN
one even if | 477 // can match, so we can early out. However, we can't return |
465 // !locationChagned, but conservatively return PaintInvalidationIncremental be
cause we are | 478 // PaintInvalidationNone even if !locationChagned, but conservatively return |
466 // not sure whether paint invalidation is actually needed just based on inform
ation known | 479 // PaintInvalidationIncremental because we are not sure whether paint |
467 // to LayoutObject. For example, a LayoutBox may need paint invalidation if bo
rder box changes. | 480 // invalidation is actually needed just based on information known to |
| 481 // LayoutObject. For example, a LayoutBox may need paint invalidation if |
| 482 // border box changes. |
468 if (m_context.oldBounds == m_context.newBounds) | 483 if (m_context.oldBounds == m_context.newBounds) |
469 return locationChanged ? PaintInvalidationLocationChange | 484 return locationChanged ? PaintInvalidationLocationChange |
470 : PaintInvalidationIncremental; | 485 : PaintInvalidationIncremental; |
471 | 486 |
472 // If the size is zero on one of our bounds then we know we're going to have | 487 // If the size is zero on one of our bounds then we know we're going to have |
473 // to do a full invalidation of either old bounds or new bounds. | 488 // to do a full invalidation of either old bounds or new bounds. |
474 if (m_context.oldBounds.isEmpty()) | 489 if (m_context.oldBounds.isEmpty()) |
475 return PaintInvalidationBecameVisible; | 490 return PaintInvalidationBecameVisible; |
476 if (m_context.newBounds.isEmpty()) | 491 if (m_context.newBounds.isEmpty()) |
477 return PaintInvalidationBecameInvisible; | 492 return PaintInvalidationBecameInvisible; |
478 | 493 |
479 // If we shifted, we don't know the exact reason so we are conservative and tr
igger a full invalidation. Shifting could | 494 // If we shifted, we don't know the exact reason so we are conservative and |
480 // be caused by some layout property (left / top) or some in-flow layoutObject
inserted / removed before us in the tree. | 495 // trigger a full invalidation. Shifting could be caused by some layout |
| 496 // property (left / top) or some in-flow layoutObject inserted / removed |
| 497 // before us in the tree. |
481 if (m_context.newBounds.location() != m_context.oldBounds.location()) | 498 if (m_context.newBounds.location() != m_context.oldBounds.location()) |
482 return PaintInvalidationBoundsChange; | 499 return PaintInvalidationBoundsChange; |
483 | 500 |
484 if (locationChanged) | 501 if (locationChanged) |
485 return PaintInvalidationLocationChange; | 502 return PaintInvalidationLocationChange; |
486 | 503 |
487 return PaintInvalidationIncremental; | 504 return PaintInvalidationIncremental; |
488 } | 505 } |
489 | 506 |
490 void ObjectPaintInvalidatorWithContext::invalidateSelectionIfNeeded( | 507 void ObjectPaintInvalidatorWithContext::invalidateSelectionIfNeeded( |
491 PaintInvalidationReason reason) { | 508 PaintInvalidationReason reason) { |
492 // Update selection rect when we are doing full invalidation (in case that the
object is moved, | 509 // Update selection rect when we are doing full invalidation (in case that the |
493 // composite status changed, etc.) or shouldInvalidationSelection is set (in c
ase that the | 510 // object is moved, composite status changed, etc.) or |
494 // selection itself changed). | 511 // shouldInvalidationSelection is set (in case that the selection itself |
| 512 // changed). |
495 bool fullInvalidation = isImmediateFullPaintInvalidationReason(reason); | 513 bool fullInvalidation = isImmediateFullPaintInvalidationReason(reason); |
496 if (!fullInvalidation && !m_object.shouldInvalidateSelection()) | 514 if (!fullInvalidation && !m_object.shouldInvalidateSelection()) |
497 return; | 515 return; |
498 | 516 |
499 LayoutRect oldSelectionRect = selectionPaintInvalidationMap().get(&m_object); | 517 LayoutRect oldSelectionRect = selectionPaintInvalidationMap().get(&m_object); |
500 LayoutRect newSelectionRect = m_object.localSelectionRect(); | 518 LayoutRect newSelectionRect = m_object.localSelectionRect(); |
501 if (!newSelectionRect.isEmpty()) { | 519 if (!newSelectionRect.isEmpty()) { |
502 m_context.mapLocalRectToPaintInvalidationBacking(m_object, | 520 m_context.mapLocalRectToPaintInvalidationBacking(m_object, |
503 newSelectionRect); | 521 newSelectionRect); |
504 newSelectionRect.move(m_object.scrollAdjustmentForPaintInvalidation( | 522 newSelectionRect.move(m_object.scrollAdjustmentForPaintInvalidation( |
505 *m_context.paintInvalidationContainer)); | 523 *m_context.paintInvalidationContainer)); |
506 } | 524 } |
507 | 525 |
508 setPreviousSelectionPaintInvalidationRect(m_object, newSelectionRect); | 526 setPreviousSelectionPaintInvalidationRect(m_object, newSelectionRect); |
509 | 527 |
510 if (!fullInvalidation) { | 528 if (!fullInvalidation) { |
511 fullyInvalidatePaint(PaintInvalidationSelection, oldSelectionRect, | 529 fullyInvalidatePaint(PaintInvalidationSelection, oldSelectionRect, |
512 newSelectionRect); | 530 newSelectionRect); |
513 m_context.paintingLayer->setNeedsRepaint(); | 531 m_context.paintingLayer->setNeedsRepaint(); |
514 m_object.invalidateDisplayItemClients(PaintInvalidationSelection); | 532 m_object.invalidateDisplayItemClients(PaintInvalidationSelection); |
515 } | 533 } |
516 } | 534 } |
517 | 535 |
518 PaintInvalidationReason | 536 PaintInvalidationReason |
519 ObjectPaintInvalidatorWithContext::invalidatePaintIfNeededWithComputedReason( | 537 ObjectPaintInvalidatorWithContext::invalidatePaintIfNeededWithComputedReason( |
520 PaintInvalidationReason reason) { | 538 PaintInvalidationReason reason) { |
521 // We need to invalidate the selection before checking for whether we are doin
g a full invalidation. | 539 // We need to invalidate the selection before checking for whether we are |
522 // This is because we need to update the previous selection rect regardless. | 540 // doing a full invalidation. This is because we need to update the previous |
| 541 // selection rect regardless. |
523 invalidateSelectionIfNeeded(reason); | 542 invalidateSelectionIfNeeded(reason); |
524 | 543 |
525 if (reason == PaintInvalidationIncremental && !incrementallyInvalidatePaint()) | 544 if (reason == PaintInvalidationIncremental && !incrementallyInvalidatePaint()) |
526 reason = PaintInvalidationNone; | 545 reason = PaintInvalidationNone; |
527 | 546 |
528 switch (reason) { | 547 switch (reason) { |
529 case PaintInvalidationNone: | 548 case PaintInvalidationNone: |
530 // TODO(trchen): Currently we don't keep track of paint offset of layout o
bjects. | 549 // TODO(trchen): Currently we don't keep track of paint offset of layout |
531 // There are corner cases that the display items need to be invalidated fo
r paint offset | 550 // objects. There are corner cases that the display items need to be |
532 // mutation, but incurs no pixel difference (i.e. bounds stay the same) so
no rect-based | 551 // invalidated for paint offset mutation, but incurs no pixel difference |
533 // invalidation is issued. See crbug.com/508383 and crbug.com/515977. | 552 // (i.e. bounds stay the same) so no rect-based invalidation is issued. |
534 // This is a workaround to force display items to update paint offset. | 553 // See crbug.com/508383 and crbug.com/515977. This is a workaround to |
| 554 // force display items to update paint offset. |
535 if (m_context.forcedSubtreeInvalidationFlags & | 555 if (m_context.forcedSubtreeInvalidationFlags & |
536 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking) { | 556 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking) { |
537 reason = PaintInvalidationLocationChange; | 557 reason = PaintInvalidationLocationChange; |
538 break; | 558 break; |
539 } | 559 } |
540 return PaintInvalidationNone; | 560 return PaintInvalidationNone; |
541 case PaintInvalidationIncremental: | 561 case PaintInvalidationIncremental: |
542 break; | 562 break; |
543 case PaintInvalidationDelayedFull: | 563 case PaintInvalidationDelayedFull: |
544 return PaintInvalidationDelayedFull; | 564 return PaintInvalidationDelayedFull; |
545 default: | 565 default: |
546 DCHECK(isImmediateFullPaintInvalidationReason(reason)); | 566 DCHECK(isImmediateFullPaintInvalidationReason(reason)); |
547 fullyInvalidatePaint(reason, m_context.oldBounds, m_context.newBounds); | 567 fullyInvalidatePaint(reason, m_context.oldBounds, m_context.newBounds); |
548 } | 568 } |
549 | 569 |
550 m_context.paintingLayer->setNeedsRepaint(); | 570 m_context.paintingLayer->setNeedsRepaint(); |
551 m_object.invalidateDisplayItemClients(reason); | 571 m_object.invalidateDisplayItemClients(reason); |
552 return reason; | 572 return reason; |
553 } | 573 } |
554 | 574 |
555 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts() | 575 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts() |
556 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {} | 576 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {} |
557 | 577 |
558 } // namespace blink | 578 } // namespace blink |
OLD | NEW |