| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 // when recursion is deep so this context object is allocated on the heap. | 47 // when recursion is deep so this context object is allocated on the heap. |
| 48 // See: https://crbug.com/698653. | 48 // See: https://crbug.com/698653. |
| 49 std::unique_ptr<PaintPropertyTreeBuilderContext> tree_builder_context; | 49 std::unique_ptr<PaintPropertyTreeBuilderContext> tree_builder_context; |
| 50 | 50 |
| 51 PaintInvalidatorContext paint_invalidator_context; | 51 PaintInvalidatorContext paint_invalidator_context; |
| 52 | 52 |
| 53 // The ancestor in the PaintLayer tree which has overflow clip, or | 53 // The ancestor in the PaintLayer tree which has overflow clip, or |
| 54 // is the root layer. Note that it is tree ancestor, not containing | 54 // is the root layer. Note that it is tree ancestor, not containing |
| 55 // block or stacking ancestor. | 55 // block or stacking ancestor. |
| 56 PaintLayer* ancestor_overflow_paint_layer; | 56 PaintLayer* ancestor_overflow_paint_layer; |
| 57 |
| 58 // The ancestor in the PaintLayer tree which has a transform or is a root |
| 59 // layer for painting (i.e. a paint invalidation container). |
| 57 PaintLayer* ancestor_transformed_or_root_paint_layer; | 60 PaintLayer* ancestor_transformed_or_root_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(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 | 119 |
| 117 if (object.StyleRef().GetPosition() == EPosition::kSticky) { | 120 if (object.StyleRef().GetPosition() == EPosition::kSticky) { |
| 118 paint_layer->GetLayoutObject().UpdateStickyPositionConstraints(); | 121 paint_layer->GetLayoutObject().UpdateStickyPositionConstraints(); |
| 119 | 122 |
| 120 // Sticky position constraints and ancestor overflow scroller affect the | 123 // Sticky position constraints and ancestor overflow scroller affect the |
| 121 // sticky layer position, so we need to update it again here. | 124 // 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. | 125 // 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). | 126 // update layer position and ancestor inputs updates in the same walk). |
| 124 paint_layer->UpdateLayerPosition(); | 127 paint_layer->UpdateLayerPosition(); |
| 125 } | 128 } |
| 126 | |
| 127 if (paint_layer->IsRootLayer() || object.HasOverflowClip()) | 129 if (paint_layer->IsRootLayer() || object.HasOverflowClip()) |
| 128 context.ancestor_overflow_paint_layer = paint_layer; | 130 context.ancestor_overflow_paint_layer = paint_layer; |
| 129 } | 131 } |
| 130 | 132 |
| 131 LayoutRect PrePaintTreeWalk::ComputeClipRectForContext( | 133 LayoutRect PrePaintTreeWalk::ComputeClipRectForContext( |
| 132 const PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext& | 134 const PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext& |
| 133 context, | 135 context, |
| 134 const EffectPaintPropertyNode* effect, | 136 const EffectPaintPropertyNode* effect, |
| 135 const PropertyTreeState& ancestor_state, | 137 const PropertyTreeState& ancestor_state, |
| 136 const LayoutPoint& ancestor_paint_offset) { | 138 const LayoutPoint& ancestor_paint_offset) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 159 } | 161 } |
| 160 | 162 |
| 161 // This code below checks whether any clips have changed that might: | 163 // This code below checks whether any clips have changed that might: |
| 162 // (a) invalidate optimizations made for a PaintLayer that supports | 164 // (a) invalidate optimizations made for a PaintLayer that supports |
| 163 // subsequence caching, or | 165 // subsequence caching, or |
| 164 // (b) impact clipping of descendant visual rects. | 166 // (b) impact clipping of descendant visual rects. |
| 165 if (!paint_layer.SupportsSubsequenceCaching() && | 167 if (!paint_layer.SupportsSubsequenceCaching() && |
| 166 !paint_layer.GetLayoutObject().HasClipRelatedProperty()) | 168 !paint_layer.GetLayoutObject().HasClipRelatedProperty()) |
| 167 return; | 169 return; |
| 168 | 170 |
| 171 FragmentData* fragment_data = |
| 172 &object.GetMutableForPainting().EnsureFirstFragment(); |
| 173 for (auto& fragment : context.tree_builder_context->fragments) { |
| 174 DCHECK(fragment_data); |
| 175 if (InvalidatePaintLayerOptimizationsForFragment( |
| 176 object, context.ancestor_transformed_or_root_paint_layer, fragment, |
| 177 *fragment_data)) { |
| 178 context.paint_invalidator_context.forced_subtree_invalidation_flags |= |
| 179 PaintInvalidatorContext::kForcedSubtreeVisualRectUpdate; |
| 180 } |
| 181 fragment_data = fragment_data->NextFragment(); |
| 182 } |
| 183 } |
| 184 |
| 185 bool PrePaintTreeWalk::InvalidatePaintLayerOptimizationsForFragment( |
| 186 const LayoutObject& object, |
| 187 const PaintLayer* ancestor_transformed_or_root_paint_layer, |
| 188 const PaintPropertyTreeBuilderFragmentContext& context, |
| 189 FragmentData& fragment_data) { |
| 190 PaintLayer& paint_layer = *ToLayoutBoxModelObject(object).Layer(); |
| 191 |
| 169 const auto& ancestor = | 192 const auto& ancestor = |
| 170 context.ancestor_transformed_or_root_paint_layer->GetLayoutObject(); | 193 ancestor_transformed_or_root_paint_layer->GetLayoutObject(); |
| 171 PropertyTreeState ancestor_state = *ancestor.LocalBorderBoxProperties(); | 194 PropertyTreeState ancestor_state = *ancestor.LocalBorderBoxProperties(); |
| 172 | 195 |
| 173 #ifdef CHECK_CLIP_RECTS | 196 #ifdef CHECK_CLIP_RECTS |
| 174 auto respect_overflow_clip = kRespectOverflowClip; | 197 auto respect_overflow_clip = kRespectOverflowClip; |
| 175 #endif | 198 #endif |
| 176 if (context.ancestor_transformed_or_root_paint_layer->GetCompositingState() == | 199 if (ancestor_transformed_or_root_paint_layer->GetCompositingState() == |
| 177 kPaintsIntoOwnBacking) { | 200 kPaintsIntoOwnBacking) { |
| 178 const auto* ancestor_properties = ancestor.PaintProperties(); | 201 const auto* ancestor_properties = ancestor.PaintProperties(); |
| 179 if (ancestor_properties && ancestor_properties->OverflowClip()) { | 202 if (ancestor_properties && ancestor_properties->OverflowClip()) { |
| 180 ancestor_state.SetClip(ancestor_properties->OverflowClip()); | 203 ancestor_state.SetClip(ancestor_properties->OverflowClip()); |
| 181 #ifdef CHECK_CLIP_RECTS | 204 #ifdef CHECK_CLIP_RECTS |
| 182 respect_overflow_clip = kIgnoreOverflowClip; | 205 respect_overflow_clip = kIgnoreOverflowClip; |
| 183 #endif | 206 #endif |
| 184 } | 207 } |
| 185 } | 208 } |
| 186 | 209 |
| 187 #ifdef CHECK_CLIP_RECTS | 210 #ifdef CHECK_CLIP_RECTS |
| 188 const auto& old_clip_rects = | 211 const auto& old_clip_rects = |
| 189 paint_layer.Clipper(PaintLayer::kDoNotUseGeometryMapper) | 212 paint_layer.Clipper(PaintLayer::kDoNotUseGeometryMapper) |
| 190 .PaintingClipRects(context.ancestor_transformed_or_root_paint_layer, | 213 .PaintingClipRects(ancestor_transformed_or_root_paint_layer, |
| 191 respect_overflow_clip, LayoutSize()); | 214 respect_overflow_clip, LayoutSize()); |
| 192 #endif | 215 #endif |
| 193 | 216 |
| 194 const LayoutPoint& ancestor_paint_offset = | 217 const LayoutPoint& ancestor_paint_offset = |
| 195 context.ancestor_transformed_or_root_paint_layer->GetLayoutObject() | 218 ancestor_transformed_or_root_paint_layer->GetLayoutObject().PaintOffset(); |
| 196 .PaintOffset(); | |
| 197 | 219 |
| 198 // TODO(chrishtr): generalize this for multicol. | 220 // TODO(chrishtr): generalize this for multicol. |
| 199 const auto* effect = | 221 const auto* effect = context.current_effect; |
| 200 context.tree_builder_context->fragments[0].current_effect; | |
| 201 auto overflow_clip_rect = ComputeClipRectForContext( | 222 auto overflow_clip_rect = ComputeClipRectForContext( |
| 202 context.tree_builder_context->fragments[0].current, effect, | 223 context.current, effect, ancestor_state, ancestor_paint_offset); |
| 203 ancestor_state, ancestor_paint_offset); | |
| 204 #ifdef CHECK_CLIP_RECTS | 224 #ifdef CHECK_CLIP_RECTS |
| 205 CHECK(overflow_clip_rect == old_clip_rects.OverflowClipRect().Rect()) | 225 CHECK(overflow_clip_rect == old_clip_rects.OverflowClipRect().Rect()) |
| 206 << " new=" << overflow_clip_rect.ToString() | 226 << " new=" << overflow_clip_rect.ToString() |
| 207 << " old=" << old_clip_rects.OverflowClipRect().Rect().ToString(); | 227 << " old=" << old_clip_rects.OverflowClipRect().Rect().ToString(); |
| 208 #endif | 228 #endif |
| 209 | 229 |
| 210 auto fixed_clip_rect = ComputeClipRectForContext( | 230 auto fixed_clip_rect = ComputeClipRectForContext( |
| 211 context.tree_builder_context->fragments[0].fixed_position, effect, | 231 context.fixed_position, effect, ancestor_state, ancestor_paint_offset); |
| 212 ancestor_state, ancestor_paint_offset); | |
| 213 #ifdef CHECK_CLIP_RECTS | 232 #ifdef CHECK_CLIP_RECTS |
| 214 CHECK(fixed_clip_rect == old_clip_rects.FixedClipRect().Rect()) | 233 CHECK(fixed_clip_rect == old_clip_rects.FixedClipRect().Rect()) |
| 215 << " new=" << fixed_clip_rect.ToString() | 234 << " new=" << fixed_clip_rect.ToString() |
| 216 << " old=" << old_clip_rects.FixedClipRect().Rect().ToString(); | 235 << " old=" << old_clip_rects.FixedClipRect().Rect().ToString(); |
| 217 #endif | 236 #endif |
| 218 | 237 |
| 219 auto pos_clip_rect = ComputeClipRectForContext( | 238 auto pos_clip_rect = ComputeClipRectForContext( |
| 220 context.tree_builder_context->fragments[0].absolute_position, effect, | 239 context.absolute_position, effect, ancestor_state, ancestor_paint_offset); |
| 221 ancestor_state, ancestor_paint_offset); | |
| 222 #ifdef CHECK_CLIP_RECTS | 240 #ifdef CHECK_CLIP_RECTS |
| 223 CHECK(pos_clip_rect == old_clip_rects.PosClipRect().Rect()) | 241 CHECK(pos_clip_rect == old_clip_rects.PosClipRect().Rect()) |
| 224 << " new=" << pos_clip_rect.ToString() | 242 << " new=" << pos_clip_rect.ToString() |
| 225 << " old=" << old_clip_rects.PosClipRect().Rect().ToString(); | 243 << " old=" << old_clip_rects.PosClipRect().Rect().ToString(); |
| 226 #endif | 244 #endif |
| 227 | 245 |
| 228 const auto* previous_clip_rects = paint_layer.PreviousPaintingClipRects(); | 246 const auto* previous_clip_rects = fragment_data.PreviousClipRects(); |
| 229 if (!previous_clip_rects || | 247 if (!previous_clip_rects || |
| 230 overflow_clip_rect != previous_clip_rects->OverflowClipRect().Rect() || | 248 overflow_clip_rect != previous_clip_rects->OverflowClipRect().Rect() || |
| 231 fixed_clip_rect != previous_clip_rects->FixedClipRect().Rect() || | 249 fixed_clip_rect != previous_clip_rects->FixedClipRect().Rect() || |
| 232 pos_clip_rect != previous_clip_rects->PosClipRect().Rect()) { | 250 pos_clip_rect != previous_clip_rects->PosClipRect().Rect()) { |
| 233 RefPtr<ClipRects> clip_rects = ClipRects::Create(); | 251 RefPtr<ClipRects> clip_rects = ClipRects::Create(); |
| 234 clip_rects->SetOverflowClipRect(overflow_clip_rect); | 252 clip_rects->SetOverflowClipRect(overflow_clip_rect); |
| 235 clip_rects->SetFixedClipRect(fixed_clip_rect); | 253 clip_rects->SetFixedClipRect(fixed_clip_rect); |
| 236 clip_rects->SetPosClipRect(pos_clip_rect); | 254 clip_rects->SetPosClipRect(pos_clip_rect); |
| 237 paint_layer.SetPreviousPaintingClipRects(*clip_rects); | 255 fragment_data.SetPreviousClipRects(*clip_rects); |
| 238 | 256 |
| 239 paint_layer.SetNeedsRepaint(); | 257 paint_layer.SetNeedsRepaint(); |
| 240 paint_layer.SetPreviousPaintPhaseDescendantOutlinesEmpty(false); | 258 paint_layer.SetPreviousPaintPhaseDescendantOutlinesEmpty(false); |
| 241 paint_layer.SetPreviousPaintPhaseFloatEmpty(false); | 259 paint_layer.SetPreviousPaintPhaseFloatEmpty(false); |
| 242 paint_layer.SetPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); | 260 paint_layer.SetPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false); |
| 243 // All subsequences which are contained below this paintLayer must also | 261 // All subsequences which are contained below this paintLayer must also |
| 244 // be checked. | 262 // be checked. |
| 245 context.paint_invalidator_context.forced_subtree_invalidation_flags |= | 263 return true; |
| 246 PaintInvalidatorContext::kForcedSubtreeVisualRectUpdate; | |
| 247 } | 264 } |
| 265 return false; |
| 248 } | 266 } |
| 249 | 267 |
| 250 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( | 268 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( |
| 251 const FrameView& frame_view, | 269 const FrameView& frame_view, |
| 252 const PrePaintTreeWalkContext& context) { | 270 const PrePaintTreeWalkContext& context) { |
| 253 return frame_view.NeedsPaintPropertyUpdate() || | 271 return frame_view.NeedsPaintPropertyUpdate() || |
| 254 (frame_view.GetLayoutView() && | 272 (frame_view.GetLayoutView() && |
| 255 NeedsTreeBuilderContextUpdate(*frame_view.GetLayoutView(), context)); | 273 NeedsTreeBuilderContextUpdate(*frame_view.GetLayoutView(), context)); |
| 256 } | 274 } |
| 257 | 275 |
| 258 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( | 276 bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate( |
| 259 const LayoutObject& object, | 277 const LayoutObject& object, |
| 260 const PrePaintTreeWalkContext& parent_context) { | 278 const PrePaintTreeWalkContext& parent_context) { |
| 261 return object.NeedsPaintPropertyUpdate() || | 279 return object.NeedsPaintPropertyUpdate() || |
| 262 object.DescendantNeedsPaintPropertyUpdate() || | 280 object.DescendantNeedsPaintPropertyUpdate() || |
| 263 (parent_context.tree_builder_context && | 281 (parent_context.tree_builder_context && |
| 264 parent_context.tree_builder_context->force_subtree_update) || | 282 parent_context.tree_builder_context->force_subtree_update) || |
| 265 // If the object needs visual rect update, we should update tree | 283 // If the object needs visual rect update, we should update tree |
| 266 // builder context which is needed by visual rect update. | 284 // builder context which is needed by visual rect update. |
| 267 parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object); | 285 parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object); |
| 268 } | 286 } |
| 269 | 287 |
| 288 void PrePaintTreeWalk::ClearPreviousClipRectsForTesting( |
| 289 const LayoutObject& object) { |
| 290 object.GetMutableForPainting().FirstFragment()->ClearPreviousClipRects(); |
| 291 } |
| 292 |
| 270 void PrePaintTreeWalk::Walk(const LayoutObject& object, | 293 void PrePaintTreeWalk::Walk(const LayoutObject& object, |
| 271 const PrePaintTreeWalkContext& parent_context) { | 294 const PrePaintTreeWalkContext& parent_context) { |
| 272 // Early out from the tree walk if possible. | 295 // Early out from the tree walk if possible. |
| 273 bool needs_tree_builder_context_update = | 296 bool needs_tree_builder_context_update = |
| 274 this->NeedsTreeBuilderContextUpdate(object, parent_context); | 297 this->NeedsTreeBuilderContextUpdate(object, parent_context); |
| 275 if (!needs_tree_builder_context_update && | 298 if (!needs_tree_builder_context_update && |
| 276 !object.ShouldCheckForPaintInvalidation()) | 299 !object.ShouldCheckForPaintInvalidation()) |
| 277 return; | 300 return; |
| 278 | 301 |
| 279 PrePaintTreeWalkContext context(parent_context, | 302 PrePaintTreeWalkContext context(parent_context, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 } | 343 } |
| 321 Walk(*frame_view, context); | 344 Walk(*frame_view, context); |
| 322 } | 345 } |
| 323 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 346 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
| 324 } | 347 } |
| 325 | 348 |
| 326 object.GetMutableForPainting().ClearPaintFlags(); | 349 object.GetMutableForPainting().ClearPaintFlags(); |
| 327 } | 350 } |
| 328 | 351 |
| 329 } // namespace blink | 352 } // namespace blink |
| OLD | NEW |