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

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

Issue 2732573003: Skip paint property update and visual rect update if no geometry change (Closed)
Patch Set: - Created 3 years, 9 months 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 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698