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

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, 8 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
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "core/layout/LayoutPart.h" 11 #include "core/layout/LayoutPart.h"
12 #include "core/layout/LayoutView.h" 12 #include "core/layout/LayoutView.h"
13 #include "core/paint/PaintLayer.h" 13 #include "core/paint/PaintLayer.h"
14 14
15 namespace blink { 15 namespace blink {
16 16
17 struct PrePaintTreeWalkContext { 17 struct PrePaintTreeWalkContext {
18 PrePaintTreeWalkContext(GeometryMapper& geometryMapper) 18 PrePaintTreeWalkContext(GeometryMapper& geometryMapper)
19 : treeBuilderContext( 19 : treeBuilderContext(
20 WTF::wrapUnique(new PaintPropertyTreeBuilderContext)), 20 WTF::wrapUnique(new PaintPropertyTreeBuilderContext)),
21 paintInvalidatorContext(*treeBuilderContext, geometryMapper), 21 paintInvalidatorContext(treeBuilderContext.get(), geometryMapper),
22 ancestorOverflowPaintLayer(nullptr), 22 ancestorOverflowPaintLayer(nullptr),
23 ancestorTransformedOrRootPaintLayer(nullptr) {} 23 ancestorTransformedOrRootPaintLayer(nullptr) {}
24 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext) 24
25 : treeBuilderContext(WTF::wrapUnique(new PaintPropertyTreeBuilderContext( 25 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext,
26 *parentContext.treeBuilderContext))), 26 bool needsTreeBuilderContext)
27 paintInvalidatorContext(*treeBuilderContext, 27 : treeBuilderContext(
28 WTF::wrapUnique(needsTreeBuilderContext || DCHECK_IS_ON()
29 ? new PaintPropertyTreeBuilderContext(
30 *parentContext.treeBuilderContext)
31 : nullptr)),
32 paintInvalidatorContext(treeBuilderContext.get(),
28 parentContext.paintInvalidatorContext), 33 parentContext.paintInvalidatorContext),
29 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer), 34 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer),
30 ancestorTransformedOrRootPaintLayer( 35 ancestorTransformedOrRootPaintLayer(
31 parentContext.ancestorTransformedOrRootPaintLayer) {} 36 parentContext.ancestorTransformedOrRootPaintLayer) {
37 #if DCHECK_IS_ON()
38 if (needsTreeBuilderContext)
39 DCHECK(parentContext.treeBuilderContext->isActuallyNeeded);
40 treeBuilderContext->isActuallyNeeded = needsTreeBuilderContext;
41 #endif
42 }
32 43
33 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows 44 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows
34 // when recursion is deep so this context object is allocated on the heap. 45 // when recursion is deep so this context object is allocated on the heap.
35 // See: https://crbug.com/698653. 46 // See: https://crbug.com/698653.
36 std::unique_ptr<PaintPropertyTreeBuilderContext> treeBuilderContext; 47 std::unique_ptr<PaintPropertyTreeBuilderContext> treeBuilderContext;
37 48
38 PaintInvalidatorContext paintInvalidatorContext; 49 PaintInvalidatorContext paintInvalidatorContext;
39 50
40 // The ancestor in the PaintLayer tree which has overflow clip, or 51 // The ancestor in the PaintLayer tree which has overflow clip, or
41 // is the root layer. Note that it is tree ancestor, not containing 52 // is the root layer. Note that it is tree ancestor, not containing
42 // block or stacking ancestor. 53 // block or stacking ancestor.
43 PaintLayer* ancestorOverflowPaintLayer; 54 PaintLayer* ancestorOverflowPaintLayer;
44 PaintLayer* ancestorTransformedOrRootPaintLayer; 55 PaintLayer* ancestorTransformedOrRootPaintLayer;
45 }; 56 };
46 57
47 void PrePaintTreeWalk::walk(FrameView& rootFrame) { 58 void PrePaintTreeWalk::walk(FrameView& rootFrame) {
48 DCHECK(rootFrame.frame().document()->lifecycle().state() == 59 DCHECK(rootFrame.frame().document()->lifecycle().state() ==
49 DocumentLifecycle::InPrePaint); 60 DocumentLifecycle::InPrePaint);
50 61
51 PrePaintTreeWalkContext initialContext(m_geometryMapper); 62 PrePaintTreeWalkContext initialContext(m_geometryMapper);
52 initialContext.ancestorTransformedOrRootPaintLayer = 63 initialContext.ancestorTransformedOrRootPaintLayer =
53 rootFrame.layoutView()->layer(); 64 rootFrame.layoutView()->layer();
54 65
55 // GeometryMapper depends on paint properties. 66 // GeometryMapper depends on paint properties.
56 if (rootFrame.needsPaintPropertyUpdate() || 67 if (needsTreeBuilderContextUpdate(rootFrame, initialContext))
57 (rootFrame.layoutView() &&
58 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext)))
59 m_geometryMapper.clearCache(); 68 m_geometryMapper.clearCache();
60 69
61 walk(rootFrame, initialContext); 70 walk(rootFrame, initialContext);
62 m_paintInvalidator.processPendingDelayedPaintInvalidations(); 71 m_paintInvalidator.processPendingDelayedPaintInvalidations();
63 } 72 }
64 73
65 void PrePaintTreeWalk::walk(FrameView& frameView, 74 void PrePaintTreeWalk::walk(FrameView& frameView,
66 const PrePaintTreeWalkContext& parentContext) { 75 const PrePaintTreeWalkContext& parentContext) {
67 if (frameView.shouldThrottleRendering()) { 76 if (frameView.shouldThrottleRendering()) {
68 // Skip the throttled frame. Will update it when it becomes unthrottled. 77 // Skip the throttled frame. Will update it when it becomes unthrottled.
69 return; 78 return;
70 } 79 }
71 80
72 PrePaintTreeWalkContext context(parentContext); 81 bool needsTreeBuilderContextUpdate =
82 this->needsTreeBuilderContextUpdate(frameView, parentContext);
83 PrePaintTreeWalkContext context(parentContext, needsTreeBuilderContextUpdate);
73 // ancestorOverflowLayer does not cross frame boundaries. 84 // ancestorOverflowLayer does not cross frame boundaries.
74 context.ancestorOverflowPaintLayer = nullptr; 85 context.ancestorOverflowPaintLayer = nullptr;
75 m_propertyTreeBuilder.updateProperties(frameView, 86 if (context.treeBuilderContext) {
76 *context.treeBuilderContext); 87 m_propertyTreeBuilder.updateProperties(frameView,
88 *context.treeBuilderContext);
89 }
77 m_paintInvalidator.invalidatePaintIfNeeded(frameView, 90 m_paintInvalidator.invalidatePaintIfNeeded(frameView,
78 context.paintInvalidatorContext); 91 context.paintInvalidatorContext);
79 92
80 if (LayoutView* view = frameView.layoutView()) { 93 if (LayoutView* view = frameView.layoutView()) {
81 walk(*view, context); 94 walk(*view, context);
82 #if DCHECK_IS_ON() 95 #if DCHECK_IS_ON()
83 view->assertSubtreeClearedPaintInvalidationFlags(); 96 view->assertSubtreeClearedPaintInvalidationFlags();
84 #endif 97 #endif
85 } 98 }
86 frameView.clearNeedsPaintPropertyUpdate(); 99 frameView.clearNeedsPaintPropertyUpdate();
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); 230 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects();
218 231
219 if (!previousClipRects || *clipRects != *previousClipRects) { 232 if (!previousClipRects || *clipRects != *previousClipRects) {
220 paintLayer.setNeedsRepaint(); 233 paintLayer.setNeedsRepaint();
221 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); 234 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false);
222 paintLayer.setPreviousPaintPhaseFloatEmpty(false); 235 paintLayer.setPreviousPaintPhaseFloatEmpty(false);
223 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); 236 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false);
224 // All subsequences which are contained below this paintLayer must also 237 // All subsequences which are contained below this paintLayer must also
225 // be checked. 238 // be checked.
226 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= 239 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |=
227 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; 240 PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate;
228 } 241 }
229 242
230 paintLayer.setPreviousPaintingClipRects(*clipRects); 243 paintLayer.setPreviousPaintingClipRects(*clipRects);
231 } 244 }
232 245
233 bool PrePaintTreeWalk::shouldEndWalkBefore( 246 bool PrePaintTreeWalk::needsTreeBuilderContextUpdate(
247 const FrameView& frameView,
248 const PrePaintTreeWalkContext& context) {
249 return frameView.needsPaintPropertyUpdate() ||
250 (frameView.layoutView() &&
251 needsTreeBuilderContextUpdate(*frameView.layoutView(), context));
252 }
253
254 bool PrePaintTreeWalk::needsTreeBuilderContextUpdate(
234 const LayoutObject& object, 255 const LayoutObject& object,
235 const PrePaintTreeWalkContext& context) { 256 const PrePaintTreeWalkContext& parentContext) {
236 return !object.needsPaintPropertyUpdate() && 257 return object.needsPaintPropertyUpdate() ||
237 !object.descendantNeedsPaintPropertyUpdate() && 258 object.descendantNeedsPaintPropertyUpdate() ||
238 !context.treeBuilderContext->forceSubtreeUpdate && 259 (parentContext.treeBuilderContext &&
239 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && 260 parentContext.treeBuilderContext->forceSubtreeUpdate) ||
240 !object.shouldCheckForPaintInvalidation(); 261 // If the object needs visual rect update, we should update tree
262 // builder context which is needed by visual rect update.
263 parentContext.paintInvalidatorContext.needsVisualRectUpdate(object);
241 } 264 }
242 265
243 void PrePaintTreeWalk::walk(const LayoutObject& object, 266 void PrePaintTreeWalk::walk(const LayoutObject& object,
244 const PrePaintTreeWalkContext& parentContext) { 267 const PrePaintTreeWalkContext& parentContext) {
245 if (shouldEndWalkBefore(object, parentContext)) 268 // Early out from the tree walk if possible.
269 bool needsTreeBuilderContextUpdate =
270 this->needsTreeBuilderContextUpdate(object, parentContext);
271 if (!needsTreeBuilderContextUpdate &&
272 !object.shouldCheckForPaintInvalidation())
246 return; 273 return;
247 274
248 PrePaintTreeWalkContext context(parentContext); 275 PrePaintTreeWalkContext context(parentContext, needsTreeBuilderContextUpdate);
249 276
250 // This must happen before updatePropertiesForSelf, because the latter reads 277 // This must happen before updatePropertiesForSelf, because the latter reads
251 // some of the state computed here. 278 // some of the state computed here.
252 updateAuxiliaryObjectProperties(object, context); 279 updateAuxiliaryObjectProperties(object, context);
253 280
254 m_propertyTreeBuilder.updatePropertiesForSelf(object, 281 if (context.treeBuilderContext) {
255 *context.treeBuilderContext); 282 DCHECK(context.treeBuilderContext);
283 m_propertyTreeBuilder.updatePropertiesForSelf(object,
284 *context.treeBuilderContext);
285 }
286
256 m_paintInvalidator.invalidatePaintIfNeeded(object, 287 m_paintInvalidator.invalidatePaintIfNeeded(object,
257 context.paintInvalidatorContext); 288 context.paintInvalidatorContext);
258 m_propertyTreeBuilder.updatePropertiesForChildren(
259 object, *context.treeBuilderContext);
260 289
261 invalidatePaintLayerOptimizationsIfNeeded(object, context); 290 if (context.treeBuilderContext) {
291 m_propertyTreeBuilder.updatePropertiesForChildren(
292 object, *context.treeBuilderContext);
293 invalidatePaintLayerOptimizationsIfNeeded(object, context);
294 }
262 295
263 for (const LayoutObject* child = object.slowFirstChild(); child; 296 for (const LayoutObject* child = object.slowFirstChild(); child;
264 child = child->nextSibling()) { 297 child = child->nextSibling()) {
265 if (child->isLayoutMultiColumnSpannerPlaceholder()) { 298 if (child->isLayoutMultiColumnSpannerPlaceholder()) {
266 child->getMutableForPainting().clearPaintFlags(); 299 child->getMutableForPainting().clearPaintFlags();
267 continue; 300 continue;
268 } 301 }
269 walk(*child, context); 302 walk(*child, context);
270 } 303 }
271 304
272 if (object.isLayoutPart()) { 305 if (object.isLayoutPart()) {
273 const LayoutPart& layoutPart = toLayoutPart(object); 306 const LayoutPart& layoutPart = toLayoutPart(object);
274 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); 307 FrameViewBase* frameViewBase = layoutPart.frameViewBase();
275 if (frameViewBase && frameViewBase->isFrameView()) { 308 if (frameViewBase && frameViewBase->isFrameView()) {
276 context.treeBuilderContext->current.paintOffset += 309 if (context.treeBuilderContext) {
277 layoutPart.replacedContentRect().location() - 310 context.treeBuilderContext->current.paintOffset +=
278 frameViewBase->frameRect().location(); 311 layoutPart.replacedContentRect().location() -
279 context.treeBuilderContext->current.paintOffset = 312 frameViewBase->frameRect().location();
280 roundedIntPoint(context.treeBuilderContext->current.paintOffset); 313 context.treeBuilderContext->current.paintOffset =
314 roundedIntPoint(context.treeBuilderContext->current.paintOffset);
315 }
281 walk(*toFrameView(frameViewBase), context); 316 walk(*toFrameView(frameViewBase), context);
282 } 317 }
283 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). 318 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
284 } 319 }
285 320
286 object.getMutableForPainting().clearPaintFlags(); 321 object.getMutableForPainting().clearPaintFlags();
287 } 322 }
288 323
289 } // namespace blink 324 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698