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" |
| 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 #include "platform/graphics/paint/GeometryMapper.h" | 14 #include "platform/graphics/paint/GeometryMapper.h" |
| 15 | 15 |
| 16 namespace blink { | 16 namespace blink { |
| 17 | 17 |
| 18 struct PrePaintTreeWalkContext { | 18 struct PrePaintTreeWalkContext { |
| 19 PrePaintTreeWalkContext() | 19 PrePaintTreeWalkContext() |
| 20 : tree_builder_context( | 20 : tree_builder_context( |
| 21 WTF::WrapUnique(new PaintPropertyTreeBuilderContext)), | 21 WTF::WrapUnique(new PaintPropertyTreeBuilderContext)), |
| 22 paint_invalidator_context(tree_builder_context.get()), | 22 paint_invalidator_context(tree_builder_context.get()), |
| 23 ancestor_overflow_paint_layer(nullptr), | 23 ancestor_overflow_paint_layer(nullptr), |
| 24 ancestor_transformed_or_root_paint_layer(nullptr) {} | 24 ancestor_transformed_or_root_paint_layer(nullptr), |
| 25 enclosing_paint_layer(nullptr) {} | |
| 25 | 26 |
| 26 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parent_context, | 27 PrePaintTreeWalkContext(const PrePaintTreeWalkContext& parent_context, |
| 27 bool needs_tree_builder_context) | 28 bool needs_tree_builder_context) |
| 28 : tree_builder_context( | 29 : tree_builder_context( |
| 29 WTF::WrapUnique(needs_tree_builder_context || DCHECK_IS_ON() | 30 WTF::WrapUnique(needs_tree_builder_context || DCHECK_IS_ON() |
| 30 ? new PaintPropertyTreeBuilderContext( | 31 ? new PaintPropertyTreeBuilderContext( |
| 31 *parent_context.tree_builder_context) | 32 *parent_context.tree_builder_context) |
| 32 : nullptr)), | 33 : nullptr)), |
| 33 paint_invalidator_context(tree_builder_context.get(), | 34 paint_invalidator_context(tree_builder_context.get(), |
| 34 parent_context.paint_invalidator_context), | 35 parent_context.paint_invalidator_context), |
| 35 ancestor_overflow_paint_layer( | 36 ancestor_overflow_paint_layer( |
| 36 parent_context.ancestor_overflow_paint_layer), | 37 parent_context.ancestor_overflow_paint_layer), |
| 37 ancestor_transformed_or_root_paint_layer( | 38 ancestor_transformed_or_root_paint_layer( |
| 38 parent_context.ancestor_transformed_or_root_paint_layer) { | 39 parent_context.ancestor_transformed_or_root_paint_layer), |
| 40 enclosing_paint_layer(parent_context.enclosing_paint_layer) { | |
| 39 #if DCHECK_IS_ON() | 41 #if DCHECK_IS_ON() |
| 40 if (needs_tree_builder_context) | 42 if (needs_tree_builder_context) |
| 41 DCHECK(parent_context.tree_builder_context->is_actually_needed); | 43 DCHECK(parent_context.tree_builder_context->is_actually_needed); |
| 42 tree_builder_context->is_actually_needed = needs_tree_builder_context; | 44 tree_builder_context->is_actually_needed = needs_tree_builder_context; |
| 43 #endif | 45 #endif |
| 44 } | 46 } |
| 45 | 47 |
| 46 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows | 48 // PaintPropertyTreeBuilderContext is large and can lead to stack overflows |
| 47 // when recursion is deep so this context object is allocated on the heap. | 49 // when recursion is deep so this context object is allocated on the heap. |
| 48 // See: https://crbug.com/698653. | 50 // See: https://crbug.com/698653. |
| 49 std::unique_ptr<PaintPropertyTreeBuilderContext> tree_builder_context; | 51 std::unique_ptr<PaintPropertyTreeBuilderContext> tree_builder_context; |
| 50 | 52 |
| 51 PaintInvalidatorContext paint_invalidator_context; | 53 PaintInvalidatorContext paint_invalidator_context; |
| 52 | 54 |
| 53 // The ancestor in the PaintLayer tree which has overflow clip, or | 55 // The ancestor in the PaintLayer tree which has overflow clip, or |
| 54 // is the root layer. Note that it is tree ancestor, not containing | 56 // is the root layer. Note that it is tree ancestor, not containing |
| 55 // block or stacking ancestor. | 57 // block or stacking ancestor. |
| 56 PaintLayer* ancestor_overflow_paint_layer; | 58 PaintLayer* ancestor_overflow_paint_layer; |
| 57 PaintLayer* ancestor_transformed_or_root_paint_layer; | 59 PaintLayer* ancestor_transformed_or_root_paint_layer; |
| 60 PaintLayer* enclosing_paint_layer; | |
| 58 }; | 61 }; |
| 59 | 62 |
| 60 void PrePaintTreeWalk::Walk(FrameView& root_frame) { | 63 void PrePaintTreeWalk::Walk(FrameView& root_frame) { |
| 61 DCHECK(root_frame.GetFrame().GetDocument()->Lifecycle().GetState() == | 64 DCHECK(root_frame.GetFrame().GetDocument()->Lifecycle().GetState() == |
| 62 DocumentLifecycle::kInPrePaint); | 65 DocumentLifecycle::kInPrePaint); |
| 63 | 66 |
| 64 PrePaintTreeWalkContext initial_context; | 67 PrePaintTreeWalkContext initial_context; |
| 65 initial_context.ancestor_transformed_or_root_paint_layer = | 68 initial_context.ancestor_transformed_or_root_paint_layer = |
| 66 root_frame.GetLayoutView()->Layer(); | 69 root_frame.GetLayoutView()->Layer(); |
| 67 | 70 |
| 68 // GeometryMapper depends on paint properties. | 71 // GeometryMapper depends on paint properties. |
| 69 if (NeedsTreeBuilderContextUpdate(root_frame, initial_context)) | 72 if (NeedsTreeBuilderContextUpdate(root_frame, initial_context)) { |
| 70 GeometryMapper::ClearCache(); | 73 GeometryMapper::ClearCache(); |
| 74 } | |
| 71 | 75 |
| 72 Walk(root_frame, initial_context); | 76 Walk(root_frame, initial_context); |
| 73 paint_invalidator_.ProcessPendingDelayedPaintInvalidations(); | 77 paint_invalidator_.ProcessPendingDelayedPaintInvalidations(); |
| 74 } | 78 } |
| 75 | 79 |
| 76 void PrePaintTreeWalk::Walk(FrameView& frame_view, | 80 void PrePaintTreeWalk::Walk(FrameView& frame_view, |
| 77 const PrePaintTreeWalkContext& parent_context) { | 81 const PrePaintTreeWalkContext& parent_context) { |
| 78 if (frame_view.ShouldThrottleRendering()) { | 82 if (frame_view.ShouldThrottleRendering()) { |
| 79 // Skip the throttled frame. Will update it when it becomes unthrottled. | 83 // Skip the throttled frame. Will update it when it becomes unthrottled. |
| 80 return; | 84 return; |
| 81 } | 85 } |
| 82 | |
| 83 bool needs_tree_builder_context_update = | 86 bool needs_tree_builder_context_update = |
| 84 this->NeedsTreeBuilderContextUpdate(frame_view, parent_context); | 87 this->NeedsTreeBuilderContextUpdate(frame_view, parent_context); |
| 85 PrePaintTreeWalkContext context(parent_context, | 88 PrePaintTreeWalkContext context(parent_context, |
| 86 needs_tree_builder_context_update); | 89 needs_tree_builder_context_update); |
| 87 // ancestorOverflowLayer does not cross frame boundaries. | 90 // ancestorOverflowLayer does not cross frame boundaries. |
| 88 context.ancestor_overflow_paint_layer = nullptr; | 91 context.ancestor_overflow_paint_layer = nullptr; |
| 89 if (context.tree_builder_context) { | 92 if (context.tree_builder_context) { |
| 90 property_tree_builder_.UpdateProperties(frame_view, | 93 property_tree_builder_.UpdateProperties(frame_view, |
| 91 *context.tree_builder_context); | 94 *context.tree_builder_context); |
| 92 } | 95 } |
| 93 paint_invalidator_.InvalidatePaintIfNeeded(frame_view, | 96 paint_invalidator_.InvalidatePaintIfNeeded(frame_view, |
| 94 context.paint_invalidator_context); | 97 context.paint_invalidator_context); |
| 95 | 98 |
| 96 if (LayoutView* view = frame_view.GetLayoutView()) { | 99 if (LayoutView* view = frame_view.GetLayoutView()) { |
| 97 Walk(*view, context); | 100 bool ignored; |
| 101 if (!ShouldEarlyOut(*view, context, ignored)) { | |
| 102 context.enclosing_paint_layer = view->Layer(); | |
| 103 if (!context.tree_builder_context) { | |
| 104 context.tree_builder_context = | |
| 105 WTF::WrapUnique(new PaintPropertyTreeBuilderContext); | |
|
chrishtr
2017/04/12 17:31:41
This is a little weird and awkward, let's discuss
| |
| 106 } | |
| 107 #if DCHECK_IS_ON() | |
| 108 if (context.tree_builder_context) | |
| 109 context.tree_builder_context->is_actually_needed = true; | |
| 110 #endif | |
| 111 Walk(*view, context); | |
| 112 } | |
| 98 #if DCHECK_IS_ON() | 113 #if DCHECK_IS_ON() |
| 99 view->AssertSubtreeClearedPaintInvalidationFlags(); | 114 view->AssertSubtreeClearedPaintInvalidationFlags(); |
| 100 #endif | 115 #endif |
| 101 } | 116 } |
| 102 frame_view.ClearNeedsPaintPropertyUpdate(); | 117 frame_view.ClearNeedsPaintPropertyUpdate(); |
| 103 } | 118 } |
| 104 | 119 |
| 105 static void UpdateAuxiliaryObjectProperties(const LayoutObject& object, | 120 static void UpdateAuxiliaryObjectProperties(const LayoutObject& object, |
| 106 PrePaintTreeWalkContext& context) { | 121 PrePaintTreeWalkContext& context) { |
| 107 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 122 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 119 | 134 |
| 120 // Sticky position constraints and ancestor overflow scroller affect the | 135 // Sticky position constraints and ancestor overflow scroller affect the |
| 121 // sticky layer position, so we need to update it again here. | 136 // sticky layer position, so we need to update it again here. |
| 122 // TODO(flackr): This should be refactored in the future to be clearer (i.e. | 137 // TODO(flackr): This should be refactored in the future to be clearer (i.e. |
| 123 // update layer position and ancestor inputs updates in the same walk). | 138 // update layer position and ancestor inputs updates in the same walk). |
| 124 paint_layer->UpdateLayerPosition(); | 139 paint_layer->UpdateLayerPosition(); |
| 125 } | 140 } |
| 126 | 141 |
| 127 if (paint_layer->IsRootLayer() || object.HasOverflowClip()) | 142 if (paint_layer->IsRootLayer() || object.HasOverflowClip()) |
| 128 context.ancestor_overflow_paint_layer = paint_layer; | 143 context.ancestor_overflow_paint_layer = paint_layer; |
| 144 | |
| 145 context.enclosing_paint_layer = paint_layer; | |
| 129 } | 146 } |
| 130 | 147 |
| 131 void PrePaintTreeWalk::ComputeClipRectForContext( | 148 void PrePaintTreeWalk::ComputeClipRectForContext( |
| 132 const PaintPropertyTreeBuilderContext::ContainingBlockContext& context, | 149 const PaintPropertyTreeBuilderContext::ContainingBlockContext& context, |
| 133 const EffectPaintPropertyNode* effect, | 150 const EffectPaintPropertyNode* effect, |
| 134 const PropertyTreeState& ancestor_state, | 151 const PropertyTreeState& ancestor_state, |
| 135 const LayoutPoint& ancestor_paint_offset, | 152 const LayoutPoint& ancestor_paint_offset, |
| 136 FloatClipRect& clip_rect) { | 153 FloatClipRect& clip_rect) { |
| 137 PropertyTreeState local_state(context.transform, context.clip, effect); | 154 PropertyTreeState local_state(context.transform, context.clip, effect); |
| 138 | 155 |
| 139 clip_rect = | 156 clip_rect = |
| 140 GeometryMapper::SourceToDestinationClipRect(local_state, ancestor_state); | 157 GeometryMapper::SourceToDestinationClipRect(local_state, ancestor_state); |
| 141 clip_rect.MoveBy(-FloatPoint(ancestor_paint_offset)); | 158 clip_rect.MoveBy(-FloatPoint(ancestor_paint_offset)); |
| 142 } | 159 } |
| 143 | 160 |
| 144 void PrePaintTreeWalk::InvalidatePaintLayerOptimizationsIfNeeded( | 161 void PrePaintTreeWalk::InvalidatePaintLayerOptimizationsIfNeeded( |
| 145 const LayoutObject& object, | 162 const LayoutObject& object, |
| 146 PrePaintTreeWalkContext& context) { | 163 PrePaintTreeWalkContext& context) { |
| 147 if (!object.HasLayer()) | 164 if (!object.HasLayer()) |
| 148 return; | 165 return; |
| 149 | 166 |
| 150 PaintLayer& paint_layer = *ToLayoutBoxModelObject(object).Layer(); | 167 PaintLayer& paint_layer = *ToLayoutBoxModelObject(object).Layer(); |
| 168 if (!paint_layer.SupportsSubsequenceCaching()) | |
| 169 return; | |
| 170 | |
| 151 if (object.StyleRef().HasTransform() || | 171 if (object.StyleRef().HasTransform() || |
| 152 &object == | 172 &object == |
| 153 context.paint_invalidator_context.paint_invalidation_container) { | 173 context.paint_invalidator_context.paint_invalidation_container) { |
| 154 context.ancestor_transformed_or_root_paint_layer = &paint_layer; | 174 context.ancestor_transformed_or_root_paint_layer = &paint_layer; |
| 155 } | 175 } |
| 156 | 176 |
| 157 const auto& ancestor = | 177 const auto& ancestor = |
| 158 context.ancestor_transformed_or_root_paint_layer->GetLayoutObject(); | 178 context.ancestor_transformed_or_root_paint_layer->GetLayoutObject(); |
| 159 PropertyTreeState ancestor_state = *ancestor.LocalBorderBoxProperties(); | 179 PropertyTreeState ancestor_state = *ancestor.LocalBorderBoxProperties(); |
| 160 | 180 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 | 259 |
| 240 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( | 260 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( |
| 241 const LayoutObject& object, | 261 const LayoutObject& object, |
| 242 const PrePaintTreeWalkContext& parent_context) { | 262 const PrePaintTreeWalkContext& parent_context) { |
| 243 return object.NeedsPaintPropertyUpdate() || | 263 return object.NeedsPaintPropertyUpdate() || |
| 244 object.DescendantNeedsPaintPropertyUpdate() || | 264 object.DescendantNeedsPaintPropertyUpdate() || |
| 245 (parent_context.tree_builder_context && | 265 (parent_context.tree_builder_context && |
| 246 parent_context.tree_builder_context->force_subtree_update) || | 266 parent_context.tree_builder_context->force_subtree_update) || |
| 247 // If the object needs visual rect update, we should update tree | 267 // If the object needs visual rect update, we should update tree |
| 248 // builder context which is needed by visual rect update. | 268 // builder context which is needed by visual rect update. |
| 249 parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object); | 269 parent_context.paint_invalidator_context.NeedsVisualRectUpdate( |
| 270 object) || | |
| 271 (parent_context.enclosing_paint_layer && | |
|
pdr.
2017/04/12 18:40:06
Can enclosing_paint_layer ever be null here?
Do w
| |
| 272 parent_context.enclosing_paint_layer | |
| 273 ->HasDescendantThatSupportsSubsequenceCaching()); | |
| 274 } | |
| 275 | |
| 276 bool PrePaintTreeWalk::ShouldEarlyOut( | |
| 277 const LayoutObject& object, | |
| 278 const PrePaintTreeWalkContext& parent_context, | |
| 279 bool& needs_tree_builder_context_update) { | |
| 280 // Early out from the tree walk if possible. | |
| 281 needs_tree_builder_context_update = | |
| 282 this->NeedsTreeBuilderContextUpdate(object, parent_context); | |
| 283 return !needs_tree_builder_context_update && | |
| 284 !object.ShouldCheckForPaintInvalidation(); | |
| 250 } | 285 } |
| 251 | 286 |
| 252 void PrePaintTreeWalk::Walk(const LayoutObject& object, | 287 void PrePaintTreeWalk::Walk(const LayoutObject& object, |
| 253 const PrePaintTreeWalkContext& parent_context) { | 288 const PrePaintTreeWalkContext& parent_context) { |
| 254 // Early out from the tree walk if possible. | 289 bool needs_tree_builder_context_update = false; |
| 255 bool needs_tree_builder_context_update = | 290 if (ShouldEarlyOut(object, parent_context, needs_tree_builder_context_update)) |
| 256 this->NeedsTreeBuilderContextUpdate(object, parent_context); | |
| 257 if (!needs_tree_builder_context_update && | |
| 258 !object.ShouldCheckForPaintInvalidation()) | |
| 259 return; | 291 return; |
| 260 | 292 |
| 261 PrePaintTreeWalkContext context(parent_context, | 293 PrePaintTreeWalkContext context(parent_context, |
| 262 needs_tree_builder_context_update); | 294 needs_tree_builder_context_update); |
| 263 | 295 |
| 264 // This must happen before updatePropertiesForSelf, because the latter reads | 296 // This must happen before updatePropertiesForSelf, because the latter reads |
| 265 // some of the state computed here. | 297 // some of the state computed here. |
| 266 UpdateAuxiliaryObjectProperties(object, context); | 298 UpdateAuxiliaryObjectProperties(object, context); |
| 267 | 299 |
| 268 if (context.tree_builder_context) { | 300 if (context.tree_builder_context) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 302 } | 334 } |
| 303 Walk(*ToFrameView(frame_view_base), context); | 335 Walk(*ToFrameView(frame_view_base), context); |
| 304 } | 336 } |
| 305 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 337 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 306 } | 338 } |
| 307 | 339 |
| 308 object.GetMutableForPainting().ClearPaintFlags(); | 340 object.GetMutableForPainting().ClearPaintFlags(); |
| 309 } | 341 } |
| 310 | 342 |
| 311 } // namespace blink | 343 } // namespace blink |
| OLD | NEW |