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

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

Issue 2741833005: Make PrePaintTreeWalkContext::treeBuilderContext a unique_ptr (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
« no previous file with comments | « third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp ('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() 18 PrePaintTreeWalkContext()
19 : paintInvalidatorContext(treeBuilderContext), 19 : treeBuilderContext(
20 WTF::wrapUnique(new PaintPropertyTreeBuilderContext)),
21 paintInvalidatorContext(*treeBuilderContext),
20 ancestorOverflowPaintLayer(nullptr), 22 ancestorOverflowPaintLayer(nullptr),
21 ancestorTransformedOrRootPaintLayer(nullptr) {} 23 ancestorTransformedOrRootPaintLayer(nullptr) {}
22 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext) 24 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext)
23 : treeBuilderContext(parentContext.treeBuilderContext), 25 : treeBuilderContext(WTF::wrapUnique(new PaintPropertyTreeBuilderContext(
24 paintInvalidatorContext(treeBuilderContext, 26 *parentContext.treeBuilderContext))),
27 paintInvalidatorContext(*treeBuilderContext,
25 parentContext.paintInvalidatorContext), 28 parentContext.paintInvalidatorContext),
26 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer), 29 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer),
27 ancestorTransformedOrRootPaintLayer( 30 ancestorTransformedOrRootPaintLayer(
28 parentContext.ancestorTransformedOrRootPaintLayer) {} 31 parentContext.ancestorTransformedOrRootPaintLayer) {}
29 32
30 PaintPropertyTreeBuilderContext treeBuilderContext; 33 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows
pdr. 2017/03/10 20:52:39 I think we may still have the issues in https://cr
Xianzhu 2017/03/10 21:54:48 I think 96 bytes is already small enough. It's sma
34 // when recursion is deep so this context object is allocated on the heap.
35 // See: https://crbug.com/698653.
36 std::unique_ptr<PaintPropertyTreeBuilderContext> treeBuilderContext;
37
31 PaintInvalidatorContext paintInvalidatorContext; 38 PaintInvalidatorContext paintInvalidatorContext;
32 39
33 // The ancestor in the PaintLayer tree which has overflow clip, or 40 // The ancestor in the PaintLayer tree which has overflow clip, or
34 // is the root layer. Note that it is tree ancestor, not containing 41 // is the root layer. Note that it is tree ancestor, not containing
35 // block or stacking ancestor. 42 // block or stacking ancestor.
36 PaintLayer* ancestorOverflowPaintLayer; 43 PaintLayer* ancestorOverflowPaintLayer;
37 PaintLayer* ancestorTransformedOrRootPaintLayer; 44 PaintLayer* ancestorTransformedOrRootPaintLayer;
38 }; 45 };
39 46
40 void PrePaintTreeWalk::walk(FrameView& rootFrame) { 47 void PrePaintTreeWalk::walk(FrameView& rootFrame) {
41 DCHECK(rootFrame.frame().document()->lifecycle().state() == 48 DCHECK(rootFrame.frame().document()->lifecycle().state() ==
42 DocumentLifecycle::InPrePaint); 49 DocumentLifecycle::InPrePaint);
43 50
44 PrePaintTreeWalkContext initialContext; 51 PrePaintTreeWalkContext initialContext;
45 initialContext.treeBuilderContext = 52 m_propertyTreeBuilder.setupInitialContext(*initialContext.treeBuilderContext);
46 m_propertyTreeBuilder.setupInitialContext();
47 initialContext.ancestorTransformedOrRootPaintLayer = 53 initialContext.ancestorTransformedOrRootPaintLayer =
48 rootFrame.layoutView()->layer(); 54 rootFrame.layoutView()->layer();
49 55
50 // GeometryMapper depends on paint properties. 56 // GeometryMapper depends on paint properties.
51 if (rootFrame.needsPaintPropertyUpdate() || 57 if (rootFrame.needsPaintPropertyUpdate() ||
52 (rootFrame.layoutView() && 58 (rootFrame.layoutView() &&
53 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) 59 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext)))
54 m_geometryMapper.clearCache(); 60 m_geometryMapper.clearCache();
55 61
56 walk(rootFrame, initialContext); 62 walk(rootFrame, initialContext);
57 m_paintInvalidator.processPendingDelayedPaintInvalidations(); 63 m_paintInvalidator.processPendingDelayedPaintInvalidations();
58 } 64 }
59 65
60 void PrePaintTreeWalk::walk(FrameView& frameView, 66 void PrePaintTreeWalk::walk(FrameView& frameView,
61 const PrePaintTreeWalkContext& parentContext) { 67 const PrePaintTreeWalkContext& parentContext) {
62 if (frameView.shouldThrottleRendering()) { 68 if (frameView.shouldThrottleRendering()) {
63 // Skip the throttled frame. Will update it when it becomes unthrottled. 69 // Skip the throttled frame. Will update it when it becomes unthrottled.
64 return; 70 return;
65 } 71 }
66 72
67 PrePaintTreeWalkContext context(parentContext); 73 PrePaintTreeWalkContext context(parentContext);
68 // ancestorOverflowLayer does not cross frame boundaries. 74 // ancestorOverflowLayer does not cross frame boundaries.
69 context.ancestorOverflowPaintLayer = nullptr; 75 context.ancestorOverflowPaintLayer = nullptr;
70 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); 76 m_propertyTreeBuilder.updateProperties(frameView,
77 *context.treeBuilderContext);
71 m_paintInvalidator.invalidatePaintIfNeeded(frameView, 78 m_paintInvalidator.invalidatePaintIfNeeded(frameView,
72 context.paintInvalidatorContext); 79 context.paintInvalidatorContext);
73 80
74 if (LayoutView* view = frameView.layoutView()) { 81 if (LayoutView* view = frameView.layoutView()) {
75 walk(*view, context); 82 walk(*view, context);
76 #if DCHECK_IS_ON() 83 #if DCHECK_IS_ON()
77 view->assertSubtreeClearedPaintInvalidationFlags(); 84 view->assertSubtreeClearedPaintInvalidationFlags();
78 #endif 85 #endif
79 } 86 }
80 frameView.clearNeedsPaintPropertyUpdate(); 87 frameView.clearNeedsPaintPropertyUpdate();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 if (object.styleRef().hasTransform() || 152 if (object.styleRef().hasTransform() ||
146 &object == context.paintInvalidatorContext.paintInvalidationContainer) { 153 &object == context.paintInvalidatorContext.paintInvalidationContainer) {
147 context.ancestorTransformedOrRootPaintLayer = &paintLayer; 154 context.ancestorTransformedOrRootPaintLayer = &paintLayer;
148 } 155 }
149 156
150 const ObjectPaintProperties& ancestorPaintProperties = 157 const ObjectPaintProperties& ancestorPaintProperties =
151 *context.ancestorTransformedOrRootPaintLayer->layoutObject() 158 *context.ancestorTransformedOrRootPaintLayer->layoutObject()
152 .paintProperties(); 159 .paintProperties();
153 PropertyTreeState ancestorState = 160 PropertyTreeState ancestorState =
154 *ancestorPaintProperties.localBorderBoxProperties(); 161 *ancestorPaintProperties.localBorderBoxProperties();
155 const EffectPaintPropertyNode* effect =
156 context.treeBuilderContext.currentEffect;
157 162
158 #ifdef CHECK_CLIP_RECTS 163 #ifdef CHECK_CLIP_RECTS
159 ShouldRespectOverflowClipType respectOverflowClip = RespectOverflowClip; 164 ShouldRespectOverflowClipType respectOverflowClip = RespectOverflowClip;
160 #endif 165 #endif
161 if (context.ancestorTransformedOrRootPaintLayer->compositingState() == 166 if (context.ancestorTransformedOrRootPaintLayer->compositingState() ==
162 PaintsIntoOwnBacking && 167 PaintsIntoOwnBacking &&
163 ancestorPaintProperties.overflowClip()) { 168 ancestorPaintProperties.overflowClip()) {
164 ancestorState.setClip(ancestorPaintProperties.overflowClip()); 169 ancestorState.setClip(ancestorPaintProperties.overflowClip());
165 #ifdef CHECK_CLIP_RECTS 170 #ifdef CHECK_CLIP_RECTS
166 respectOverflowClip = IgnoreOverflowClip; 171 respectOverflowClip = IgnoreOverflowClip;
167 #endif 172 #endif
168 } 173 }
169 174
170 #ifdef CHECK_CLIP_RECTS 175 #ifdef CHECK_CLIP_RECTS
171 ClipRects& oldClipRects = 176 ClipRects& oldClipRects =
172 paintLayer.clipper(PaintLayer::DoNotUseGeometryMapper) 177 paintLayer.clipper(PaintLayer::DoNotUseGeometryMapper)
173 .paintingClipRects(&ancestorTransformedOrRootPaintLayer, 178 .paintingClipRects(&ancestorTransformedOrRootPaintLayer,
174 respectOverflowClip, LayoutSize()); 179 respectOverflowClip, LayoutSize());
175 #endif 180 #endif
176 181
177 bool hasClip = false; 182 bool hasClip = false;
178 RefPtr<ClipRects> clipRects = ClipRects::create(); 183 RefPtr<ClipRects> clipRects = ClipRects::create();
179 const LayoutPoint& ancestorPaintOffset = 184 const LayoutPoint& ancestorPaintOffset =
180 context.ancestorTransformedOrRootPaintLayer->layoutObject().paintOffset(); 185 context.ancestorTransformedOrRootPaintLayer->layoutObject().paintOffset();
181 186
182 FloatClipRect clipRect; 187 FloatClipRect clipRect;
183 computeClipRectForContext(context.treeBuilderContext.current, effect, 188 const EffectPaintPropertyNode* effect =
189 context.treeBuilderContext->currentEffect;
190 computeClipRectForContext(context.treeBuilderContext->current, effect,
184 ancestorState, ancestorPaintOffset, hasClip, 191 ancestorState, ancestorPaintOffset, hasClip,
185 clipRect); 192 clipRect);
186 clipRects->setOverflowClipRect(clipRect); 193 clipRects->setOverflowClipRect(clipRect);
187 #ifdef CHECK_CLIP_RECTS 194 #ifdef CHECK_CLIP_RECTS
188 CHECK(!hasClip || 195 CHECK(!hasClip ||
189 clipRects->overflowClipRect() == oldClipRects.overflowClipRect()) 196 clipRects->overflowClipRect() == oldClipRects.overflowClipRect())
190 << "rect= " << clipRects->overflowClipRect().toString(); 197 << "rect= " << clipRects->overflowClipRect().toString();
191 #endif 198 #endif
192 199
193 computeClipRectForContext(context.treeBuilderContext.fixedPosition, effect, 200 computeClipRectForContext(context.treeBuilderContext->fixedPosition, effect,
194 ancestorState, ancestorPaintOffset, hasClip, 201 ancestorState, ancestorPaintOffset, hasClip,
195 clipRect); 202 clipRect);
196 clipRects->setFixedClipRect(clipRect); 203 clipRects->setFixedClipRect(clipRect);
197 #ifdef CHECK_CLIP_RECTS 204 #ifdef CHECK_CLIP_RECTS
198 CHECK(hasClip || clipRects->fixedClipRect() == oldClipRects.fixedClipRect()) 205 CHECK(hasClip || clipRects->fixedClipRect() == oldClipRects.fixedClipRect())
199 << " fixed=" << clipRects->fixedClipRect().toString(); 206 << " fixed=" << clipRects->fixedClipRect().toString();
200 #endif 207 #endif
201 208
202 computeClipRectForContext(context.treeBuilderContext.absolutePosition, effect, 209 computeClipRectForContext(context.treeBuilderContext->absolutePosition,
203 ancestorState, ancestorPaintOffset, hasClip, 210 effect, ancestorState, ancestorPaintOffset, hasClip,
204 clipRect); 211 clipRect);
205 clipRects->setPosClipRect(clipRect); 212 clipRects->setPosClipRect(clipRect);
206 #ifdef CHECK_CLIP_RECTS 213 #ifdef CHECK_CLIP_RECTS
207 CHECK(!hasClip || clipRects->posClipRect() == oldClipRects.posClipRect()) 214 CHECK(!hasClip || clipRects->posClipRect() == oldClipRects.posClipRect())
208 << " abs=" << clipRects->posClipRect().toString(); 215 << " abs=" << clipRects->posClipRect().toString();
209 #endif 216 #endif
210 217
211 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); 218 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects();
212 219
213 if (!previousClipRects || *clipRects != *previousClipRects) { 220 if (!previousClipRects || *clipRects != *previousClipRects) {
214 paintLayer.setNeedsRepaint(); 221 paintLayer.setNeedsRepaint();
215 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); 222 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false);
216 paintLayer.setPreviousPaintPhaseFloatEmpty(false); 223 paintLayer.setPreviousPaintPhaseFloatEmpty(false);
217 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); 224 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false);
218 // All subsequences which are contained below this paintLayer must also 225 // All subsequences which are contained below this paintLayer must also
219 // be checked. 226 // be checked.
220 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= 227 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |=
221 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; 228 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate;
222 } 229 }
223 230
224 paintLayer.setPreviousPaintingClipRects(*clipRects); 231 paintLayer.setPreviousPaintingClipRects(*clipRects);
225 } 232 }
226 233
227 bool PrePaintTreeWalk::shouldEndWalkBefore( 234 bool PrePaintTreeWalk::shouldEndWalkBefore(
228 const LayoutObject& object, 235 const LayoutObject& object,
229 const PrePaintTreeWalkContext& context) { 236 const PrePaintTreeWalkContext& context) {
230 return ( 237 return (
231 !object.needsPaintPropertyUpdate() && 238 !object.needsPaintPropertyUpdate() &&
232 !object.descendantNeedsPaintPropertyUpdate() && 239 !object.descendantNeedsPaintPropertyUpdate() &&
233 !context.treeBuilderContext.forceSubtreeUpdate && 240 !context.treeBuilderContext->forceSubtreeUpdate &&
234 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && 241 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags &&
235 !object 242 !object
236 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ; 243 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ;
237 } 244 }
238 245
239 void PrePaintTreeWalk::walk(const LayoutObject& object, 246 void PrePaintTreeWalk::walk(const LayoutObject& object,
240 const PrePaintTreeWalkContext& parentContext) { 247 const PrePaintTreeWalkContext& parentContext) {
241 if (shouldEndWalkBefore(object, parentContext)) 248 if (shouldEndWalkBefore(object, parentContext))
242 return; 249 return;
243 250
244 // PrePaintTreeWalkContext is large and can lead to stack overflows when 251 PrePaintTreeWalkContext context(parentContext);
245 // recursion is deep so this context object is allocated on the heap.
246 // See: https://crbug.com/698653.
247 std::unique_ptr<PrePaintTreeWalkContext> context =
248 WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext));
249 252
250 // This must happen before updatePropertiesForSelf, because the latter reads 253 // This must happen before updatePropertiesForSelf, because the latter reads
251 // some of the state computed here. 254 // some of the state computed here.
252 updateAuxiliaryObjectProperties(object, *context); 255 updateAuxiliaryObjectProperties(object, context);
253 256
254 m_propertyTreeBuilder.updatePropertiesForSelf(object, 257 m_propertyTreeBuilder.updatePropertiesForSelf(object,
255 context->treeBuilderContext); 258 *context.treeBuilderContext);
256 m_paintInvalidator.invalidatePaintIfNeeded(object, 259 m_paintInvalidator.invalidatePaintIfNeeded(object,
257 context->paintInvalidatorContext); 260 context.paintInvalidatorContext);
258 m_propertyTreeBuilder.updatePropertiesForChildren( 261 m_propertyTreeBuilder.updatePropertiesForChildren(
259 object, context->treeBuilderContext); 262 object, *context.treeBuilderContext);
260 263
261 invalidatePaintLayerOptimizationsIfNeeded(object, *context); 264 invalidatePaintLayerOptimizationsIfNeeded(object, context);
262 265
263 for (const LayoutObject* child = object.slowFirstChild(); child; 266 for (const LayoutObject* child = object.slowFirstChild(); child;
264 child = child->nextSibling()) { 267 child = child->nextSibling()) {
265 if (child->isLayoutMultiColumnSpannerPlaceholder()) { 268 if (child->isLayoutMultiColumnSpannerPlaceholder()) {
266 child->getMutableForPainting().clearPaintFlags(); 269 child->getMutableForPainting().clearPaintFlags();
267 continue; 270 continue;
268 } 271 }
269 walk(*child, *context); 272 walk(*child, context);
270 } 273 }
271 274
272 if (object.isLayoutPart()) { 275 if (object.isLayoutPart()) {
273 const LayoutPart& layoutPart = toLayoutPart(object); 276 const LayoutPart& layoutPart = toLayoutPart(object);
274 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); 277 FrameViewBase* frameViewBase = layoutPart.frameViewBase();
275 if (frameViewBase && frameViewBase->isFrameView()) { 278 if (frameViewBase && frameViewBase->isFrameView()) {
276 context->treeBuilderContext.current.paintOffset += 279 context.treeBuilderContext->current.paintOffset +=
277 layoutPart.replacedContentRect().location() - 280 layoutPart.replacedContentRect().location() -
278 frameViewBase->frameRect().location(); 281 frameViewBase->frameRect().location();
279 context->treeBuilderContext.current.paintOffset = 282 context.treeBuilderContext->current.paintOffset =
280 roundedIntPoint(context->treeBuilderContext.current.paintOffset); 283 roundedIntPoint(context.treeBuilderContext->current.paintOffset);
281 walk(*toFrameView(frameViewBase), *context); 284 walk(*toFrameView(frameViewBase), context);
282 } 285 }
283 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). 286 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
284 } 287 }
285 288
286 object.getMutableForPainting().clearPaintFlags(); 289 object.getMutableForPainting().clearPaintFlags();
287 } 290 }
288 291
289 } // namespace blink 292 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698