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

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

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