| 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 USING_FAST_MALLOC(PrePaintTreeWalkContext); |
| 19 |
| 20 public: |
| 18 PrePaintTreeWalkContext() | 21 PrePaintTreeWalkContext() |
| 19 : treeBuilderContext( | 22 : treeBuilderContext(), |
| 20 WTF::wrapUnique(new PaintPropertyTreeBuilderContext)), | 23 paintInvalidatorContext(treeBuilderContext), |
| 21 paintInvalidatorContext(*treeBuilderContext), | |
| 22 ancestorOverflowPaintLayer(nullptr), | 24 ancestorOverflowPaintLayer(nullptr), |
| 23 ancestorTransformedOrRootPaintLayer(nullptr) {} | 25 ancestorTransformedOrRootPaintLayer(nullptr) {} |
| 24 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext) | 26 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parentContext) |
| 25 : treeBuilderContext(WTF::wrapUnique(new PaintPropertyTreeBuilderContext( | 27 : treeBuilderContext(parentContext.treeBuilderContext), |
| 26 *parentContext.treeBuilderContext))), | 28 paintInvalidatorContext(treeBuilderContext, |
| 27 paintInvalidatorContext(*treeBuilderContext, | |
| 28 parentContext.paintInvalidatorContext), | 29 parentContext.paintInvalidatorContext), |
| 29 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer), | 30 ancestorOverflowPaintLayer(parentContext.ancestorOverflowPaintLayer), |
| 30 ancestorTransformedOrRootPaintLayer( | 31 ancestorTransformedOrRootPaintLayer( |
| 31 parentContext.ancestorTransformedOrRootPaintLayer) {} | 32 parentContext.ancestorTransformedOrRootPaintLayer) {} |
| 32 | 33 |
| 33 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows | 34 PaintPropertyTreeBuilderContext treeBuilderContext; |
| 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 | 35 |
| 38 PaintInvalidatorContext paintInvalidatorContext; | 36 PaintInvalidatorContext paintInvalidatorContext; |
| 39 | 37 |
| 40 // The ancestor in the PaintLayer tree which has overflow clip, or | 38 // The ancestor in the PaintLayer tree which has overflow clip, or |
| 41 // is the root layer. Note that it is tree ancestor, not containing | 39 // is the root layer. Note that it is tree ancestor, not containing |
| 42 // block or stacking ancestor. | 40 // block or stacking ancestor. |
| 43 PaintLayer* ancestorOverflowPaintLayer; | 41 PaintLayer* ancestorOverflowPaintLayer; |
| 44 PaintLayer* ancestorTransformedOrRootPaintLayer; | 42 PaintLayer* ancestorTransformedOrRootPaintLayer; |
| 45 }; | 43 }; |
| 46 | 44 |
| 47 void PrePaintTreeWalk::walk(FrameView& rootFrame) { | 45 void PrePaintTreeWalk::walk(FrameView& rootFrame) { |
| 48 DCHECK(rootFrame.frame().document()->lifecycle().state() == | 46 DCHECK(rootFrame.frame().document()->lifecycle().state() == |
| 49 DocumentLifecycle::InPrePaint); | 47 DocumentLifecycle::InPrePaint); |
| 50 | 48 |
| 51 PrePaintTreeWalkContext initialContext; | 49 PrePaintTreeWalkContext initialContext; |
| 52 m_propertyTreeBuilder.setupInitialContext(*initialContext.treeBuilderContext); | 50 m_propertyTreeBuilder.setupInitialContext(initialContext.treeBuilderContext); |
| 53 initialContext.ancestorTransformedOrRootPaintLayer = | 51 initialContext.ancestorTransformedOrRootPaintLayer = |
| 54 rootFrame.layoutView()->layer(); | 52 rootFrame.layoutView()->layer(); |
| 55 | 53 |
| 56 // GeometryMapper depends on paint properties. | 54 // GeometryMapper depends on paint properties. |
| 57 if (rootFrame.needsPaintPropertyUpdate() || | 55 if (rootFrame.needsPaintPropertyUpdate() || |
| 58 (rootFrame.layoutView() && | 56 (rootFrame.layoutView() && |
| 59 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) | 57 !shouldEndWalkBefore(*rootFrame.layoutView(), initialContext))) |
| 60 m_geometryMapper.clearCache(); | 58 m_geometryMapper.clearCache(); |
| 61 | 59 |
| 62 walk(rootFrame, initialContext); | 60 walk(rootFrame, initialContext); |
| 63 m_paintInvalidator.processPendingDelayedPaintInvalidations(); | 61 m_paintInvalidator.processPendingDelayedPaintInvalidations(); |
| 64 } | 62 } |
| 65 | 63 |
| 66 void PrePaintTreeWalk::walk(FrameView& frameView, | 64 void PrePaintTreeWalk::walk(FrameView& frameView, |
| 67 const PrePaintTreeWalkContext& parentContext) { | 65 const PrePaintTreeWalkContext& parentContext) { |
| 68 if (frameView.shouldThrottleRendering()) { | 66 if (frameView.shouldThrottleRendering()) { |
| 69 // Skip the throttled frame. Will update it when it becomes unthrottled. | 67 // Skip the throttled frame. Will update it when it becomes unthrottled. |
| 70 return; | 68 return; |
| 71 } | 69 } |
| 72 | 70 |
| 73 PrePaintTreeWalkContext context(parentContext); | 71 PrePaintTreeWalkContext context(parentContext); |
| 74 // ancestorOverflowLayer does not cross frame boundaries. | 72 // ancestorOverflowLayer does not cross frame boundaries. |
| 75 context.ancestorOverflowPaintLayer = nullptr; | 73 context.ancestorOverflowPaintLayer = nullptr; |
| 76 m_propertyTreeBuilder.updateProperties(frameView, | 74 m_propertyTreeBuilder.updateProperties(frameView, context.treeBuilderContext); |
| 77 *context.treeBuilderContext); | |
| 78 m_paintInvalidator.invalidatePaintIfNeeded(frameView, | 75 m_paintInvalidator.invalidatePaintIfNeeded(frameView, |
| 79 context.paintInvalidatorContext); | 76 context.paintInvalidatorContext); |
| 80 | 77 |
| 81 if (LayoutView* view = frameView.layoutView()) { | 78 if (LayoutView* view = frameView.layoutView()) { |
| 82 walk(*view, context); | 79 walk(*view, context); |
| 83 #if DCHECK_IS_ON() | 80 #if DCHECK_IS_ON() |
| 84 view->assertSubtreeClearedPaintInvalidationFlags(); | 81 view->assertSubtreeClearedPaintInvalidationFlags(); |
| 85 #endif | 82 #endif |
| 86 } | 83 } |
| 87 frameView.clearNeedsPaintPropertyUpdate(); | 84 frameView.clearNeedsPaintPropertyUpdate(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 respectOverflowClip, LayoutSize()); | 176 respectOverflowClip, LayoutSize()); |
| 180 #endif | 177 #endif |
| 181 | 178 |
| 182 bool hasClip = false; | 179 bool hasClip = false; |
| 183 RefPtr<ClipRects> clipRects = ClipRects::create(); | 180 RefPtr<ClipRects> clipRects = ClipRects::create(); |
| 184 const LayoutPoint& ancestorPaintOffset = | 181 const LayoutPoint& ancestorPaintOffset = |
| 185 context.ancestorTransformedOrRootPaintLayer->layoutObject().paintOffset(); | 182 context.ancestorTransformedOrRootPaintLayer->layoutObject().paintOffset(); |
| 186 | 183 |
| 187 FloatClipRect clipRect; | 184 FloatClipRect clipRect; |
| 188 const EffectPaintPropertyNode* effect = | 185 const EffectPaintPropertyNode* effect = |
| 189 context.treeBuilderContext->currentEffect; | 186 context.treeBuilderContext.currentEffect; |
| 190 computeClipRectForContext(context.treeBuilderContext->current, effect, | 187 computeClipRectForContext(context.treeBuilderContext.current, effect, |
| 191 ancestorState, ancestorPaintOffset, hasClip, | 188 ancestorState, ancestorPaintOffset, hasClip, |
| 192 clipRect); | 189 clipRect); |
| 193 clipRects->setOverflowClipRect(clipRect); | 190 clipRects->setOverflowClipRect(clipRect); |
| 194 #ifdef CHECK_CLIP_RECTS | 191 #ifdef CHECK_CLIP_RECTS |
| 195 CHECK(!hasClip || | 192 CHECK(!hasClip || |
| 196 clipRects->overflowClipRect() == oldClipRects.overflowClipRect()) | 193 clipRects->overflowClipRect() == oldClipRects.overflowClipRect()) |
| 197 << "rect= " << clipRects->overflowClipRect().toString(); | 194 << "rect= " << clipRects->overflowClipRect().toString(); |
| 198 #endif | 195 #endif |
| 199 | 196 |
| 200 computeClipRectForContext(context.treeBuilderContext->fixedPosition, effect, | 197 computeClipRectForContext(context.treeBuilderContext.fixedPosition, effect, |
| 201 ancestorState, ancestorPaintOffset, hasClip, | 198 ancestorState, ancestorPaintOffset, hasClip, |
| 202 clipRect); | 199 clipRect); |
| 203 clipRects->setFixedClipRect(clipRect); | 200 clipRects->setFixedClipRect(clipRect); |
| 204 #ifdef CHECK_CLIP_RECTS | 201 #ifdef CHECK_CLIP_RECTS |
| 205 CHECK(hasClip || clipRects->fixedClipRect() == oldClipRects.fixedClipRect()) | 202 CHECK(hasClip || clipRects->fixedClipRect() == oldClipRects.fixedClipRect()) |
| 206 << " fixed=" << clipRects->fixedClipRect().toString(); | 203 << " fixed=" << clipRects->fixedClipRect().toString(); |
| 207 #endif | 204 #endif |
| 208 | 205 |
| 209 computeClipRectForContext(context.treeBuilderContext->absolutePosition, | 206 computeClipRectForContext(context.treeBuilderContext.absolutePosition, effect, |
| 210 effect, ancestorState, ancestorPaintOffset, hasClip, | 207 ancestorState, ancestorPaintOffset, hasClip, |
| 211 clipRect); | 208 clipRect); |
| 212 clipRects->setPosClipRect(clipRect); | 209 clipRects->setPosClipRect(clipRect); |
| 213 #ifdef CHECK_CLIP_RECTS | 210 #ifdef CHECK_CLIP_RECTS |
| 214 CHECK(!hasClip || clipRects->posClipRect() == oldClipRects.posClipRect()) | 211 CHECK(!hasClip || clipRects->posClipRect() == oldClipRects.posClipRect()) |
| 215 << " abs=" << clipRects->posClipRect().toString(); | 212 << " abs=" << clipRects->posClipRect().toString(); |
| 216 #endif | 213 #endif |
| 217 | 214 |
| 218 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); | 215 ClipRects* previousClipRects = paintLayer.previousPaintingClipRects(); |
| 219 | 216 |
| 220 if (!previousClipRects || *clipRects != *previousClipRects) { | 217 if (!previousClipRects || *clipRects != *previousClipRects) { |
| 221 paintLayer.setNeedsRepaint(); | 218 paintLayer.setNeedsRepaint(); |
| 222 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); | 219 paintLayer.setPreviousPaintPhaseDescendantOutlinesEmpty(false); |
| 223 paintLayer.setPreviousPaintPhaseFloatEmpty(false); | 220 paintLayer.setPreviousPaintPhaseFloatEmpty(false); |
| 224 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); | 221 paintLayer.setPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); |
| 225 // All subsequences which are contained below this paintLayer must also | 222 // All subsequences which are contained below this paintLayer must also |
| 226 // be checked. | 223 // be checked. |
| 227 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= | 224 context.paintInvalidatorContext.forcedSubtreeInvalidationFlags |= |
| 228 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 225 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
| 229 } | 226 } |
| 230 | 227 |
| 231 paintLayer.setPreviousPaintingClipRects(*clipRects); | 228 paintLayer.setPreviousPaintingClipRects(*clipRects); |
| 232 } | 229 } |
| 233 | 230 |
| 234 bool PrePaintTreeWalk::shouldEndWalkBefore( | 231 bool PrePaintTreeWalk::shouldEndWalkBefore( |
| 235 const LayoutObject& object, | 232 const LayoutObject& object, |
| 236 const PrePaintTreeWalkContext& context) { | 233 const PrePaintTreeWalkContext& context) { |
| 237 return ( | 234 return ( |
| 238 !object.needsPaintPropertyUpdate() && | 235 !object.needsPaintPropertyUpdate() && |
| 239 !object.descendantNeedsPaintPropertyUpdate() && | 236 !object.descendantNeedsPaintPropertyUpdate() && |
| 240 !context.treeBuilderContext->forceSubtreeUpdate && | 237 !context.treeBuilderContext.forceSubtreeUpdate && |
| 241 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && | 238 !context.paintInvalidatorContext.forcedSubtreeInvalidationFlags && |
| 242 !object | 239 !object |
| 243 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState())
; | 240 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState())
; |
| 244 } | 241 } |
| 245 | 242 |
| 246 void PrePaintTreeWalk::walk(const LayoutObject& object, | 243 void PrePaintTreeWalk::walk(const LayoutObject& object, |
| 247 const PrePaintTreeWalkContext& parentContext) { | 244 const PrePaintTreeWalkContext& parentContext) { |
| 248 if (shouldEndWalkBefore(object, parentContext)) | 245 if (shouldEndWalkBefore(object, parentContext)) |
| 249 return; | 246 return; |
| 250 | 247 |
| 251 PrePaintTreeWalkContext context(parentContext); | 248 PrePaintTreeWalkContext context(parentContext); |
| 252 | 249 |
| 253 // This must happen before updatePropertiesForSelf, because the latter reads | 250 // This must happen before updatePropertiesForSelf, because the latter reads |
| 254 // some of the state computed here. | 251 // some of the state computed here. |
| 255 updateAuxiliaryObjectProperties(object, context); | 252 updateAuxiliaryObjectProperties(object, context); |
| 256 | 253 |
| 257 m_propertyTreeBuilder.updatePropertiesForSelf(object, | 254 m_propertyTreeBuilder.updatePropertiesForSelf(object, |
| 258 *context.treeBuilderContext); | 255 context.treeBuilderContext); |
| 259 m_paintInvalidator.invalidatePaintIfNeeded(object, | 256 m_paintInvalidator.invalidatePaintIfNeeded(object, |
| 260 context.paintInvalidatorContext); | 257 context.paintInvalidatorContext); |
| 261 m_propertyTreeBuilder.updatePropertiesForChildren( | 258 m_propertyTreeBuilder.updatePropertiesForChildren(object, |
| 262 object, *context.treeBuilderContext); | 259 context.treeBuilderContext); |
| 263 | 260 |
| 264 invalidatePaintLayerOptimizationsIfNeeded(object, context); | 261 invalidatePaintLayerOptimizationsIfNeeded(object, context); |
| 265 | 262 |
| 266 for (const LayoutObject* child = object.slowFirstChild(); child; | 263 for (const LayoutObject* child = object.slowFirstChild(); child; |
| 267 child = child->nextSibling()) { | 264 child = child->nextSibling()) { |
| 268 if (child->isLayoutMultiColumnSpannerPlaceholder()) { | 265 if (child->isLayoutMultiColumnSpannerPlaceholder()) { |
| 269 child->getMutableForPainting().clearPaintFlags(); | 266 child->getMutableForPainting().clearPaintFlags(); |
| 270 continue; | 267 continue; |
| 271 } | 268 } |
| 272 walk(*child, context); | 269 walk(*child, context); |
| 273 } | 270 } |
| 274 | 271 |
| 275 if (object.isLayoutPart()) { | 272 if (object.isLayoutPart()) { |
| 276 const LayoutPart& layoutPart = toLayoutPart(object); | 273 const LayoutPart& layoutPart = toLayoutPart(object); |
| 277 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); | 274 FrameViewBase* frameViewBase = layoutPart.frameViewBase(); |
| 278 if (frameViewBase && frameViewBase->isFrameView()) { | 275 if (frameViewBase && frameViewBase->isFrameView()) { |
| 279 context.treeBuilderContext->current.paintOffset += | 276 context.treeBuilderContext.current.paintOffset += |
| 280 layoutPart.replacedContentRect().location() - | 277 layoutPart.replacedContentRect().location() - |
| 281 frameViewBase->frameRect().location(); | 278 frameViewBase->frameRect().location(); |
| 282 context.treeBuilderContext->current.paintOffset = | 279 context.treeBuilderContext.current.paintOffset = |
| 283 roundedIntPoint(context.treeBuilderContext->current.paintOffset); | 280 roundedIntPoint(context.treeBuilderContext.current.paintOffset); |
| 284 walk(*toFrameView(frameViewBase), context); | 281 walk(*toFrameView(frameViewBase), context); |
| 285 } | 282 } |
| 286 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 283 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 287 } | 284 } |
| 288 | 285 |
| 289 object.getMutableForPainting().clearPaintFlags(); | 286 object.getMutableForPainting().clearPaintFlags(); |
| 290 } | 287 } |
| 291 | 288 |
| 292 } // namespace blink | 289 } // namespace blink |
| OLD | NEW |