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" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 | 72 |
73 if (LayoutView* view = frameView.layoutView()) { | 73 if (LayoutView* view = frameView.layoutView()) { |
74 walk(*view, context); | 74 walk(*view, context); |
75 #if DCHECK_IS_ON() | 75 #if DCHECK_IS_ON() |
76 view->assertSubtreeClearedPaintInvalidationFlags(); | 76 view->assertSubtreeClearedPaintInvalidationFlags(); |
77 #endif | 77 #endif |
78 } | 78 } |
79 frameView.clearNeedsPaintPropertyUpdate(); | 79 frameView.clearNeedsPaintPropertyUpdate(); |
80 } | 80 } |
81 | 81 |
82 // |PrePaintTreeWalkContext| is large and can cause stack overflows when used | |
83 // in a recursive treewalk (see: https://crbug.com/698653). This function | |
84 // implements an iterative pre-order tree walk of the layout tree where the | |
85 // stack is maintained using heap allocations in a Vector. | |
86 void PrePaintTreeWalk::walk(const LayoutView& view, | |
87 const PrePaintTreeWalkContext& parentContext) { | |
88 Vector<PrePaintTreeWalkContext> stack; | |
pdr.
2017/03/08 01:04:59
This has a bug: when the vector resizes, parent po
| |
89 stack.push_back(parentContext); | |
90 | |
91 const LayoutObject* object = &view; | |
92 while (object) { | |
93 if (!shouldEndWalkBefore(*object, stack.back())) { | |
94 stack.push_back(stack.back()); | |
95 walkObject(*object, stack.back()); | |
96 if (const auto* child = object->slowFirstChild()) { | |
97 object = child; | |
98 continue; | |
99 } | |
100 stack.pop_back(); | |
101 } | |
102 | |
103 while (object && !object->nextSibling()) { | |
104 object->getMutableForPainting().clearPaintFlags(); | |
105 stack.pop_back(); | |
106 object = object->parent(); | |
107 } | |
108 | |
109 if (object) { | |
110 object->getMutableForPainting().clearPaintFlags(); | |
111 object = object->nextSibling(); | |
112 } | |
113 } | |
114 } | |
115 | |
82 static void updateAuxiliaryObjectProperties(const LayoutObject& object, | 116 static void updateAuxiliaryObjectProperties(const LayoutObject& object, |
83 PrePaintTreeWalkContext& context) { | 117 PrePaintTreeWalkContext& context) { |
84 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 118 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
85 return; | 119 return; |
86 | 120 |
87 if (!object.hasLayer()) | 121 if (!object.hasLayer()) |
88 return; | 122 return; |
89 | 123 |
90 PaintLayer* paintLayer = object.enclosingLayer(); | 124 PaintLayer* paintLayer = object.enclosingLayer(); |
91 paintLayer->updateAncestorOverflowLayer(context.ancestorOverflowPaintLayer); | 125 paintLayer->updateAncestorOverflowLayer(context.ancestorOverflowPaintLayer); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 const PrePaintTreeWalkContext& context) { | 259 const PrePaintTreeWalkContext& context) { |
226 return ( | 260 return ( |
227 !object.needsPaintPropertyUpdate() && | 261 !object.needsPaintPropertyUpdate() && |
228 !object.descendantNeedsPaintPropertyUpdate() && | 262 !object.descendantNeedsPaintPropertyUpdate() && |
229 !context.treeBuilderContext.forceSubtreeUpdate && | 263 !context.treeBuilderContext.forceSubtreeUpdate && |
230 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && | 264 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && |
231 !object | 265 !object |
232 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ; | 266 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ; |
233 } | 267 } |
234 | 268 |
235 void PrePaintTreeWalk::walk(const LayoutObject& object, | 269 void PrePaintTreeWalk::walkObject(const LayoutObject& object, |
236 const PrePaintTreeWalkContext& parentContext) { | 270 PrePaintTreeWalkContext& context) { |
237 PrePaintTreeWalkContext context(parentContext); | 271 DCHECK(!shouldEndWalkBefore(object, context)); |
238 | 272 |
239 if (shouldEndWalkBefore(object, parentContext)) | 273 if (object.isLayoutMultiColumnSpannerPlaceholder()) |
240 return; | 274 return; |
241 | 275 |
242 // This must happen before updatePropertiesForSelf, because the latter reads | 276 // This must happen before updatePropertiesForSelf, because the latter reads |
243 // some of the state computed here. | 277 // some of the state computed here. |
244 updateAuxiliaryObjectProperties(object, context); | 278 updateAuxiliaryObjectProperties(object, context); |
245 | 279 |
246 m_propertyTreeBuilder.updatePropertiesForSelf(object, | 280 m_propertyTreeBuilder.updatePropertiesForSelf(object, |
247 context.treeBuilderContext); | 281 context.treeBuilderContext); |
248 m_paintInvalidator.invalidatePaintIfNeeded(object, | 282 m_paintInvalidator.invalidatePaintIfNeeded(object, |
249 context.paintInvalidatorContext); | 283 context.paintInvalidatorContext); |
250 m_propertyTreeBuilder.updatePropertiesForChildren(object, | 284 m_propertyTreeBuilder.updatePropertiesForChildren(object, |
251 context.treeBuilderContext); | 285 context.treeBuilderContext); |
252 | 286 |
253 invalidatePaintLayerOptimizationsIfNeeded(object, context); | 287 invalidatePaintLayerOptimizationsIfNeeded(object, context); |
254 | 288 |
255 for (const LayoutObject* child = object.slowFirstChild(); child; | |
256 child = child->nextSibling()) { | |
257 if (child->isLayoutMultiColumnSpannerPlaceholder()) { | |
258 child->getMutableForPainting().clearPaintFlags(); | |
259 continue; | |
260 } | |
261 walk(*child, context); | |
262 } | |
263 | |
264 if (object.isLayoutPart()) { | 289 if (object.isLayoutPart()) { |
265 const LayoutPart& layoutPart = toLayoutPart(object); | 290 const LayoutPart& layoutPart = toLayoutPart(object); |
266 FrameViewBase* frameViewBase = layoutPart.widget(); | 291 FrameViewBase* frameViewBase = layoutPart.widget(); |
267 if (frameViewBase && frameViewBase->isFrameView()) { | 292 if (frameViewBase && frameViewBase->isFrameView()) { |
268 context.treeBuilderContext.current.paintOffset += | 293 PrePaintTreeWalkContext frameViewContext(context); |
294 frameViewContext.treeBuilderContext.current.paintOffset += | |
269 layoutPart.replacedContentRect().location() - | 295 layoutPart.replacedContentRect().location() - |
270 frameViewBase->frameRect().location(); | 296 frameViewBase->frameRect().location(); |
271 context.treeBuilderContext.current.paintOffset = | 297 frameViewContext.treeBuilderContext.current.paintOffset = roundedIntPoint( |
272 roundedIntPoint(context.treeBuilderContext.current.paintOffset); | 298 frameViewContext.treeBuilderContext.current.paintOffset); |
273 walk(*toFrameView(frameViewBase), context); | 299 walk(*toFrameView(frameViewBase), frameViewContext); |
274 } | 300 } |
275 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 301 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
276 } | 302 } |
277 | |
278 object.getMutableForPainting().clearPaintFlags(); | |
279 } | 303 } |
280 | 304 |
281 } // namespace blink | 305 } // namespace blink |
OLD | NEW |