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" |
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 Loading... | |
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 |
OLD | NEW |