OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/PaintInvalidator.h" | 5 #include "core/paint/PaintInvalidator.h" |
6 | 6 |
7 #include "core/editing/FrameSelection.h" | 7 #include "core/editing/FrameSelection.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/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 // TODO(wkorman): The flip below is required because visual rects are | 62 // TODO(wkorman): The flip below is required because visual rects are |
63 // currently in "physical coordinates with flipped block-flow direction" | 63 // currently in "physical coordinates with flipped block-flow direction" |
64 // (see LayoutBoxModelObject.h) but we need them to be in physical | 64 // (see LayoutBoxModelObject.h) but we need them to be in physical |
65 // coordinates. | 65 // coordinates. |
66 Rect rect = local_rect; | 66 Rect rect = local_rect; |
67 // Writing-mode flipping doesn't apply to non-root SVG. | 67 // Writing-mode flipping doesn't apply to non-root SVG. |
68 if (!is_svg_child) { | 68 if (!is_svg_child) { |
69 if (object.IsBox()) { | 69 if (object.IsBox()) { |
70 ToLayoutBox(object).FlipForWritingMode(rect); | 70 ToLayoutBox(object).FlipForWritingMode(rect); |
71 } else if (!(context.forced_subtree_invalidation_flags & | 71 } else if (!(context.subtree_flags & |
72 PaintInvalidatorContext::kForcedSubtreeSlowPathRect)) { | 72 PaintInvalidatorContext::kSubtreeSlowPathRect)) { |
73 // For SPv2 and the GeometryMapper path, we also need to convert the rect | 73 // For SPv2 and the GeometryMapper path, we also need to convert the rect |
74 // for non-boxes into physical coordinates before applying paint offset. | 74 // for non-boxes into physical coordinates before applying paint offset. |
75 // (Otherwise we'll call mapToVisualrectInAncestorSpace() which requires | 75 // (Otherwise we'll call mapToVisualrectInAncestorSpace() which requires |
76 // physical coordinates for boxes, but "physical coordinates with flipped | 76 // physical coordinates for boxes, but "physical coordinates with flipped |
77 // block-flow direction" for non-boxes for which we don't need to flip.) | 77 // block-flow direction" for non-boxes for which we don't need to flip.) |
78 // TODO(wangxianzhu): Avoid containingBlock(). | 78 // TODO(wangxianzhu): Avoid containingBlock(). |
79 object.ContainingBlock()->FlipForWritingMode(rect); | 79 object.ContainingBlock()->FlipForWritingMode(rect); |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 83 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
84 // In SPv2, visual rects are in the space of their local transform node. | 84 // In SPv2, visual rects are in the space of their local transform node. |
85 // For SVG, the input rect is in local SVG coordinates in which paint | 85 // For SVG, the input rect is in local SVG coordinates in which paint |
86 // offset doesn't apply. | 86 // offset doesn't apply. |
87 if (!is_svg_child) | 87 if (!is_svg_child) |
88 rect.MoveBy(Point(object.PaintOffset())); | 88 rect.MoveBy(Point(object.PaintOffset())); |
89 // Use enclosingIntRect to ensure the final visual rect will cover the | 89 // Use enclosingIntRect to ensure the final visual rect will cover the |
90 // rect in source coordinates no matter if the painting will use pixel | 90 // rect in source coordinates no matter if the painting will use pixel |
91 // snapping. | 91 // snapping. |
92 return LayoutRect(EnclosingIntRect(rect)); | 92 return LayoutRect(EnclosingIntRect(rect)); |
93 } | 93 } |
94 | 94 |
95 // If kForcedSubtreeNoRasterInvalidation is set, we map the rect to the | |
96 // temporary root paint property state instead of the paint invalidation | |
97 // backing. | |
98 bool map_to_backing = | |
99 !(context.forced_subtree_invalidation_flags & | |
100 PaintInvalidatorContext::kForcedSubtreeNoRasterInvalidation); | |
101 | |
102 LayoutRect result; | 95 LayoutRect result; |
103 if (context.forced_subtree_invalidation_flags & | 96 if (context.subtree_flags & PaintInvalidatorContext::kSubtreeSlowPathRect) { |
104 PaintInvalidatorContext::kForcedSubtreeSlowPathRect) { | |
105 result = SlowMapToVisualRectInAncestorSpace( | 97 result = SlowMapToVisualRectInAncestorSpace( |
106 object, *context.paint_invalidation_container, rect); | 98 object, *context.paint_invalidation_container, rect); |
107 } else if (object == context.paint_invalidation_container) { | 99 } else if (object == context.paint_invalidation_container) { |
108 DCHECK(map_to_backing); | |
109 result = LayoutRect(rect); | 100 result = LayoutRect(rect); |
110 } else { | 101 } else { |
111 // For non-root SVG, the input rect is in local SVG coordinates in which | 102 // For non-root SVG, the input rect is in local SVG coordinates in which |
112 // paint offset doesn't apply. | 103 // paint offset doesn't apply. |
113 if (!is_svg_child) | 104 if (!is_svg_child) |
114 rect.MoveBy(Point(object.PaintOffset())); | 105 rect.MoveBy(Point(object.PaintOffset())); |
115 | 106 |
116 auto container_contents_properties = | 107 auto container_contents_properties = |
117 map_to_backing | 108 context.paint_invalidation_container->ContentsProperties(); |
118 ? context.paint_invalidation_container->ContentsProperties() | |
119 : PropertyTreeState::Root(); | |
120 if (context.tree_builder_context_->current.transform == | 109 if (context.tree_builder_context_->current.transform == |
121 container_contents_properties.Transform() && | 110 container_contents_properties.Transform() && |
122 context.tree_builder_context_->current.clip == | 111 context.tree_builder_context_->current.clip == |
123 container_contents_properties.Clip()) { | 112 container_contents_properties.Clip()) { |
124 result = LayoutRect(rect); | 113 result = LayoutRect(rect); |
125 } else { | 114 } else { |
126 // Use enclosingIntRect to ensure the final visual rect will cover the | 115 // Use enclosingIntRect to ensure the final visual rect will cover the |
127 // rect in source coordinates no matter if the painting will use pixel | 116 // rect in source coordinates no matter if the painting will use pixel |
128 // snapping, when transforms are applied. If there is no transform, | 117 // snapping, when transforms are applied. If there is no transform, |
129 // enclosingIntRect is applied in the last step of paint invalidation | 118 // enclosingIntRect is applied in the last step of paint invalidation |
130 // (see CompositedLayerMapping::setContentsNeedDisplayInRect()). | 119 // (see CompositedLayerMapping::setContentsNeedDisplayInRect()). |
131 if (!is_svg_child && context.tree_builder_context_->current.transform != | 120 if (!is_svg_child && context.tree_builder_context_->current.transform != |
132 container_contents_properties.Transform()) | 121 container_contents_properties.Transform()) |
133 rect = Rect(EnclosingIntRect(rect)); | 122 rect = Rect(EnclosingIntRect(rect)); |
134 | 123 |
135 PropertyTreeState current_tree_state( | 124 PropertyTreeState current_tree_state( |
136 context.tree_builder_context_->current.transform, | 125 context.tree_builder_context_->current.transform, |
137 context.tree_builder_context_->current.clip, nullptr); | 126 context.tree_builder_context_->current.clip, nullptr); |
138 | 127 |
139 FloatClipRect float_rect((FloatRect(rect))); | 128 FloatClipRect float_rect((FloatRect(rect))); |
140 GeometryMapper::SourceToDestinationVisualRect( | 129 GeometryMapper::SourceToDestinationVisualRect( |
141 current_tree_state, container_contents_properties, float_rect); | 130 current_tree_state, container_contents_properties, float_rect); |
142 result = LayoutRect(float_rect.Rect()); | 131 result = LayoutRect(float_rect.Rect()); |
143 } | 132 } |
144 | 133 |
145 // Convert the result to the container's contents space. | 134 // Convert the result to the container's contents space. |
146 if (map_to_backing) | 135 result.MoveBy(-context.paint_invalidation_container->PaintOffset()); |
147 result.MoveBy(-context.paint_invalidation_container->PaintOffset()); | |
148 } | 136 } |
149 | 137 |
150 object.AdjustVisualRectForRasterEffects(result); | 138 object.AdjustVisualRectForRasterEffects(result); |
151 if (!map_to_backing) | |
152 return result; | |
153 | 139 |
154 PaintLayer::MapRectInPaintInvalidationContainerToBacking( | 140 PaintLayer::MapRectInPaintInvalidationContainerToBacking( |
155 *context.paint_invalidation_container, result); | 141 *context.paint_invalidation_container, result); |
156 | 142 |
157 result.Move(object.ScrollAdjustmentForPaintInvalidation( | 143 result.Move(object.ScrollAdjustmentForPaintInvalidation( |
158 *context.paint_invalidation_container)); | 144 *context.paint_invalidation_container)); |
159 | 145 |
160 return result; | 146 return result; |
161 } | 147 } |
162 | 148 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 // This is to exclude some objects (e.g. LayoutText) inheriting | 320 // This is to exclude some objects (e.g. LayoutText) inheriting |
335 // stacked style from parent but aren't actually stacked. | 321 // stacked style from parent but aren't actually stacked. |
336 object.HasLayer() && | 322 object.HasLayer() && |
337 context.paint_invalidation_container != | 323 context.paint_invalidation_container != |
338 context.paint_invalidation_container_for_stacked_contents) { | 324 context.paint_invalidation_container_for_stacked_contents) { |
339 // The current object is stacked, so we should use | 325 // The current object is stacked, so we should use |
340 // m_paintInvalidationContainerForStackedContents as its paint invalidation | 326 // m_paintInvalidationContainerForStackedContents as its paint invalidation |
341 // container on which the current object is painted. | 327 // container on which the current object is painted. |
342 context.paint_invalidation_container = | 328 context.paint_invalidation_container = |
343 context.paint_invalidation_container_for_stacked_contents; | 329 context.paint_invalidation_container_for_stacked_contents; |
344 if (context.forced_subtree_invalidation_flags & | 330 if (context.subtree_flags & |
345 PaintInvalidatorContext:: | 331 PaintInvalidatorContext::kSubtreeFullInvalidationForStackedContents) { |
346 kForcedSubtreeFullInvalidationForStackedContents) | 332 context.subtree_flags |= |
347 context.forced_subtree_invalidation_flags |= | 333 PaintInvalidatorContext::kSubtreeFullInvalidation; |
348 PaintInvalidatorContext::kForcedSubtreeFullInvalidation; | 334 } |
349 } | 335 } |
350 | 336 |
351 if (object == context.paint_invalidation_container) { | 337 if (object == context.paint_invalidation_container) { |
352 // When we hit a new paint invalidation container, we don't need to | 338 // When we hit a new paint invalidation container, we don't need to |
353 // continue forcing a check for paint invalidation, since we're | 339 // continue forcing a check for paint invalidation, since we're |
354 // descending into a different invalidation container. (For instance if | 340 // descending into a different invalidation container. (For instance if |
355 // our parents were moved, the entire container will just move.) | 341 // our parents were moved, the entire container will just move.) |
356 if (object != context.paint_invalidation_container_for_stacked_contents) { | 342 if (object != context.paint_invalidation_container_for_stacked_contents) { |
357 // However, we need to keep kForcedSubtreeVisualRectUpdate and | 343 // However, we need to keep kSubtreeVisualRectUpdate and |
358 // kForcedSubtreeFullInvalidationForStackedContents flags if the current | 344 // kSubtreeFullInvalidationForStackedContents flags if the current |
359 // object isn't the paint invalidation container of stacked contents. | 345 // object isn't the paint invalidation container of stacked contents. |
360 context.forced_subtree_invalidation_flags &= | 346 context.subtree_flags &= |
361 (PaintInvalidatorContext::kForcedSubtreeVisualRectUpdate | | 347 (PaintInvalidatorContext::kSubtreeVisualRectUpdate | |
362 PaintInvalidatorContext:: | 348 PaintInvalidatorContext::kSubtreeFullInvalidationForStackedContents); |
363 kForcedSubtreeFullInvalidationForStackedContents); | |
364 } else { | 349 } else { |
365 context.forced_subtree_invalidation_flags = 0; | 350 context.subtree_flags = 0; |
366 } | 351 } |
367 } | 352 } |
368 | 353 |
369 DCHECK(context.paint_invalidation_container == | 354 DCHECK(context.paint_invalidation_container == |
370 object.ContainerForPaintInvalidation()); | 355 object.ContainerForPaintInvalidation()); |
371 DCHECK(context.painting_layer == object.PaintingLayer()); | 356 DCHECK(context.painting_layer == object.PaintingLayer()); |
372 } | 357 } |
373 | 358 |
374 void PaintInvalidator::UpdateVisualRectIfNeeded( | 359 void PaintInvalidator::UpdateVisualRectIfNeeded( |
375 const LayoutObject& object, | 360 const LayoutObject& object, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 } | 447 } |
463 | 448 |
464 void PaintInvalidator::InvalidatePaint( | 449 void PaintInvalidator::InvalidatePaint( |
465 const LayoutObject& object, | 450 const LayoutObject& object, |
466 const PaintPropertyTreeBuilderContext* tree_builder_context, | 451 const PaintPropertyTreeBuilderContext* tree_builder_context, |
467 PaintInvalidatorContext& context) { | 452 PaintInvalidatorContext& context) { |
468 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), | 453 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), |
469 "PaintInvalidator::invalidatePaintIfNeeded()", "object", | 454 "PaintInvalidator::invalidatePaintIfNeeded()", "object", |
470 object.DebugName().Ascii()); | 455 object.DebugName().Ascii()); |
471 | 456 |
| 457 if (object.IsSVGHiddenContainer()) { |
| 458 context.subtree_flags |= PaintInvalidatorContext::kSubtreeNoInvalidation; |
| 459 } |
| 460 if (context.subtree_flags & PaintInvalidatorContext::kSubtreeNoInvalidation) |
| 461 return; |
| 462 |
472 object.GetMutableForPainting().EnsureIsReadyForPaintInvalidation(); | 463 object.GetMutableForPainting().EnsureIsReadyForPaintInvalidation(); |
473 | 464 |
474 UpdatePaintingLayer(object, context); | 465 UpdatePaintingLayer(object, context); |
475 | 466 |
476 if (object.GetDocument().Printing() && | 467 if (object.GetDocument().Printing() && |
477 !RuntimeEnabledFeatures::printBrowserEnabled()) | 468 !RuntimeEnabledFeatures::printBrowserEnabled()) |
478 return; // Don't invalidate paints if we're printing. | 469 return; // Don't invalidate paints if we're printing. |
479 | 470 |
480 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter | 471 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter |
481 // geometry effects, after skia optimizes filter's mapRect operation. | 472 // geometry effects, after skia optimizes filter's mapRect operation. |
482 // TODO(crbug.com/648274): This is a workaround for multi-column contents. | 473 // TODO(crbug.com/648274): This is a workaround for multi-column contents. |
483 if (object.HasFilterInducingProperty() || object.IsLayoutFlowThread()) { | 474 if (object.HasFilterInducingProperty() || object.IsLayoutFlowThread()) { |
484 context.forced_subtree_invalidation_flags |= | 475 context.subtree_flags |= PaintInvalidatorContext::kSubtreeSlowPathRect; |
485 PaintInvalidatorContext::kForcedSubtreeSlowPathRect; | |
486 } | 476 } |
487 | 477 |
488 UpdatePaintInvalidationContainer(object, context); | 478 UpdatePaintInvalidationContainer(object, context); |
489 UpdateVisualRectIfNeeded(object, tree_builder_context, context); | 479 UpdateVisualRectIfNeeded(object, tree_builder_context, context); |
490 | 480 |
491 if (!object.ShouldCheckForPaintInvalidation() && | 481 if (!object.ShouldCheckForPaintInvalidation() && |
492 !(context.forced_subtree_invalidation_flags & | 482 !(context.subtree_flags & |
493 ~PaintInvalidatorContext::kForcedSubtreeVisualRectUpdate)) { | 483 ~PaintInvalidatorContext::kSubtreeVisualRectUpdate)) { |
494 // We are done updating anything needed. No other paint invalidation work to | 484 // We are done updating anything needed. No other paint invalidation work to |
495 // do for this object. | 485 // do for this object. |
496 return; | 486 return; |
497 } | 487 } |
498 | 488 |
499 if (object.IsSVGHiddenContainer()) { | |
500 context.forced_subtree_invalidation_flags |= | |
501 PaintInvalidatorContext::kForcedSubtreeNoRasterInvalidation; | |
502 } | |
503 | |
504 PaintInvalidationReason reason = object.InvalidatePaint(context); | 489 PaintInvalidationReason reason = object.InvalidatePaint(context); |
505 switch (reason) { | 490 switch (reason) { |
506 case PaintInvalidationReason::kDelayedFull: | 491 case PaintInvalidationReason::kDelayedFull: |
507 pending_delayed_paint_invalidations_.push_back(&object); | 492 pending_delayed_paint_invalidations_.push_back(&object); |
508 break; | 493 break; |
509 case PaintInvalidationReason::kSubtree: | 494 case PaintInvalidationReason::kSubtree: |
510 context.forced_subtree_invalidation_flags |= | 495 context.subtree_flags |= |
511 (PaintInvalidatorContext::kForcedSubtreeFullInvalidation | | 496 (PaintInvalidatorContext::kSubtreeFullInvalidation | |
512 PaintInvalidatorContext:: | 497 PaintInvalidatorContext::kSubtreeFullInvalidationForStackedContents); |
513 kForcedSubtreeFullInvalidationForStackedContents); | |
514 break; | 498 break; |
515 case PaintInvalidationReason::kSVGResource: | 499 case PaintInvalidationReason::kSVGResource: |
516 context.forced_subtree_invalidation_flags |= | 500 context.subtree_flags |= |
517 PaintInvalidatorContext::kForcedSubtreeSVGResourceChange; | 501 PaintInvalidatorContext::kSubtreeSVGResourceChange; |
518 break; | 502 break; |
519 default: | 503 default: |
520 break; | 504 break; |
521 } | 505 } |
522 | 506 |
523 if (object.MayNeedPaintInvalidationSubtree()) { | 507 if (object.MayNeedPaintInvalidationSubtree()) { |
524 context.forced_subtree_invalidation_flags |= | 508 context.subtree_flags |= |
525 PaintInvalidatorContext::kForcedSubtreeInvalidationChecking; | 509 PaintInvalidatorContext::kSubtreeInvalidationChecking; |
526 } | 510 } |
527 | 511 |
528 if (context.old_location != context.new_location && | 512 if (context.old_location != context.new_location && |
529 !context.painting_layer->SubtreeIsInvisible()) { | 513 !context.painting_layer->SubtreeIsInvisible()) { |
530 context.forced_subtree_invalidation_flags |= | 514 context.subtree_flags |= |
531 PaintInvalidatorContext::kForcedSubtreeInvalidationChecking; | 515 PaintInvalidatorContext::kSubtreeInvalidationChecking; |
532 } | 516 } |
533 | 517 |
534 if (context.forced_subtree_invalidation_flags && | 518 if (context.subtree_flags && context.NeedsVisualRectUpdate(object)) { |
535 context.NeedsVisualRectUpdate(object)) { | |
536 // If any subtree flag is set, we also need to pass needsVisualRectUpdate | 519 // If any subtree flag is set, we also need to pass needsVisualRectUpdate |
537 // requirement to the subtree. | 520 // requirement to the subtree. |
538 context.forced_subtree_invalidation_flags |= | 521 context.subtree_flags |= PaintInvalidatorContext::kSubtreeVisualRectUpdate; |
539 PaintInvalidatorContext::kForcedSubtreeVisualRectUpdate; | |
540 } | 522 } |
541 } | 523 } |
542 | 524 |
543 void PaintInvalidator::ProcessPendingDelayedPaintInvalidations() { | 525 void PaintInvalidator::ProcessPendingDelayedPaintInvalidations() { |
544 for (auto target : pending_delayed_paint_invalidations_) { | 526 for (auto target : pending_delayed_paint_invalidations_) { |
545 target->GetMutableForPainting() | 527 target->GetMutableForPainting() |
546 .SetShouldDoFullPaintInvalidationWithoutGeometryChange( | 528 .SetShouldDoFullPaintInvalidationWithoutGeometryChange( |
547 PaintInvalidationReason::kDelayedFull); | 529 PaintInvalidationReason::kDelayedFull); |
548 } | 530 } |
549 } | 531 } |
550 | 532 |
551 } // namespace blink | 533 } // namespace blink |
OLD | NEW |