diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-12 15:59:20 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-25 06:57:22 +0000 |
commit | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch) | |
tree | caed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc | |
parent | 9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff) | |
download | qtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz |
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc | 659 |
1 files changed, 147 insertions, 512 deletions
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc index b7b8adce7b9..31c15a4769c 100644 --- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc +++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc @@ -11,7 +11,6 @@ #include "third_party/blink/renderer/core/layout/layout_video.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/clip_path_clipper.h" -#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" #include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h" #include "third_party/blink/renderer/core/paint/object_paint_properties.h" #include "third_party/blink/renderer/core/paint/paint_info.h" @@ -20,8 +19,6 @@ #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/paint/paint_timing_detector.h" #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h" -#include "third_party/blink/renderer/platform/geometry/float_point_3d.h" -#include "third_party/blink/renderer/platform/graphics/graphics_layer.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h" #include "third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h" @@ -29,27 +26,10 @@ #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h" #include "third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "ui/gfx/geometry/point3_f.h" namespace blink { -void PaintLayerPainter::Paint(GraphicsContext& context, - const CullRect& cull_rect, - const GlobalPaintFlags global_paint_flags, - PaintLayerFlags paint_flags) { - PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, - global_paint_flags, PhysicalOffset()); - if (!paint_layer_.PaintsIntoOwnOrGroupedBacking(global_paint_flags)) - Paint(context, painting_info, paint_flags); -} - -static ShouldRespectOverflowClipType ShouldRespectOverflowClip( - PaintLayerFlags paint_flags, - const LayoutObject& layout_object) { - return (paint_flags & kPaintLayerPaintingOverflowContents) - ? kIgnoreOverflowClip - : kRespectOverflowClip; -} - bool PaintLayerPainter::PaintedOutputInvisible(const ComputedStyle& style) { if (style.HasNonInitialBackdropFilter()) return false; @@ -83,7 +63,7 @@ PhysicalRect PaintLayerPainter::ContentsVisualRect(const FragmentData& fragment, ? fragment.PaintProperties()->ReplacedContentTransform() : nullptr; if (replaced_transform) { - FloatRect float_contents_visual_rect(contents_visual_rect); + gfx::RectF float_contents_visual_rect(contents_visual_rect); GeometryMapper::SourceToDestinationRect(*replaced_transform->Parent(), *replaced_transform, float_contents_visual_rect); @@ -93,10 +73,8 @@ PhysicalRect PaintLayerPainter::ContentsVisualRect(const FragmentData& fragment, return contents_visual_rect; } -PaintResult PaintLayerPainter::Paint( - GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info, - PaintLayerFlags paint_flags) { +PaintResult PaintLayerPainter::Paint(GraphicsContext& context, + PaintFlags paint_flags) { const LayoutObject& layout_object = paint_layer_.GetLayoutObject(); if (UNLIKELY(layout_object.NeedsLayout() && !layout_object.ChildLayoutBlockedByDisplayLock())) { @@ -114,32 +92,26 @@ PaintResult PaintLayerPainter::Paint( !paint_layer_.HasSelfPaintingLayerDescendant()) return kFullyPainted; - // If the transform can't be inverted, don't paint anything. We still need - // to paint with CompositeAfterPaint if there are animations to ensure the - // animation can be setup to run on the compositor. + // If the transform can't be inverted, don't paint anything. We still need to + // paint if there are animations to ensure the animation can be setup to run + // on the compositor. bool paint_non_invertible_transforms = false; - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - const auto* properties = layout_object.FirstFragment().PaintProperties(); - if (properties && properties->Transform() && - properties->Transform()->HasActiveTransformAnimation()) { - paint_non_invertible_transforms = true; - } + const auto* properties = layout_object.FirstFragment().PaintProperties(); + if (properties && properties->Transform() && + properties->Transform()->HasActiveTransformAnimation()) { + paint_non_invertible_transforms = true; } - if (!paint_non_invertible_transforms && - paint_layer_.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) && - !paint_layer_.RenderableTransform(painting_info.GetGlobalPaintFlags()) - .IsInvertible()) { + if (!paint_non_invertible_transforms && paint_layer_.Transform() && + !paint_layer_.Transform()->IsInvertible()) { return kFullyPainted; } - paint_flags |= kPaintLayerPaintingCompositingAllPhases; - return PaintLayerContents(context, painting_info, paint_flags); + return PaintLayerContents(context, paint_flags); } -static bool ShouldCreateSubsequence( - const PaintLayer& paint_layer, - const GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info) { +static bool ShouldCreateSubsequence(const PaintLayer& paint_layer, + const GraphicsContext& context, + PaintFlags paint_flags) { // Caching is not needed during printing or painting previews. if (paint_layer.GetLayoutObject().GetDocument().IsPrintingOrPaintingPreview()) return false; @@ -152,50 +124,13 @@ static bool ShouldCreateSubsequence( // Don't create subsequence during special painting to avoid cache conflict // with normal painting. - if (painting_info.GetGlobalPaintFlags() & - kGlobalPaintFlattenCompositingLayers) - return false; - - // Don't create subsequence for a composited layer because if it can be - // cached, we can skip the whole painting in GraphicsLayer::paint() with - // CachedDisplayItemList. This also avoids conflict of - // PaintLayer::previousXXX() when paintLayer is composited scrolling and is - // painted twice for GraphicsLayers of container and scrolling contents. - if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && - (paint_layer.GetCompositingState() == kPaintsIntoOwnBacking)) + if (paint_flags & PaintFlag::kOmitCompositingInfo) return false; return true; } -static bool ShouldRepaintSubsequence( - PaintLayer& paint_layer, - const PaintLayerPaintingInfo& painting_info) { - // Repaint subsequence if the layer is marked for needing repaint. - if (paint_layer.SelfOrDescendantNeedsRepaint()) - return true; - - // Repaint if previously the layer may be clipped by cull rect, and cull rect - // changes. - if (!RuntimeEnabledFeatures::CullRectUpdateEnabled() && - paint_layer.PreviousCullRect() != painting_info.cull_rect) { - if (paint_layer.PreviousPaintResult() == kMayBeClippedByCullRect) - return true; - // When PaintUnderInvalidationChecking is enabled, always repaint the - // subsequence when the paint rect changes because we will strictly match - // new and cached subsequences. Normally we can reuse the cached fully - // painted subsequence even if we would partially paint this time. - if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) - return true; - } - - return false; -} - static bool IsUnclippedLayoutView(const PaintLayer& layer) { - // If MainFrameClipsContent is false which means that WebPreferences:: - // record_whole_document is true, we should not cull the scrolling contents - // of the main frame. if (IsA<LayoutView>(layer.GetLayoutObject())) { const auto* frame = layer.GetLayoutObject().GetFrame(); if (frame && !frame->ClipsContent()) @@ -205,13 +140,10 @@ static bool IsUnclippedLayoutView(const PaintLayer& layer) { } bool PaintLayerPainter::ShouldUseInfiniteCullRect() { - DCHECK(RuntimeEnabledFeatures::CullRectUpdateEnabled()); - return ShouldUseInfiniteCullRectInternal(kGlobalPaintNormalPhase, - /*for_cull_rect_update*/ true); + return ShouldUseInfiniteCullRectInternal(/*for_cull_rect_update*/ true); } bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal( - GlobalPaintFlags global_flags, bool for_cull_rect_update) { bool is_printing = paint_layer_.GetLayoutObject().GetDocument().Printing(); if (IsUnclippedLayoutView(paint_layer_) && !is_printing) @@ -220,8 +152,8 @@ bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal( // Cull rects and clips can't be propagated across a filter which moves // pixels, since the input of the filter may be outside the cull rect / // clips yet still result in painted output. - // TODO(wangxianzhu): With CullRectUpdate, we can let CullRect support - // mapping for pixel moving filters to avoid this infinite cull rect. + // TODO(wangxianzhu): We can let CullRect support mapping for pixel moving + // filters to avoid this infinite cull rect. if (paint_layer_.HasFilterThatMovesPixels() && // However during printing, we don't want filter outset to cross page // boundaries. This also avoids performance issue because the PDF renderer @@ -255,13 +187,9 @@ bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal( return true; } - // Ensure content under animating transforms is not culled out, even if - // the initial matrix is non-invertible. - if (transform->HasActiveTransformAnimation() && - !transform->IsIdentityOr2DTranslation() && - !transform->Matrix().IsInvertible()) { + // Ensure content under animating transforms is not culled out. + if (transform->HasActiveTransformAnimation()) return true; - } // As an optimization, skip cull rect updating for non-composited // transforms which have already been painted. This is because the cull @@ -281,8 +209,8 @@ bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal( // 2) Complexity: Difficulty updating clips when ancestor transforms // change. // For these reasons, we use an infinite dirty rect here. - // The reasons don't apply for CullRectUpdate. - if (!for_cull_rect_update && paint_layer_.PaintsWithTransform(global_flags) && + // The reasons don't apply for CullRectUpdater. + if (!for_cull_rect_update && paint_layer_.Transform() && // The reasons don't apply for printing though, because when we enter and // leaving printing mode, full invalidations occur. !is_printing) @@ -291,72 +219,6 @@ bool PaintLayerPainter::ShouldUseInfiniteCullRectInternal( return false; } -void PaintLayerPainter::AdjustForPaintProperties( - const GraphicsContext& context, - PaintLayerPaintingInfo& painting_info, - PaintLayerFlags& paint_flags) { - const auto& first_fragment = paint_layer_.GetLayoutObject().FirstFragment(); - - bool should_use_infinite_cull_rect = - ShouldUseInfiniteCullRectInternal(painting_info.GetGlobalPaintFlags(), - /*for_cull_rect_update*/ false); - if (should_use_infinite_cull_rect) { - painting_info.cull_rect = CullRect::Infinite(); - // Avoid clipping during CollectFragments. - if (IsUnclippedLayoutView(paint_layer_)) - paint_flags |= kPaintLayerPaintingOverflowContents; - } - - if (painting_info.root_layer == &paint_layer_) - return; - - if (!should_use_infinite_cull_rect) { - // painting_info.cull_rect is currently in |painting_info.root_layer|'s - // pixel-snapped border box space. We need to adjust it into - // |paint_layer_|'s space. This handles the following cases: - // - The current layer has PaintOffsetTranslation; - // - The current layer's transform state escapes the root layers contents - // transform, e.g. a fixed-position layer; - // - Scroll offsets. - const auto& first_root_fragment = - painting_info.root_layer->GetLayoutObject().FirstFragment(); - const auto* source_transform = - &first_root_fragment.LocalBorderBoxProperties().Transform(); - const auto& destination_transform = - first_fragment.LocalBorderBoxProperties().Transform(); - if (source_transform == &destination_transform) - return; - - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - DCHECK(RuntimeEnabledFeatures::CullRectUpdateEnabled()); - } else if (!painting_info.cull_rect.IsInfinite()) { - auto rect = painting_info.cull_rect.Rect(); - const FragmentData& primary_stitching_fragment = - paint_layer_.GetLayoutObject().PrimaryStitchingFragment(); - const FragmentData& primary_root_stitching_fragment = - painting_info.root_layer->GetLayoutObject() - .PrimaryStitchingFragment(); - primary_root_stitching_fragment.MapRectToFragment( - primary_stitching_fragment, rect); - painting_info.cull_rect = CullRect(rect); - } - } - - // We reach here if the layer requires infinite cull rect or has different - // transform space from the current root layer. Use the current layer as - // the new root layer. - painting_info.root_layer = &paint_layer_; - // These flags no longer apply for the new root layer. - paint_flags &= ~kPaintLayerPaintingSkipRootBackground; - paint_flags &= ~kPaintLayerPaintingOverflowContents; - paint_flags &= ~kPaintLayerPaintingCompositingScrollingPhase; - - if (first_fragment.PaintProperties() && - first_fragment.PaintProperties()->PaintOffsetTranslation()) { - painting_info.sub_pixel_accumulation = first_fragment.PaintOffset(); - } -} - static gfx::Rect FirstFragmentVisualRect(const LayoutBoxModelObject& object) { // We don't want to include overflowing contents. PhysicalRect overflow_rect = @@ -366,10 +228,8 @@ static gfx::Rect FirstFragmentVisualRect(const LayoutBoxModelObject& object) { return ToEnclosingRect(overflow_rect); } -PaintResult PaintLayerPainter::PaintLayerContents( - GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info_arg, - PaintLayerFlags paint_flags_arg) { +PaintResult PaintLayerPainter::PaintLayerContents(GraphicsContext& context, + PaintFlags paint_flags) { DCHECK(paint_layer_.IsSelfPaintingLayer() || paint_layer_.HasSelfPaintingLayerDescendant()); @@ -384,13 +244,11 @@ PaintResult PaintLayerPainter::PaintLayerContents( // TODO(crbug.com/848056): This can happen e.g. when we paint a filter // referencing a SVG foreign object through feImage, especially when there // is circular references. Should find a better solution. - if (!RuntimeEnabledFeatures::CullRectUpdateEnabled()) - paint_layer_.SetPreviousCullRect(CullRect()); return kMayBeClippedByCullRect; } - bool selection_drag_image_only = painting_info_arg.GetGlobalPaintFlags() & - kGlobalPaintSelectionDragImageOnly; + bool selection_drag_image_only = + paint_flags & PaintFlag::kSelectionDragImageOnly; if (selection_drag_image_only && !object.IsSelected()) return result; @@ -410,142 +268,57 @@ PaintResult PaintLayerPainter::PaintLayerContents( IgnorePaintTimingScope::SetIsDocumentElementInvisible( is_document_element_invisible); - PaintLayerFlags paint_flags = paint_flags_arg; - PaintLayerPaintingInfo painting_info = painting_info_arg; - AdjustForPaintProperties(context, painting_info, paint_flags); - bool is_self_painting_layer = paint_layer_.IsSelfPaintingLayer(); - bool is_painting_overlay_overflow_controls = - paint_flags & kPaintLayerPaintingOverlayOverflowControls; - bool is_painting_scrolling_content = - paint_flags & kPaintLayerPaintingCompositingScrollingPhase; - bool is_painting_composited_foreground = - paint_flags & kPaintLayerPaintingCompositingForegroundPhase; - bool is_painting_composited_background = - paint_flags & kPaintLayerPaintingCompositingBackgroundPhase; - bool is_painting_composited_decoration = - paint_flags & kPaintLayerPaintingCompositingDecorationPhase; - bool is_painting_overflow_contents = - paint_flags & kPaintLayerPaintingOverflowContents; - bool is_painting_mask = paint_flags & kPaintLayerPaintingCompositingMaskPhase; - - // Outline always needs to be painted even if we have no visible content. - // It is painted as part of the decoration phase which paints content that - // is not scrolled and should be above scrolled content. - bool should_paint_self_outline = - is_self_painting_layer && !is_painting_overlay_overflow_controls && - is_painting_composited_decoration && object.StyleRef().HasOutline(); - - PhysicalOffset subpixel_accumulation = - (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && - !(painting_info.GetGlobalPaintFlags() & - kGlobalPaintFlattenCompositingLayers) && - paint_layer_.GetCompositingState() == kPaintsIntoOwnBacking) - ? paint_layer_.SubpixelAccumulation() - : painting_info.sub_pixel_accumulation; - - ShouldRespectOverflowClipType respect_overflow_clip = - ShouldRespectOverflowClip(paint_flags, object); + bool is_unclipped_layout_view = IsUnclippedLayoutView(paint_layer_); bool should_paint_content = paint_layer_.HasVisibleContent() && // Content under a LayoutSVGHiddenContainer is auxiliary resources for // painting. Foreign content should never paint in this situation, as it // is primary, not auxiliary. - !paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer && - !is_painting_overlay_overflow_controls; - - // TODO(paint-dev): Become block fragmentation aware. Unconditionally using - // the first fragment doesn't seem right. - PhysicalOffset offset_from_root = object.FirstFragment().PaintOffset(); - if (const PaintLayer* root = painting_info.root_layer) - offset_from_root -= root->GetLayoutObject().FirstFragment().PaintOffset(); - offset_from_root += subpixel_accumulation; - - if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) { - if (object.FirstFragment().NextFragment() || - IsUnclippedLayoutView(paint_layer_)) { - result = kMayBeClippedByCullRect; - } else { - gfx::Rect visual_rect = FirstFragmentVisualRect(object); - gfx::Rect cull_rect = object.FirstFragment().GetCullRect().Rect(); - bool cull_rect_intersects_self = cull_rect.Intersects(visual_rect); - if (!cull_rect.Contains(visual_rect)) - result = kMayBeClippedByCullRect; - - bool cull_rect_intersects_contents = true; - if (const auto* box = DynamicTo<LayoutBox>(object)) { - PhysicalRect contents_visual_rect( - ContentsVisualRect(object.FirstFragment(), *box)); - PhysicalRect contents_cull_rect( - object.FirstFragment().GetContentsCullRect().Rect()); - cull_rect_intersects_contents = - contents_cull_rect.Intersects(contents_visual_rect); - if (!contents_cull_rect.Contains(contents_visual_rect)) - result = kMayBeClippedByCullRect; - } else { - cull_rect_intersects_contents = cull_rect_intersects_self; - } - - if (!cull_rect_intersects_self && !cull_rect_intersects_contents) { - if (!is_painting_overflow_contents && - paint_layer_.KnownToClipSubtree()) { - paint_layer_.SetPreviousPaintResult(kMayBeClippedByCullRect); - return kMayBeClippedByCullRect; - } - should_paint_content = false; - } + !paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer; - // The above doesn't consider clips on non-self-painting contents. - // Will update in ScopedBoxContentsPaintState. - } + if (object.FirstFragment().NextFragment() || is_unclipped_layout_view) { + result = kMayBeClippedByCullRect; } else { - PhysicalRect bounds = paint_layer_.PhysicalBoundingBox(offset_from_root); - if (!PhysicalRect(painting_info.cull_rect.Rect()).Contains(bounds)) + gfx::Rect visual_rect = FirstFragmentVisualRect(object); + gfx::Rect cull_rect = object.FirstFragment().GetCullRect().Rect(); + bool cull_rect_intersects_self = cull_rect.Intersects(visual_rect); + if (!cull_rect.Contains(visual_rect)) result = kMayBeClippedByCullRect; - } - PaintLayerPaintingInfo local_painting_info(painting_info); - local_painting_info.sub_pixel_accumulation = subpixel_accumulation; - - PaintLayerFragments layer_fragments; - ClearCollectionScope<PaintLayerFragments> scope(&layer_fragments); - - if (should_paint_content || should_paint_self_outline || - is_painting_overlay_overflow_controls) { - // Collect the fragments. If CullRectUpdate is enabled, this will just - // create a light-weight adapter from FragmentData to PaintLayerFragment - // and we'll remove the adapter in the future. Otherwise this will compute - // the clip rectangles and paint offsets for each layer fragment. - paint_layer_.CollectFragments( - layer_fragments, local_painting_info.root_layer, - &local_painting_info.cull_rect, kIgnoreOverlayScrollbarSize, - respect_overflow_clip, &offset_from_root, - local_painting_info.sub_pixel_accumulation); - - if (!RuntimeEnabledFeatures::CullRectUpdateEnabled()) { - // PaintLayer::CollectFragments depends on the paint dirty rect in - // complicated ways. For now, always assume a partially painted output - // for fragmented content. - if (layer_fragments.size() > 1) + bool cull_rect_intersects_contents = true; + if (const auto* box = DynamicTo<LayoutBox>(object)) { + PhysicalRect contents_visual_rect( + ContentsVisualRect(object.FirstFragment(), *box)); + PhysicalRect contents_cull_rect( + object.FirstFragment().GetContentsCullRect().Rect()); + cull_rect_intersects_contents = + contents_cull_rect.Intersects(contents_visual_rect); + if (!contents_cull_rect.Contains(contents_visual_rect)) result = kMayBeClippedByCullRect; + } else { + cull_rect_intersects_contents = cull_rect_intersects_self; + } - if (should_paint_content) { - should_paint_content = AtLeastOneFragmentIntersectsDamageRect( - layer_fragments, local_painting_info, paint_flags, - offset_from_root); - if (!should_paint_content) - result = kMayBeClippedByCullRect; + if (!cull_rect_intersects_self && !cull_rect_intersects_contents) { + if (!is_unclipped_layout_view && paint_layer_.KnownToClipSubtree()) { + paint_layer_.SetPreviousPaintResult(kMayBeClippedByCullRect); + return kMayBeClippedByCullRect; } + should_paint_content = false; } + + // The above doesn't consider clips on non-self-painting contents. + // Will update in ScopedBoxContentsPaintState. } bool should_create_subsequence = should_paint_content && - ShouldCreateSubsequence(paint_layer_, context, painting_info); + ShouldCreateSubsequence(paint_layer_, context, paint_flags); absl::optional<SubsequenceRecorder> subsequence_recorder; if (should_create_subsequence) { - if (!ShouldRepaintSubsequence(paint_layer_, painting_info) && + if (!paint_layer_.SelfOrDescendantNeedsRepaint() && SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, paint_layer_)) { return paint_layer_.PreviousPaintResult(); @@ -554,26 +327,8 @@ PaintResult PaintLayerPainter::PaintLayerContents( subsequence_recorder.emplace(context, paint_layer_); } - bool is_painting_root_layer = (&paint_layer_) == painting_info.root_layer; - bool should_paint_background = - should_paint_content && !selection_drag_image_only && - (is_painting_composited_background || - (is_painting_root_layer && - !(paint_flags & kPaintLayerPaintingSkipRootBackground))); - bool should_paint_neg_z_order_list = - !is_painting_overlay_overflow_controls && - (is_painting_scrolling_content ? is_painting_overflow_contents - : is_painting_composited_background); - bool should_paint_own_contents = - is_painting_composited_foreground && should_paint_content; - bool should_paint_normal_flow_and_pos_z_order_lists = - is_painting_composited_foreground && - !is_painting_overlay_overflow_controls; - bool is_video = IsA<LayoutVideo>(object); - absl::optional<ScopedEffectivelyInvisible> effectively_invisible; - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && - PaintedOutputInvisible(object.StyleRef())) + if (PaintedOutputInvisible(object.StyleRef())) effectively_invisible.emplace(context.GetPaintController()); absl::optional<ScopedPaintChunkProperties> layer_chunk_properties; @@ -586,19 +341,17 @@ PaintResult PaintLayerPainter::PaintLayerContents( DisplayItem::kLayerChunk); } + bool should_paint_background = + should_paint_content && !selection_drag_image_only; if (should_paint_background) { - PaintBackgroundForFragmentsWithPhase(PaintPhase::kSelfBlockBackgroundOnly, - layer_fragments, context, - local_painting_info, paint_flags); + PaintWithPhase(PaintPhase::kSelfBlockBackgroundOnly, context, paint_flags); } - if (should_paint_neg_z_order_list) { - if (PaintChildren(kNegativeZOrderChildren, context, painting_info, - paint_flags) == kMayBeClippedByCullRect) - result = kMayBeClippedByCullRect; - } + if (PaintChildren(kNegativeZOrderChildren, context, paint_flags) == + kMayBeClippedByCullRect) + result = kMayBeClippedByCullRect; - if (should_paint_own_contents) { + if (should_paint_content) { // If the negative-z-order children created paint chunks, this gives the // foreground paint chunk a stable id. ScopedPaintChunkProperties foreground_properties( @@ -607,109 +360,59 @@ PaintResult PaintLayerPainter::PaintLayerContents( DisplayItem::kLayerChunkForeground); if (selection_drag_image_only) { - PaintForegroundForFragmentsWithPhase(PaintPhase::kSelectionDragImage, - layer_fragments, context, - local_painting_info, paint_flags); + PaintWithPhase(PaintPhase::kSelectionDragImage, context, paint_flags); } else { - PaintForegroundForFragments(layer_fragments, context, local_painting_info, - paint_flags); + PaintForegroundPhases(context, paint_flags); } } - if (!is_video && should_paint_self_outline) { - PaintBackgroundForFragmentsWithPhase(PaintPhase::kSelfOutlineOnly, - layer_fragments, context, - local_painting_info, paint_flags); - } + // Outline always needs to be painted even if we have no visible content. + bool should_paint_self_outline = + is_self_painting_layer && object.StyleRef().HasOutline(); - if (should_paint_normal_flow_and_pos_z_order_lists) { - if (PaintChildren(kNormalFlowAndPositiveZOrderChildren, context, - painting_info, paint_flags) == kMayBeClippedByCullRect) - result = kMayBeClippedByCullRect; - } + bool is_video = IsA<LayoutVideo>(object); + if (!is_video && should_paint_self_outline) + PaintWithPhase(PaintPhase::kSelfOutlineOnly, context, paint_flags); - if (paint_layer_.GetScrollableArea() && + if (PaintChildren(kNormalFlowAndPositiveZOrderChildren, context, + paint_flags) == kMayBeClippedByCullRect) + result = kMayBeClippedByCullRect; + + if (should_paint_content && paint_layer_.GetScrollableArea() && paint_layer_.GetScrollableArea() ->ShouldOverflowControlsPaintAsOverlay()) { - if (is_painting_overlay_overflow_controls || - !paint_layer_.NeedsReorderOverlayOverflowControls()) { - PaintOverlayOverflowControlsForFragments( - layer_fragments, context, local_painting_info, paint_flags); - } + if (!paint_layer_.NeedsReorderOverlayOverflowControls()) + PaintOverlayOverflowControls(context, paint_flags); + // Otherwise the overlay overflow controls will be painted after scrolling + // children in PaintChildren(). } + // Overlay overflow controls of scrollers without a self-painting layer are + // painted in the foreground paint phase. See ScrollableAreaPainter. if (is_video && should_paint_self_outline) { // We paint outlines for video later so that they aren't obscured by the // video controls. - PaintBackgroundForFragmentsWithPhase(PaintPhase::kSelfOutlineOnly, - layer_fragments, context, - local_painting_info, paint_flags); + PaintWithPhase(PaintPhase::kSelfOutlineOnly, context, paint_flags); } - if (is_painting_mask && should_paint_content && !selection_drag_image_only) { + if (should_paint_content && !selection_drag_image_only) { if (const auto* properties = object.FirstFragment().PaintProperties()) { if (properties->Mask()) { - PaintBackgroundForFragmentsWithPhase(PaintPhase::kMask, layer_fragments, - context, local_painting_info, - paint_flags); - } - if (properties->ClipPathMask()) { - PhysicalOffset visual_offset_from_root = - paint_layer_.EnclosingPaginationLayer() - ? paint_layer_.VisualOffsetFromAncestor( - local_painting_info.root_layer, subpixel_accumulation) - : offset_from_root; - ClipPathClipper::PaintClipPathAsMaskImage(context, object, object, - visual_offset_from_root); + PaintWithPhase(PaintPhase::kMask, context, paint_flags); } + if (properties->ClipPathMask()) + ClipPathClipper::PaintClipPathAsMaskImage(context, object, object); } } paint_layer_.SetPreviousPaintResult(result); - if (!RuntimeEnabledFeatures::CullRectUpdateEnabled()) - paint_layer_.SetPreviousCullRect(local_painting_info.cull_rect); return result; } -bool PaintLayerPainter::AtLeastOneFragmentIntersectsDamageRect( - PaintLayerFragments& fragments, - const PaintLayerPaintingInfo& local_painting_info, - PaintLayerFlags local_paint_flags, - const PhysicalOffset& offset_from_root) { - DCHECK(!RuntimeEnabledFeatures::CullRectUpdateEnabled()); - - if (&paint_layer_ == local_painting_info.root_layer && - (local_paint_flags & kPaintLayerPaintingOverflowContents)) - return true; - - // Skip the optimization if the layer is fragmented to avoid complexity - // about overflows in fragments. LayoutObject painters will do cull rect - // optimization later. - if (paint_layer_.EnclosingPaginationLayer() || fragments.size() > 1) - return true; - - return paint_layer_.IntersectsDamageRect(fragments[0].layer_bounds, - fragments[0].background_rect.Rect(), - offset_from_root); -} - -template <typename Function> -static void ForAllFragments(GraphicsContext& context, - const PaintLayerFragments& fragments, - const Function& function) { - for (wtf_size_t i = 0; i < fragments.size(); ++i) { - absl::optional<ScopedDisplayItemFragment> scoped_display_item_fragment; - if (i) - scoped_display_item_fragment.emplace(context, i); - function(fragments[i]); - } -} - PaintResult PaintLayerPainter::PaintChildren( PaintLayerIteration children_to_visit, GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info, - PaintLayerFlags paint_flags) { + PaintFlags paint_flags) { PaintResult result = kFullyPainted; if (!paint_layer_.HasSelfPaintingLayerDescendant()) return result; @@ -719,17 +422,10 @@ PaintResult PaintLayerPainter::PaintChildren( PaintLayerPaintOrderIterator iterator(&paint_layer_, children_to_visit); while (PaintLayer* child = iterator.Next()) { - // If this Layer should paint into its own backing or a grouped backing, - // that will be done via CompositedLayerMapping::PaintContents() and - // CompositedLayerMapping::DoPaintTask(). - if (child->PaintsIntoOwnOrGroupedBacking( - painting_info.GetGlobalPaintFlags())) - continue; - if (child->IsReplacedNormalFlowStacking()) continue; - if (PaintLayerPainter(*child).Paint(context, painting_info, paint_flags) == + if (PaintLayerPainter(*child).Paint(context, paint_flags) == kMayBeClippedByCullRect) result = kMayBeClippedByCullRect; @@ -739,11 +435,12 @@ PaintResult PaintLayerPainter::PaintChildren( *layers_painting_overlay_overflow_controls_after) { DCHECK(reparent_overflow_controls_layer ->NeedsReorderOverlayOverflowControls()); - if (PaintLayerPainter(*reparent_overflow_controls_layer) - .Paint(context, painting_info, - kPaintLayerPaintingOverlayOverflowControls) == - kMayBeClippedByCullRect) + PaintLayerPainter(*reparent_overflow_controls_layer) + .PaintOverlayOverflowControls(context, paint_flags); + if (reparent_overflow_controls_layer->PreviousPaintResult() == + kMayBeClippedByCullRect) { result = kMayBeClippedByCullRect; + } } } } @@ -751,38 +448,30 @@ PaintResult PaintLayerPainter::PaintChildren( return result; } -void PaintLayerPainter::PaintOverlayOverflowControlsForFragments( - const PaintLayerFragments& layer_fragments, - GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info, - PaintLayerFlags paint_flags) { +void PaintLayerPainter::PaintOverlayOverflowControls(GraphicsContext& context, + PaintFlags paint_flags) { + DCHECK(paint_layer_.GetScrollableArea()); DCHECK( - paint_layer_.GetScrollableArea() && paint_layer_.GetScrollableArea()->ShouldOverflowControlsPaintAsOverlay()); - - // We don't need to paint composited overflow controls. - if (paint_layer_.GetScrollableArea()->HasLayerForHorizontalScrollbar() || - paint_layer_.GetScrollableArea()->HasLayerForVerticalScrollbar() || - paint_layer_.GetScrollableArea()->HasLayerForScrollCorner()) - return; - - PaintBackgroundForFragmentsWithPhase(PaintPhase::kOverlayOverflowControls, - layer_fragments, context, painting_info, - paint_flags); + PaintWithPhase(PaintPhase::kOverlayOverflowControls, context, paint_flags); } void PaintLayerPainter::PaintFragmentWithPhase( PaintPhase phase, - const PaintLayerFragment& fragment, + const FragmentData& fragment_data, + const NGPhysicalBoxFragment* physical_fragment, GraphicsContext& context, - const CullRect& cull_rect, - const PaintLayerPaintingInfo& painting_info, - PaintLayerFlags paint_flags) { - DCHECK(paint_layer_.IsSelfPaintingLayer()); + PaintFlags paint_flags) { + DCHECK(paint_layer_.IsSelfPaintingLayer() || + phase == PaintPhase::kOverlayOverflowControls); - auto chunk_properties = fragment.fragment_data->LocalBorderBoxProperties(); + CullRect cull_rect = fragment_data.GetCullRect(); + if (cull_rect.Rect().IsEmpty()) + return; + + auto chunk_properties = fragment_data.LocalBorderBoxProperties(); if (phase == PaintPhase::kMask) { - const auto* properties = fragment.fragment_data->PaintProperties(); + const auto* properties = fragment_data.PaintProperties(); DCHECK(properties); DCHECK(properties->Mask()); chunk_properties.SetEffect(*properties->Mask()); @@ -791,117 +480,63 @@ void PaintLayerPainter::PaintFragmentWithPhase( context.GetPaintController(), chunk_properties, paint_layer_, DisplayItem::PaintPhaseToDrawingType(phase)); - PaintInfo paint_info(context, cull_rect, phase, - painting_info.GetGlobalPaintFlags(), paint_flags, - &painting_info.root_layer->GetLayoutObject()); + PaintInfo paint_info(context, cull_rect, phase, paint_flags); if (paint_layer_.GetLayoutObject().ChildPaintBlockedByDisplayLock()) paint_info.SetDescendantPaintingBlocked(true); - if (fragment.physical_fragment) { - NGBoxFragmentPainter(*fragment.physical_fragment).Paint(paint_info); + if (physical_fragment) { + NGBoxFragmentPainter(*physical_fragment).Paint(paint_info); } else { - if (fragment.fragment_data) - paint_info.SetFragmentID(fragment.fragment_data->FragmentID()); + paint_info.SetFragmentID(fragment_data.FragmentID()); paint_layer_.GetLayoutObject().Paint(paint_info); } } -static CullRect LegacyCullRect(const PaintLayerFragment& fragment, - const ClipRect& clip_rect) { - DCHECK(!RuntimeEnabledFeatures::CullRectUpdateEnabled()); - PhysicalRect new_cull_rect(clip_rect.Rect()); - // Now |new_cull_rect| is in the pixel-snapped border box space of - // |fragment.root_fragment_data|. Adjust it to the containing transform node's - // space in which we will paint. - new_cull_rect.Move(PhysicalOffset( - ToRoundedPoint(fragment.root_fragment_data->PaintOffset()))); - return CullRect(ToPixelSnappedRect(new_cull_rect)); -} +void PaintLayerPainter::PaintWithPhase(PaintPhase phase, + GraphicsContext& context, + PaintFlags paint_flags) { + const auto* layout_box_with_fragments = + paint_layer_.GetLayoutBoxWithBlockFragments(); + wtf_size_t fragment_idx = 0u; + for (const auto* fragment = &paint_layer_.GetLayoutObject().FirstFragment(); + fragment; fragment = fragment->NextFragment(), ++fragment_idx) { + const NGPhysicalBoxFragment* physical_fragment = nullptr; + if (layout_box_with_fragments) { + physical_fragment = + layout_box_with_fragments->GetPhysicalFragment(fragment_idx); + DCHECK(physical_fragment); + } -void PaintLayerPainter::PaintBackgroundForFragmentsWithPhase( - PaintPhase phase, - const PaintLayerFragments& layer_fragments, - GraphicsContext& context, - const PaintLayerPaintingInfo& local_painting_info, - PaintLayerFlags paint_flags) { - ForAllFragments( - context, layer_fragments, [&](const PaintLayerFragment& fragment) { - CullRect cull_rect = - RuntimeEnabledFeatures::CullRectUpdateEnabled() - ? fragment.fragment_data->GetCullRect() - : LegacyCullRect(fragment, fragment.background_rect); - if (!cull_rect.Rect().IsEmpty()) { - PaintFragmentWithPhase(phase, fragment, context, cull_rect, - local_painting_info, paint_flags); - } - }); + absl::optional<ScopedDisplayItemFragment> scoped_display_item_fragment; + if (fragment_idx) + scoped_display_item_fragment.emplace(context, fragment_idx); + + PaintFragmentWithPhase(phase, *fragment, physical_fragment, context, + paint_flags); + } } -void PaintLayerPainter::PaintForegroundForFragments( - const PaintLayerFragments& layer_fragments, - GraphicsContext& context, - const PaintLayerPaintingInfo& local_painting_info, - PaintLayerFlags paint_flags) { - PaintForegroundForFragmentsWithPhase( - PaintPhase::kDescendantBlockBackgroundsOnly, layer_fragments, context, - local_painting_info, paint_flags); +void PaintLayerPainter::PaintForegroundPhases(GraphicsContext& context, + PaintFlags paint_flags) { + PaintWithPhase(PaintPhase::kDescendantBlockBackgroundsOnly, context, + paint_flags); if (paint_layer_.GetLayoutObject().GetDocument().InForcedColorsMode()) { - PaintForegroundForFragmentsWithPhase(PaintPhase::kForcedColorsModeBackplate, - layer_fragments, context, - local_painting_info, paint_flags); + PaintWithPhase(PaintPhase::kForcedColorsModeBackplate, context, + paint_flags); } if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() || paint_layer_.NeedsPaintPhaseFloat()) { - PaintForegroundForFragmentsWithPhase(PaintPhase::kFloat, layer_fragments, - context, local_painting_info, - paint_flags); + PaintWithPhase(PaintPhase::kFloat, context, paint_flags); } - PaintForegroundForFragmentsWithPhase(PaintPhase::kForeground, layer_fragments, - context, local_painting_info, - paint_flags); + PaintWithPhase(PaintPhase::kForeground, context, paint_flags); if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() || paint_layer_.NeedsPaintPhaseDescendantOutlines()) { - PaintForegroundForFragmentsWithPhase(PaintPhase::kDescendantOutlinesOnly, - layer_fragments, context, - local_painting_info, paint_flags); + PaintWithPhase(PaintPhase::kDescendantOutlinesOnly, context, paint_flags); } } -void PaintLayerPainter::PaintForegroundForFragmentsWithPhase( - PaintPhase phase, - const PaintLayerFragments& layer_fragments, - GraphicsContext& context, - const PaintLayerPaintingInfo& local_painting_info, - PaintLayerFlags paint_flags) { - ForAllFragments( - context, layer_fragments, [&](const PaintLayerFragment& fragment) { - CullRect cull_rect; - if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) { - // In CullRectUpdate, this function is the same as - // PaintBackgroundForFragmentsWithPhase(). The contents cull rect will - // be applied by ScopedBoxContentsPaintState. - cull_rect = fragment.fragment_data->GetCullRect(); - } else { - cull_rect = LegacyCullRect(fragment, fragment.foreground_rect); - } - if (!cull_rect.Rect().IsEmpty()) { - PaintFragmentWithPhase(phase, fragment, context, cull_rect, - local_painting_info, paint_flags); - } - }); -} - -void PaintLayerPainter::PaintOverlayOverflowControls( - GraphicsContext& context, - const CullRect& cull_rect, - const GlobalPaintFlags paint_flags) { - PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, paint_flags, - PhysicalOffset()); - Paint(context, painting_info, kPaintLayerPaintingOverlayOverflowControls); -} - } // namespace blink |