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 |