| 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 |