OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/PrePaintTreeWalk.h" | 5 #include "core/paint/PrePaintTreeWalk.h" |
6 | 6 |
7 #include "core/dom/DocumentLifecycle.h" | 7 #include "core/dom/DocumentLifecycle.h" |
8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
10 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" | 10 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 DocumentLifecycle::InPrePaint); | 42 DocumentLifecycle::InPrePaint); |
43 | 43 |
44 PrePaintTreeWalkContext initialContext; | 44 PrePaintTreeWalkContext initialContext; |
45 initialContext.treeBuilderContext = | 45 initialContext.treeBuilderContext = |
46 m_propertyTreeBuilder.setupInitialContext(); | 46 m_propertyTreeBuilder.setupInitialContext(); |
47 initialContext.ancestorTransformedOrRootPaintLayer = | 47 initialContext.ancestorTransformedOrRootPaintLayer = |
48 rootFrame.layoutView()->layer(); | 48 rootFrame.layoutView()->layer(); |
49 | 49 |
50 // GeometryMapper depends on paint properties. | 50 // GeometryMapper depends on paint properties. |
51 if (rootFrame.needsPaintPropertyUpdate() || | 51 if (rootFrame.needsPaintPropertyUpdate() || |
52 (rootFrame.layoutView() && | 52 (rootFrame.layoutView() && needsWalkForPaintPropertyUpdate( |
53 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) | 53 *rootFrame.layoutView(), initialContext))) |
54 m_geometryMapper.clearCache(); | 54 m_geometryMapper.clearCache(); |
55 | 55 |
56 walk(rootFrame, initialContext); | 56 walk(rootFrame, initialContext); |
57 m_paintInvalidator.processPendingDelayedPaintInvalidations(); | 57 m_paintInvalidator.processPendingDelayedPaintInvalidations(); |
58 } | 58 } |
59 | 59 |
60 void PrePaintTreeWalk::walk(FrameView& frameView, | 60 void PrePaintTreeWalk::walk(FrameView& frameView, |
61 const PrePaintTreeWalkContext& parentContext) { | 61 const PrePaintTreeWalkContext& parentContext) { |
62 if (frameView.shouldThrottleRendering()) { | 62 if (frameView.shouldThrottleRendering()) { |
63 // Skip the throttled frame. Will update it when it becomes unthrottled. | 63 // Skip the throttled frame. Will update it when it becomes unthrottled. |
64 return; | 64 return; |
65 } | 65 } |
66 | 66 |
67 PrePaintTreeWalkContext context(parentContext); | 67 PrePaintTreeWalkContext context(parentContext); |
68 // ancestorOverflowLayer does not cross frame boundaries. | 68 // ancestorOverflowLayer does not cross frame boundaries. |
69 context.ancestorOverflowPaintLayer = nullptr; | 69 context.ancestorOverflowPaintLayer = nullptr; |
70 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); | 70 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); |
71 m_paintInvalidator.invalidatePaintIfNeeded(frameView, | 71 m_paintInvalidator.invalidatePaintIfNeeded(frameView, |
72 context.paintInvalidatorContext); | 72 context.paintInvalidatorContext); |
73 | 73 |
74 if (LayoutView* view = frameView.layoutView()) { | 74 if (LayoutView* view = frameView.layoutView()) { |
75 #if DCHECK_IS_ON() | |
76 context.treeBuilderContext.updatedForSelf = true; | |
77 context.treeBuilderContext.updatedForChildren = true; | |
78 #endif | |
75 walk(*view, context); | 79 walk(*view, context); |
76 #if DCHECK_IS_ON() | 80 #if DCHECK_IS_ON() |
77 view->assertSubtreeClearedPaintInvalidationFlags(); | 81 view->assertSubtreeClearedPaintInvalidationFlags(); |
78 #endif | 82 #endif |
79 } | 83 } |
80 frameView.clearNeedsPaintPropertyUpdate(); | 84 frameView.clearNeedsPaintPropertyUpdate(); |
81 } | 85 } |
82 | 86 |
83 static void updateAuxiliaryObjectProperties(const LayoutObject& object, | 87 static void updateAuxiliaryObjectProperties(const LayoutObject& object, |
84 PrePaintTreeWalkContext& context) { | 88 PrePaintTreeWalkContext& context) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 rect.moveBy(-FloatPoint(ancestorPaintOffset)); | 140 rect.moveBy(-FloatPoint(ancestorPaintOffset)); |
137 return rect; | 141 return rect; |
138 } | 142 } |
139 | 143 |
140 void PrePaintTreeWalk::invalidatePaintLayerOptimizationsIfNeeded( | 144 void PrePaintTreeWalk::invalidatePaintLayerOptimizationsIfNeeded( |
141 const LayoutObject& object, | 145 const LayoutObject& object, |
142 PrePaintTreeWalkContext& context) { | 146 PrePaintTreeWalkContext& context) { |
143 if (!object.hasLayer()) | 147 if (!object.hasLayer()) |
144 return; | 148 return; |
145 | 149 |
150 #if DCHECK_IS_ON() | |
151 DCHECK(context.treeBuilderContext.updatedForChildren); | |
152 #endif | |
153 | |
146 PaintLayer& paintLayer = *toLayoutBoxModelObject(object).layer(); | 154 PaintLayer& paintLayer = *toLayoutBoxModelObject(object).layer(); |
147 if (object.styleRef().hasTransform() || | 155 if (object.styleRef().hasTransform() || |
148 &object == context.paintInvalidatorContext.paintInvalidationContainer) { | 156 &object == context.paintInvalidatorContext.paintInvalidationContainer) { |
149 context.ancestorTransformedOrRootPaintLayer = &paintLayer; | 157 context.ancestorTransformedOrRootPaintLayer = &paintLayer; |
150 } | 158 } |
151 | 159 |
152 const ObjectPaintProperties& ancestorPaintProperties = | 160 const ObjectPaintProperties& ancestorPaintProperties = |
153 *context.ancestorTransformedOrRootPaintLayer->layoutObject() | 161 *context.ancestorTransformedOrRootPaintLayer->layoutObject() |
154 .paintProperties(); | 162 .paintProperties(); |
155 PropertyTreeState ancestorState = | 163 PropertyTreeState ancestorState = |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); | 216 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); |
209 | 217 |
210 if (!previousClipRects || *clipRects != *previousClipRects) { | 218 if (!previousClipRects || *clipRects != *previousClipRects) { |
211 paintLayer.setNeedsRepaint(); | 219 paintLayer.setNeedsRepaint(); |
212 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); | 220 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); |
213 paintLayer.setPreviousPaintPhaseFloatEmpty(false); | 221 paintLayer.setPreviousPaintPhaseFloatEmpty(false); |
214 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); | 222 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); |
215 // All subsequences which are contained below this paintLayer must also | 223 // All subsequences which are contained below this paintLayer must also |
216 // be checked. | 224 // be checked. |
217 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= | 225 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= |
218 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 226 PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate; |
219 } | 227 } |
220 | 228 |
221 paintLayer.setPreviousPaintingClipRects(*clipRects); | 229 paintLayer.setPreviousPaintingClipRects(*clipRects); |
222 } | 230 } |
223 | 231 |
224 bool PrePaintTreeWalk::shouldEndWalkBefore( | 232 bool PrePaintTreeWalk::needsWalkForPaintPropertyUpdate( |
225 const LayoutObject& object, | 233 const LayoutObject& object, |
226 const PrePaintTreeWalkContext& context) { | 234 const PrePaintTreeWalkContext& context) { |
227 return ( | 235 return object.needsPaintPropertyUpdate() || |
228 !object.needsPaintPropertyUpdate() && | 236 object.descendantNeedsPaintPropertyUpdate() || |
229 !object.descendantNeedsPaintPropertyUpdate() && | 237 context.treeBuilderContext.forceSubtreeUpdate || |
230 !context.treeBuilderContext.forceSubtreeUpdate && | 238 // If the object needs visual rect update, we should update paint |
231 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && | 239 // properties which are needed by visual rect update. |
232 !object | 240 m_paintInvalidator.needsVisualRectUpdate( |
233 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ; | 241 object, context.paintInvalidatorContext); |
234 } | 242 } |
235 | 243 |
236 void PrePaintTreeWalk::walk(const LayoutObject& object, | 244 void PrePaintTreeWalk::walk(const LayoutObject& object, |
237 const PrePaintTreeWalkContext& parentContext) { | 245 const PrePaintTreeWalkContext& parentContext) { |
238 if (shouldEndWalkBefore(object, parentContext)) | 246 // Early out from the treewalk if possible. |
247 bool needsWalkForPaintPropertyUpdate = | |
248 this->needsWalkForPaintPropertyUpdate(object, parentContext); | |
249 if (!needsWalkForPaintPropertyUpdate && | |
250 !object | |
251 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) | |
239 return; | 252 return; |
240 | 253 |
241 // PrePaintTreeWalkContext is large and can lead to stack overflows when | 254 // PrePaintTreeWalkContext is large and can lead to stack overflows when |
242 // recursion is deep so this context object is allocated on the heap. | 255 // recursion is deep so this context object is allocated on the heap. |
243 // See: https://crbug.com/698653. | 256 // See: https://crbug.com/698653. |
244 std::unique_ptr<PrePaintTreeWalkContext> context = | 257 std::unique_ptr<PrePaintTreeWalkContext> context = |
245 WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext)); | 258 WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext)); |
246 | 259 |
247 // This must happen before updatePropertiesForSelf, because the latter reads | 260 // This must happen before updatePropertiesForSelf, because the latter reads |
248 // some of the state computed here. | 261 // some of the state computed here. |
249 updateAuxiliaryObjectProperties(object, *context); | 262 updateAuxiliaryObjectProperties(object, *context); |
250 | 263 |
251 m_propertyTreeBuilder.updatePropertiesForSelf(object, | 264 if (needsWalkForPaintPropertyUpdate) { |
pdr.
2017/03/10 06:21:39
Trying to think of ways to simplify these DCHECKS.
Xianzhu
2017/03/10 17:43:05
This looks a good idea. Will try.
Xianzhu
2017/03/13 19:08:09
I tried the method, but found that we still need t
| |
252 context->treeBuilderContext); | 265 #if DCHECK_IS_ON() |
266 DCHECK(context->treeBuilderContext.parentUpdated); | |
267 #endif | |
268 m_propertyTreeBuilder.updatePropertiesForSelf(object, | |
269 context->treeBuilderContext); | |
270 #if DCHECK_IS_ON() | |
271 context->treeBuilderContext.updatedForSelf = true; | |
272 #endif | |
273 } else { | |
274 #if DCHECK_IS_ON() | |
275 // When DCHECK_IS_ON, always update paint properties so that paint | |
276 // invalidator can update visual rect for checking missing flags. | |
277 LayoutPoint oldPaintOffset = object.paintOffset(); | |
278 m_propertyTreeBuilder.updatePropertiesForSelf(object, | |
279 context->treeBuilderContext); | |
280 DCHECK(object.paintOffset() == oldPaintOffset) | |
281 << "Paint offset changed without needsPaintOffsetAndVisualRectUpdate" | |
282 << " old=" << oldPaintOffset.toString() | |
283 << " new=" << object.paintOffset().toString(); | |
284 #endif | |
285 } | |
286 | |
253 m_paintInvalidator.invalidatePaintIfNeeded(object, | 287 m_paintInvalidator.invalidatePaintIfNeeded(object, |
254 context->paintInvalidatorContext); | 288 context->paintInvalidatorContext); |
255 m_propertyTreeBuilder.updatePropertiesForChildren( | |
256 object, context->treeBuilderContext); | |
257 | 289 |
258 invalidatePaintLayerOptimizationsIfNeeded(object, *context); | 290 if (needsWalkForPaintPropertyUpdate) { |
291 m_propertyTreeBuilder.updatePropertiesForChildren( | |
292 object, context->treeBuilderContext); | |
293 #if DCHECK_IS_ON() | |
294 context->treeBuilderContext.updatedForChildren = true; | |
295 #endif | |
296 invalidatePaintLayerOptimizationsIfNeeded(object, *context); | |
297 } else { | |
298 #if DCHECK_IS_ON() | |
299 // When DCHECK_IS_ON, always update paint properties so that paint | |
300 // invalidator can update visual rect for checking missing flags. | |
301 m_propertyTreeBuilder.updatePropertiesForChildren( | |
302 object, context->treeBuilderContext); | |
303 #endif | |
304 } | |
259 | 305 |
260 for (const LayoutObject* child = object.slowFirstChild(); child; | 306 for (const LayoutObject* child = object.slowFirstChild(); child; |
261 child = child->nextSibling()) { | 307 child = child->nextSibling()) { |
262 if (child->isLayoutMultiColumnSpannerPlaceholder()) { | 308 if (child->isLayoutMultiColumnSpannerPlaceholder()) { |
263 child->getMutableForPainting().clearPaintFlags(); | 309 child->getMutableForPainting().clearPaintFlags(); |
264 continue; | 310 continue; |
265 } | 311 } |
266 walk(*child, *context); | 312 walk(*child, *context); |
267 } | 313 } |
268 | 314 |
269 if (object.isLayoutPart()) { | 315 if (object.isLayoutPart()) { |
270 const LayoutPart& layoutPart = toLayoutPart(object); | 316 const LayoutPart& layoutPart = toLayoutPart(object); |
271 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); | 317 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); |
272 if (frameViewBase && frameViewBase->isFrameView()) { | 318 if (frameViewBase && frameViewBase->isFrameView()) { |
273 context->treeBuilderContext.current.paintOffset += | 319 context->treeBuilderContext.current.paintOffset += |
274 layoutPart.replacedContentRect().location() - | 320 layoutPart.replacedContentRect().location() - |
275 frameViewBase->frameRect().location(); | 321 frameViewBase->frameRect().location(); |
276 context->treeBuilderContext.current.paintOffset = | 322 context->treeBuilderContext.current.paintOffset = |
277 roundedIntPoint(context->treeBuilderContext.current.paintOffset); | 323 roundedIntPoint(context->treeBuilderContext.current.paintOffset); |
278 walk(*toFrameView(frameViewBase), *context); | 324 walk(*toFrameView(frameViewBase), *context); |
279 } | 325 } |
280 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 326 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
281 } | 327 } |
282 | 328 |
283 object.getMutableForPainting().clearPaintFlags(); | 329 object.getMutableForPainting().clearPaintFlags(); |
284 } | 330 } |
285 | 331 |
286 } // namespace blink | 332 } // namespace blink |
OLD | NEW |