Chromium Code Reviews| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 DocumentLifecycle::InPrePaint); | 42 DocumentLifecycle::InPrePaint); |
| 43 | 43 |
| 44 PrePaintTreeWalkContext initialContext; | 44 PrePaintTreeWalkContext initialContext; |
| 45 initialContext.treeBuilderContext = | 45 initialContext.treeBuilderContext = |
| 46 m_propertyTreeBuilder.setupInitialContext(); | 46 m_propertyTreeBuilder.setupInitialContext(); |
| 47 initialContext.ancestorTransformedOrRootPaintLayer = | 47 initialContext.ancestorTransformedOrRootPaintLayer = |
| 48 rootFrame.layoutView()->layer(); | 48 rootFrame.layoutView()->layer(); |
| 49 | 49 |
| 50 // GeometryMapper depends on paint properties. | 50 // GeometryMapper depends on paint properties. |
| 51 if (rootFrame.needsPaintPropertyUpdate() || | 51 if (rootFrame.needsPaintPropertyUpdate() || |
| 52 (rootFrame.layoutView() && | 52 (rootFrame.layoutView() && needsWalkForPaintPropertyUpdate( |
| 53 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) | 53 *rootFrame.layoutView(), initialContext))) |
| 54 m_geometryMapper.clearCache(); | 54 m_geometryMapper.clearCache(); |
| 55 | 55 |
| 56 walk(rootFrame, initialContext); | 56 walk(rootFrame, initialContext); |
| 57 m_paintInvalidator.processPendingDelayedPaintInvalidations(); | 57 m_paintInvalidator.processPendingDelayedPaintInvalidations(); |
| 58 } | 58 } |
| 59 | 59 |
| 60 void PrePaintTreeWalk::walk(FrameView& frameView, | 60 void PrePaintTreeWalk::walk(FrameView& frameView, |
| 61 const PrePaintTreeWalkContext& parentContext) { | 61 const PrePaintTreeWalkContext& parentContext) { |
| 62 if (frameView.shouldThrottleRendering()) { | 62 if (frameView.shouldThrottleRendering()) { |
| 63 // Skip the throttled frame. Will update it when it becomes unthrottled. | 63 // Skip the throttled frame. Will update it when it becomes unthrottled. |
| 64 return; | 64 return; |
| 65 } | 65 } |
| 66 | 66 |
| 67 PrePaintTreeWalkContext context(parentContext); | 67 PrePaintTreeWalkContext context(parentContext); |
| 68 // ancestorOverflowLayer does not cross frame boundaries. | 68 // ancestorOverflowLayer does not cross frame boundaries. |
| 69 context.ancestorOverflowPaintLayer = nullptr; | 69 context.ancestorOverflowPaintLayer = nullptr; |
| 70 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); | 70 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); |
| 71 m_paintInvalidator.invalidatePaintIfNeeded(frameView, | 71 m_paintInvalidator.invalidatePaintIfNeeded(frameView, |
| 72 context.paintInvalidatorContext); | 72 context.paintInvalidatorContext); |
| 73 | 73 |
| 74 if (LayoutView* view = frameView.layoutView()) { | 74 if (LayoutView* view = frameView.layoutView()) { |
| 75 #if DCHECK_IS_ON() | |
| 76 context.treeBuilderContext.updatedForSelf = true; | |
| 77 context.treeBuilderContext.updatedForChildren = true; | |
| 78 #endif | |
| 75 walk(*view, context); | 79 walk(*view, context); |
| 76 #if DCHECK_IS_ON() | 80 #if DCHECK_IS_ON() |
| 77 view->assertSubtreeClearedPaintInvalidationFlags(); | 81 view->assertSubtreeClearedPaintInvalidationFlags(); |
| 78 #endif | 82 #endif |
| 79 } | 83 } |
| 80 frameView.clearNeedsPaintPropertyUpdate(); | 84 frameView.clearNeedsPaintPropertyUpdate(); |
| 81 } | 85 } |
| 82 | 86 |
| 83 static void updateAuxiliaryObjectProperties(const LayoutObject& object, | 87 static void updateAuxiliaryObjectProperties(const LayoutObject& object, |
| 84 PrePaintTreeWalkContext& context) { | 88 PrePaintTreeWalkContext& context) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 rect.moveBy(-FloatPoint(ancestorPaintOffset)); | 140 rect.moveBy(-FloatPoint(ancestorPaintOffset)); |
| 137 return rect; | 141 return rect; |
| 138 } | 142 } |
| 139 | 143 |
| 140 void PrePaintTreeWalk::invalidatePaintLayerOptimizationsIfNeeded( | 144 void PrePaintTreeWalk::invalidatePaintLayerOptimizationsIfNeeded( |
| 141 const LayoutObject& object, | 145 const LayoutObject& object, |
| 142 PrePaintTreeWalkContext& context) { | 146 PrePaintTreeWalkContext& context) { |
| 143 if (!object.hasLayer()) | 147 if (!object.hasLayer()) |
| 144 return; | 148 return; |
| 145 | 149 |
| 150 #if DCHECK_IS_ON() | |
| 151 DCHECK(context.treeBuilderContext.updatedForChildren); | |
| 152 #endif | |
| 153 | |
| 146 PaintLayer& paintLayer = *toLayoutBoxModelObject(object).layer(); | 154 PaintLayer& paintLayer = *toLayoutBoxModelObject(object).layer(); |
| 147 if (object.styleRef().hasTransform() || | 155 if (object.styleRef().hasTransform() || |
| 148 &object == context.paintInvalidatorContext.paintInvalidationContainer) { | 156 &object == context.paintInvalidatorContext.paintInvalidationContainer) { |
| 149 context.ancestorTransformedOrRootPaintLayer = &paintLayer; | 157 context.ancestorTransformedOrRootPaintLayer = &paintLayer; |
| 150 } | 158 } |
| 151 | 159 |
| 152 const ObjectPaintProperties& ancestorPaintProperties = | 160 const ObjectPaintProperties& ancestorPaintProperties = |
| 153 *context.ancestorTransformedOrRootPaintLayer->layoutObject() | 161 *context.ancestorTransformedOrRootPaintLayer->layoutObject() |
| 154 .paintProperties(); | 162 .paintProperties(); |
| 155 PropertyTreeState ancestorState = | 163 PropertyTreeState ancestorState = |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); | 216 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); |
| 209 | 217 |
| 210 if (!previousClipRects || *clipRects != *previousClipRects) { | 218 if (!previousClipRects || *clipRects != *previousClipRects) { |
| 211 paintLayer.setNeedsRepaint(); | 219 paintLayer.setNeedsRepaint(); |
| 212 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); | 220 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); |
| 213 paintLayer.setPreviousPaintPhaseFloatEmpty(false); | 221 paintLayer.setPreviousPaintPhaseFloatEmpty(false); |
| 214 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); | 222 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); |
| 215 // All subsequences which are contained below this paintLayer must also | 223 // All subsequences which are contained below this paintLayer must also |
| 216 // be checked. | 224 // be checked. |
| 217 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= | 225 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= |
| 218 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 226 PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate; |
| 219 } | 227 } |
| 220 | 228 |
| 221 paintLayer.setPreviousPaintingClipRects(*clipRects); | 229 paintLayer.setPreviousPaintingClipRects(*clipRects); |
| 222 } | 230 } |
| 223 | 231 |
| 224 bool PrePaintTreeWalk::shouldEndWalkBefore( | 232 bool PrePaintTreeWalk::needsWalkForPaintPropertyUpdate( |
| 225 const LayoutObject& object, | 233 const LayoutObject& object, |
| 226 const PrePaintTreeWalkContext& context) { | 234 const PrePaintTreeWalkContext& context) { |
| 227 return ( | 235 return object.needsPaintPropertyUpdate() || |
| 228 !object.needsPaintPropertyUpdate() && | 236 object.descendantNeedsPaintPropertyUpdate() || |
| 229 !object.descendantNeedsPaintPropertyUpdate() && | 237 context.treeBuilderContext.forceSubtreeUpdate || |
| 230 !context.treeBuilderContext.forceSubtreeUpdate && | 238 // If the object needs visual rect update, we should update paint |
| 231 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && | 239 // properties which are needed by visual rect update. |
| 232 !object | 240 m_paintInvalidator.needsVisualRectUpdate( |
| 233 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) ; | 241 object, context.paintInvalidatorContext); |
| 234 } | 242 } |
| 235 | 243 |
| 236 void PrePaintTreeWalk::walk(const LayoutObject& object, | 244 void PrePaintTreeWalk::walk(const LayoutObject& object, |
| 237 const PrePaintTreeWalkContext& parentContext) { | 245 const PrePaintTreeWalkContext& parentContext) { |
| 238 if (shouldEndWalkBefore(object, parentContext)) | 246 // Early out from the treewalk if possible. |
| 247 bool needsWalkForPaintPropertyUpdate = | |
| 248 this->needsWalkForPaintPropertyUpdate(object, parentContext); | |
| 249 if (!needsWalkForPaintPropertyUpdate && | |
| 250 !object | |
| 251 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) | |
| 239 return; | 252 return; |
| 240 | 253 |
| 241 // PrePaintTreeWalkContext is large and can lead to stack overflows when | 254 // PrePaintTreeWalkContext is large and can lead to stack overflows when |
| 242 // recursion is deep so this context object is allocated on the heap. | 255 // recursion is deep so this context object is allocated on the heap. |
| 243 // See: https://crbug.com/698653. | 256 // See: https://crbug.com/698653. |
| 244 std::unique_ptr<PrePaintTreeWalkContext> context = | 257 std::unique_ptr<PrePaintTreeWalkContext> context = |
| 245 WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext)); | 258 WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext)); |
| 246 | 259 |
| 247 // This must happen before updatePropertiesForSelf, because the latter reads | 260 // This must happen before updatePropertiesForSelf, because the latter reads |
| 248 // some of the state computed here. | 261 // some of the state computed here. |
| 249 updateAuxiliaryObjectProperties(object, *context); | 262 updateAuxiliaryObjectProperties(object, *context); |
| 250 | 263 |
| 251 m_propertyTreeBuilder.updatePropertiesForSelf(object, | 264 if (needsWalkForPaintPropertyUpdate) { |
|
pdr.
2017/03/10 06:21:39
Trying to think of ways to simplify these DCHECKS.
Xianzhu
2017/03/10 17:43:05
This looks a good idea. Will try.
Xianzhu
2017/03/13 19:08:09
I tried the method, but found that we still need t
| |
| 252 context->treeBuilderContext); | 265 #if DCHECK_IS_ON() |
| 266 DCHECK(context->treeBuilderContext.parentUpdated); | |
| 267 #endif | |
| 268 m_propertyTreeBuilder.updatePropertiesForSelf(object, | |
| 269 context->treeBuilderContext); | |
| 270 #if DCHECK_IS_ON() | |
| 271 context->treeBuilderContext.updatedForSelf = true; | |
| 272 #endif | |
| 273 } else { | |
| 274 #if DCHECK_IS_ON() | |
| 275 // When DCHECK_IS_ON, always update paint properties so that paint | |
| 276 // invalidator can update visual rect for checking missing flags. | |
| 277 LayoutPoint oldPaintOffset = object.paintOffset(); | |
| 278 m_propertyTreeBuilder.updatePropertiesForSelf(object, | |
| 279 context->treeBuilderContext); | |
| 280 DCHECK(object.paintOffset() == oldPaintOffset) | |
| 281 << "Paint offset changed without needsPaintOffsetAndVisualRectUpdate" | |
| 282 << " old=" << oldPaintOffset.toString() | |
| 283 << " new=" << object.paintOffset().toString(); | |
| 284 #endif | |
| 285 } | |
| 286 | |
| 253 m_paintInvalidator.invalidatePaintIfNeeded(object, | 287 m_paintInvalidator.invalidatePaintIfNeeded(object, |
| 254 context->paintInvalidatorContext); | 288 context->paintInvalidatorContext); |
| 255 m_propertyTreeBuilder.updatePropertiesForChildren( | |
| 256 object, context->treeBuilderContext); | |
| 257 | 289 |
| 258 invalidatePaintLayerOptimizationsIfNeeded(object, *context); | 290 if (needsWalkForPaintPropertyUpdate) { |
| 291 m_propertyTreeBuilder.updatePropertiesForChildren( | |
| 292 object, context->treeBuilderContext); | |
| 293 #if DCHECK_IS_ON() | |
| 294 context->treeBuilderContext.updatedForChildren = true; | |
| 295 #endif | |
| 296 invalidatePaintLayerOptimizationsIfNeeded(object, *context); | |
| 297 } else { | |
| 298 #if DCHECK_IS_ON() | |
| 299 // When DCHECK_IS_ON, always update paint properties so that paint | |
| 300 // invalidator can update visual rect for checking missing flags. | |
| 301 m_propertyTreeBuilder.updatePropertiesForChildren( | |
| 302 object, context->treeBuilderContext); | |
| 303 #endif | |
| 304 } | |
| 259 | 305 |
| 260 for (const LayoutObject* child = object.slowFirstChild(); child; | 306 for (const LayoutObject* child = object.slowFirstChild(); child; |
| 261 child = child->nextSibling()) { | 307 child = child->nextSibling()) { |
| 262 if (child->isLayoutMultiColumnSpannerPlaceholder()) { | 308 if (child->isLayoutMultiColumnSpannerPlaceholder()) { |
| 263 child->getMutableForPainting().clearPaintFlags(); | 309 child->getMutableForPainting().clearPaintFlags(); |
| 264 continue; | 310 continue; |
| 265 } | 311 } |
| 266 walk(*child, *context); | 312 walk(*child, *context); |
| 267 } | 313 } |
| 268 | 314 |
| 269 if (object.isLayoutPart()) { | 315 if (object.isLayoutPart()) { |
| 270 const LayoutPart& layoutPart = toLayoutPart(object); | 316 const LayoutPart& layoutPart = toLayoutPart(object); |
| 271 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); | 317 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); |
| 272 if (frameViewBase && frameViewBase->isFrameView()) { | 318 if (frameViewBase && frameViewBase->isFrameView()) { |
| 273 context->treeBuilderContext.current.paintOffset += | 319 context->treeBuilderContext.current.paintOffset += |
| 274 layoutPart.replacedContentRect().location() - | 320 layoutPart.replacedContentRect().location() - |
| 275 frameViewBase->frameRect().location(); | 321 frameViewBase->frameRect().location(); |
| 276 context->treeBuilderContext.current.paintOffset = | 322 context->treeBuilderContext.current.paintOffset = |
| 277 roundedIntPoint(context->treeBuilderContext.current.paintOffset); | 323 roundedIntPoint(context->treeBuilderContext.current.paintOffset); |
| 278 walk(*toFrameView(frameViewBase), *context); | 324 walk(*toFrameView(frameViewBase), *context); |
| 279 } | 325 } |
| 280 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 326 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 281 } | 327 } |
| 282 | 328 |
| 283 object.getMutableForPainting().clearPaintFlags(); | 329 object.getMutableForPainting().clearPaintFlags(); |
| 284 } | 330 } |
| 285 | 331 |
| 286 } // namespace blink | 332 } // namespace blink |
| OLD | NEW |