diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-29 10:46:47 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-11-02 12:02:10 +0000 |
commit | 99677208ff3b216fdfec551fbe548da5520cd6fb (patch) | |
tree | 476a4865c10320249360e859d8fdd3e01833b03a /chromium/cc/layers/picture_layer_impl.cc | |
parent | c30a6232df03e1efbd9f3b226777b07e087a1122 (diff) |
BASELINE: Update Chromium to 86.0.4240.124
Change-Id: Ide0ff151e94cd665ae6521a446995d34a9d1d644
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc/layers/picture_layer_impl.cc')
-rw-r--r-- | chromium/cc/layers/picture_layer_impl.cc | 301 |
1 files changed, 180 insertions, 121 deletions
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index 0f030bd4ff3..06fa222c84a 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -10,7 +10,9 @@ #include <algorithm> #include <cmath> #include <limits> +#include <memory> #include <set> +#include <utility> #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" @@ -96,7 +98,6 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) was_screen_space_transform_animating_(false), only_used_low_res_last_append_quads_(false), nearest_neighbor_(false), - use_transformed_rasterization_(false), lcd_text_disallowed_reason_(LCDTextDisallowedReason::kNone), directly_composited_image_size_(base::nullopt), directly_composited_image_initial_raster_scale_(0.f), @@ -139,7 +140,6 @@ std::unique_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); - LayerImpl::PushPropertiesTo(base_layer); // Twin relationships should never change once established. @@ -153,7 +153,6 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { layer_impl->twin_layer_ = this; layer_impl->SetNearestNeighbor(nearest_neighbor_); - layer_impl->SetUseTransformedRasterization(use_transformed_rasterization_); layer_impl->SetDirectlyCompositedImageSize(directly_composited_image_size_); layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask_); @@ -273,7 +272,7 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass, // Validate that the tile and bounds size are always within one pixel. PictureLayerTiling* high_res = tilings_->FindTilingWithResolution(HIGH_RESOLUTION); - if (high_res) { + if (raster_contents_scale_ >= 1.f && high_res) { const float epsilon = 1.f; gfx::SizeF scaled_tiling_size(high_res->tiling_size()); scaled_tiling_size.Scale(1 / raster_contents_scale_); @@ -600,14 +599,11 @@ bool PictureLayerImpl::UpdateTiles() { const float old_ideal_contents_scale = ideal_contents_scale_; UpdateIdealScales(); - const bool ideal_contents_scale_changed = - old_ideal_contents_scale != 0 && - old_ideal_contents_scale != ideal_contents_scale_; - if (!raster_contents_scale_ || - ShouldAdjustRasterScale(ideal_contents_scale_changed)) { + const bool should_adjust_raster_scale = + ShouldAdjustRasterScale(old_ideal_contents_scale); + if (should_adjust_raster_scale) RecalculateRasterScales(); - AddTilingsForRasterScale(); - } + UpdateTilingsForRasterScaleAndTranslation(should_adjust_raster_scale); if (layer_tree_impl()->IsActiveTree()) AddLowResolutionTilingIfNeeded(); @@ -754,10 +750,12 @@ void PictureLayerImpl::UpdateRasterSource( layer_tree_impl()->GetMSAASampleCountForRaster( new_display_item_list); needs_full_invalidation |= - current_display_item_list->discardable_image_map() - .contains_only_srgb_images() != - new_display_item_list->discardable_image_map() - .contains_only_srgb_images(); + layer_tree_impl()->GetRasterColorSpace( + current_display_item_list->discardable_image_map() + .content_color_usage()) != + layer_tree_impl()->GetRasterColorSpace( + new_display_item_list->discardable_image_map() + .content_color_usage()); if (needs_full_invalidation) new_invalidation->Union(gfx::Rect(raster_source->GetSize())); } @@ -814,28 +812,24 @@ void PictureLayerImpl::UpdateRasterSource( } } -bool PictureLayerImpl::UpdateCanUseLCDTextAfterCommit() { - DCHECK(layer_tree_impl()->IsSyncTree()); - - // Once we disable lcd text, we don't re-enable it. - if (!can_use_lcd_text()) +bool PictureLayerImpl::UpdateCanUseLCDText( + bool raster_translation_aligns_pixels) { + // If we have pending/active trees, the active tree doesn't update lcd text + // status but copies it from the pending tree. + if (!layer_tree_impl()->IsSyncTree()) return false; - auto new_lcd_text_disallowed_reason = ComputeLCDTextDisallowedReason(); + auto new_lcd_text_disallowed_reason = + ComputeLCDTextDisallowedReason(raster_translation_aligns_pixels); if (lcd_text_disallowed_reason_ == new_lcd_text_disallowed_reason) return false; lcd_text_disallowed_reason_ = new_lcd_text_disallowed_reason; - // Synthetically invalidate everything. - gfx::Rect bounds_rect(bounds()); - invalidation_ = Region(bounds_rect); - tilings_->Invalidate(invalidation_); - UnionUpdateRect(bounds_rect); return true; } -LCDTextDisallowedReason PictureLayerImpl::ComputeLCDTextDisallowedReason() - const { +LCDTextDisallowedReason PictureLayerImpl::ComputeLCDTextDisallowedReason( + bool raster_translation_aligns_pixels) const { if (layer_tree_impl()->settings().layers_always_allowed_lcd_text) return LCDTextDisallowedReason::kNone; if (!layer_tree_impl()->settings().can_use_lcd_text) @@ -846,25 +840,38 @@ LCDTextDisallowedReason PictureLayerImpl::ComputeLCDTextDisallowedReason() return LCDTextDisallowedReason::kContentsNotOpaque; } - if (!use_transformed_rasterization_) { - if (!GetTransformTree() - .Node(transform_tree_index()) - ->node_and_ancestors_have_only_integer_translation) - return LCDTextDisallowedReason::kNonIntegralTranslation; + // If raster translation aligns pixels, we can ignore fractional layer offset + // and transform for LCD text. + if (!raster_translation_aligns_pixels) { if (static_cast<int>(offset_to_transform_parent().x()) != offset_to_transform_parent().x()) return LCDTextDisallowedReason::kNonIntegralXOffset; if (static_cast<int>(offset_to_transform_parent().y()) != offset_to_transform_parent().y()) return LCDTextDisallowedReason::kNonIntegralYOffset; + return LCDTextDisallowedReason::kNonIntegralTranslation; } if (has_will_change_transform_hint()) return LCDTextDisallowedReason::kWillChangeTransform; + if (screen_space_transform_is_animating()) + return LCDTextDisallowedReason::kTransformAnimation; + + EffectNode* effect_node = GetEffectTree().Node(effect_tree_index()); + if (effect_node->node_or_ancestor_has_filters) + return LCDTextDisallowedReason::kPixelOrColorEffect; + return LCDTextDisallowedReason::kNone; } +LCDTextDisallowedReason +PictureLayerImpl::ComputeLCDTextDisallowedReasonForTesting() const { + gfx::Vector2dF raster_translation; + return ComputeLCDTextDisallowedReason( + CalculateRasterTranslation(raster_translation)); +} + void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { if (layer_tree_impl()->IsActiveTree()) damage_rect_.Union(tile->enclosing_layer_rect()); @@ -928,8 +935,7 @@ std::unique_ptr<Tile> PictureLayerImpl::CreateTile( flags |= Tile::IS_OPAQUE; return layer_tree_impl()->tile_manager()->CreateTile( - info, id(), layer_tree_impl()->source_frame_number(), flags, - can_use_lcd_text()); + info, id(), layer_tree_impl()->source_frame_number(), flags); } const Region* PictureLayerImpl::GetPendingInvalidation() { @@ -965,6 +971,10 @@ const PaintWorkletRecordMap& PictureLayerImpl::GetPaintWorkletRecords() const { return paint_worklet_records_; } +bool PictureLayerImpl::IsDirectlyCompositedImage() const { + return directly_composited_image_size_.has_value(); +} + gfx::Rect PictureLayerImpl::GetEnclosingRectInTargetSpace() const { return GetScaledEnclosingRectInTargetSpace(MaximumTilingContentsScale()); } @@ -1071,19 +1081,6 @@ void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { NoteLayerPropertyChanged(); } -void PictureLayerImpl::SetUseTransformedRasterization(bool use) { - // With transformed rasterization, the pixels along the edge of the layer may - // become translucent, so clear contents_opaque. - if (use) - SetContentsOpaque(false); - - if (use_transformed_rasterization_ == use) - return; - - use_transformed_rasterization_ = use; - NoteLayerPropertyChanged(); -} - void PictureLayerImpl::SetDirectlyCompositedImageSize( base::Optional<gfx::Size> size) { if (directly_composited_image_size_ == size) @@ -1094,6 +1091,11 @@ void PictureLayerImpl::SetDirectlyCompositedImageSize( } bool PictureLayerImpl::ShouldDirectlyCompositeImage(float raster_scale) const { + // Even if there are minor rendering differences, we want to apply directly + // compositing images in cases where doing so is going to save memory. + if (raster_scale < 0.1f) + return true; + // If the results of scaling the bounds by the expected raster scale // would end up with a content rect whose width/height are more than one // pixel different from the layer bounds, don't directly composite the image @@ -1179,12 +1181,15 @@ void PictureLayerImpl::LogDirectlyCompositedImageRasterScaleUMAs() const { } PictureLayerTiling* PictureLayerImpl::AddTiling( - const gfx::AxisTransform2d& contents_transform) { + const gfx::AxisTransform2d& raster_transform) { DCHECK(CanHaveTilings()); - DCHECK_GE(contents_transform.scale(), MinimumContentsScale()); - DCHECK_LE(contents_transform.scale(), MaximumContentsScale()); + DCHECK_GE(raster_transform.scale(), MinimumContentsScale()); + DCHECK_LE(raster_transform.scale(), MaximumContentsScale()); DCHECK(raster_source_->HasRecordings()); - return tilings_->AddTiling(contents_transform, raster_source_); + bool tiling_can_use_lcd_text = + can_use_lcd_text() && raster_transform.scale() == raster_contents_scale_; + return tilings_->AddTiling(raster_transform, raster_source_, + tiling_can_use_lcd_text); } void PictureLayerImpl::RemoveAllTilings() { @@ -1193,24 +1198,56 @@ void PictureLayerImpl::RemoveAllTilings() { ResetRasterScale(); } -void PictureLayerImpl::AddTilingsForRasterScale() { - // Reset all resolution enums on tilings, we'll be setting new values in this - // function. - tilings_->MarkAllTilingsNonIdeal(); +bool PictureLayerImpl::CanRecreateHighResTilingForLCDTextAndRasterTranslation( + const PictureLayerTiling& high_res) const { + // This is for the sync tree only to avoid flickering. + if (!layer_tree_impl()->IsSyncTree()) + return false; + // We can recreate the tiling if we would invalidate all of its tiles. + if (high_res.may_contain_low_resolution_tiles()) + return true; + // Keep the non-ideal raster translation unchanged for transform animations + // to avoid re-rasterization during animation. + if (draw_properties().screen_space_transform_is_animating || + has_will_change_transform_hint()) + return false; + // Also avoid re-rasterization during pinch-zoom. + if (layer_tree_impl()->PinchGestureActive()) + return false; + return true; +} +void PictureLayerImpl::UpdateTilingsForRasterScaleAndTranslation( + bool has_adjusted_raster_scale) { PictureLayerTiling* high_res = tilings_->FindTilingWithScaleKey(raster_contents_scale_); - // Note: This function is always invoked when raster scale is recomputed, - // but not necessarily changed. This means raster translation update is also - // always done when there are significant changes that triggered raster scale - // recomputation. - gfx::Vector2dF raster_translation = - CalculateRasterTranslation(raster_contents_scale_); - if (high_res && - high_res->raster_transform().translation() != raster_translation) { - tilings_->Remove(high_res); - high_res = nullptr; + + gfx::Vector2dF raster_translation; + bool raster_translation_aligns_pixels = + CalculateRasterTranslation(raster_translation); + bool can_use_lcd_text_changed = + UpdateCanUseLCDText(raster_translation_aligns_pixels); + if (high_res) { + bool raster_translation_is_not_ideal = + high_res->raster_transform().translation() != raster_translation; + bool should_recreate_high_res = + (raster_translation_is_not_ideal || can_use_lcd_text_changed) && + CanRecreateHighResTilingForLCDTextAndRasterTranslation(*high_res); + if (should_recreate_high_res) { + tilings_->Remove(high_res); + high_res = nullptr; + } else if (!has_adjusted_raster_scale) { + // Nothing changed, no need to update tilings. + DCHECK_EQ(HIGH_RESOLUTION, high_res->resolution()); + SanityCheckTilingState(); + return; + } } + + // Reset all resolution enums on tilings, we'll be setting new values in this + // function. + tilings_->MarkAllTilingsNonIdeal(); + if (!high_res) { // We always need a high res tiling, so create one if it doesn't exist. high_res = AddTiling( @@ -1244,7 +1281,10 @@ void PictureLayerImpl::AddTilingsForRasterScale() { } bool PictureLayerImpl::ShouldAdjustRasterScale( - bool ideal_contents_scale_changed) const { + float old_ideal_contents_scale) const { + if (!raster_contents_scale_) + return true; + if (directly_composited_image_size_) { // If we have a directly composited image size, but previous raster scale // calculations did not set an initial raster scale, we must recalcluate. @@ -1269,6 +1309,9 @@ bool PictureLayerImpl::ShouldAdjustRasterScale( // changed. We should recalculate in order to raster at the intrinsic image // size. Note that this is not a comparison of the used raster_source_scale_ // and desired because of the adjustments in RecalculateRasterScales. + bool ideal_contents_scale_changed = + old_ideal_contents_scale != 0 && + old_ideal_contents_scale != ideal_contents_scale_; bool default_raster_scale_changed = default_raster_scale != directly_composited_image_initial_raster_scale_; if (ideal_contents_scale_changed && !default_raster_scale_changed) { @@ -1567,43 +1610,58 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer( SanityCheckTilingState(); } -gfx::Vector2dF PictureLayerImpl::CalculateRasterTranslation( - float raster_scale) { - if (!use_transformed_rasterization_) - return gfx::Vector2dF(); - - DCHECK(!contents_opaque()); +bool PictureLayerImpl::CalculateRasterTranslation( + gfx::Vector2dF& raster_translation) const { + // If this setting is set, the client (e.g. the Chromium UI) is sure that it + // can almost always align raster pixels to physical pixels, and doesn't care + // about temporary misalignment, so don't bother raster translation. + if (layer_tree_impl()->settings().layers_always_allowed_lcd_text) + return true; + const gfx::Transform& screen_transform = ScreenSpaceTransform(); gfx::Transform draw_transform = DrawTransform(); - // TODO(enne): for performance reasons, we should only have a raster - // translation when the screen space transform is not animating. We try to - // avoid this elsewhere but it still happens: http://crbug.com/778440 - // TODO(enne): Also, we shouldn't ever get here if the draw transform is not - // just a scale + translation, but we do sometimes: http://crbug.com/740113 - if (draw_properties().screen_space_transform_is_animating || + + if (!screen_transform.IsScaleOrTranslation() || !draw_transform.IsScaleOrTranslation()) { - // For now, while these problems are not well understood, avoid changing - // the raster scale in these cases. - return gfx::Vector2dF(); + return false; } // It is only useful to align the content space to the target space if their // relative pixel ratio is some small rational number. Currently we only - // align if the relative pixel ratio is 1:1. - // Good match if the maximum alignment error on a layer of size 10000px - // does not exceed 0.001px. - static constexpr float kErrorThreshold = 0.0000001f; - if (std::abs(draw_transform.matrix().getFloat(0, 0) - raster_scale) > - kErrorThreshold || - std::abs(draw_transform.matrix().getFloat(1, 1) - raster_scale) > - kErrorThreshold) - return gfx::Vector2dF(); - - // Extract the fractional part of layer origin in the target space. - float origin_x = draw_transform.matrix().getFloat(0, 3); - float origin_y = draw_transform.matrix().getFloat(1, 3); - return gfx::Vector2dF(origin_x - floorf(origin_x), - origin_y - floorf(origin_y)); + // align if the relative pixel ratio is 1:1 (i.e. the scale components of + // both the screen transform and the draw transform are approximately the same + // as |raster_contents_scale_|). Good match if the maximum alignment error on + // a layer of size 10000px does not exceed 0.001px. + static constexpr float kPixelErrorThreshold = 0.001f; + static constexpr float kScaleErrorThreshold = kPixelErrorThreshold / 10000; + auto is_raster_scale = [this](float scale) -> bool { + return std::abs(scale - raster_contents_scale_) <= kScaleErrorThreshold; + }; + if (!is_raster_scale(screen_transform.matrix().getFloat(0, 0)) || + !is_raster_scale(screen_transform.matrix().getFloat(1, 1)) || + !is_raster_scale(draw_transform.matrix().getFloat(0, 0)) || + !is_raster_scale(draw_transform.matrix().getFloat(1, 1))) { + return false; + } + + // Extract the fractional part of layer origin in the screen space and in the + // target space. + auto fraction = [](float f) -> float { return f - floorf(f); }; + float screen_x_fraction = fraction(screen_transform.matrix().getFloat(0, 3)); + float screen_y_fraction = fraction(screen_transform.matrix().getFloat(1, 3)); + float target_x_fraction = fraction(draw_transform.matrix().getFloat(0, 3)); + float target_y_fraction = fraction(draw_transform.matrix().getFloat(1, 3)); + + // If the origin is different in the screen space and in the target space, + // it means the render target is not aligned to physical pixels, and the + // text content will be blurry regardless of raster translation. + if (std::abs(screen_x_fraction - target_x_fraction) > kPixelErrorThreshold || + std::abs(screen_y_fraction - target_y_fraction) > kPixelErrorThreshold) { + return false; + } + + raster_translation = gfx::Vector2dF(target_x_fraction, target_y_fraction); + return true; } float PictureLayerImpl::MinimumContentsScale() const { @@ -1713,26 +1771,34 @@ void PictureLayerImpl::UpdateIdealScales() { DCHECK_GT(min_contents_scale, 0.f); ideal_device_scale_ = layer_tree_impl()->device_scale_factor(); + ideal_page_scale_ = 1.f; + ideal_contents_scale_ = GetIdealContentsScale(); + if (layer_tree_impl()->PageScaleTransformNode()) { + DCHECK(!layer_tree_impl()->settings().is_layer_tree_for_subframe); ideal_page_scale_ = IsAffectedByPageScale() ? layer_tree_impl()->current_page_scale_factor() : 1.f; - ideal_contents_scale_ = GetIdealContentsScale(); - } else { - // This layer may be in a layer tree embedded in a hierarchy that has its - // own page scale factor. We represent that here as - // 'external_page_scale_factor', a value that affects raster scale in the - // same way that page_scale_factor does, but doesn't affect any geometry - // calculations. - float external_page_scale_factor = - layer_tree_impl() ? layer_tree_impl()->external_page_scale_factor() - : 1.f; - DCHECK(!layer_tree_impl() || external_page_scale_factor == 1.f || - layer_tree_impl()->current_page_scale_factor() == 1.f); - ideal_page_scale_ = external_page_scale_factor; - ideal_contents_scale_ = - GetIdealContentsScale() * external_page_scale_factor; } + + // This layer may be in a layer tree embedded in a hierarchy that has its own + // page scale factor. We represent that here as 'external_page_scale_factor', + // a value that affects raster scale in the same way that page_scale_factor + // does, but doesn't affect any geometry calculations. In a normal main frame + // or OOPIF, only one of current or external page scale factor is ever used + // but not both. The only exception to this is a main frame in a portal. It + // may have a current_page_scale_factor (e.g. due to a viewport <meta> tag) + // as well as an external_page_scale_factor coming from the page scale of its + // embedder page. + float external_page_scale_factor = + layer_tree_impl() ? layer_tree_impl()->external_page_scale_factor() : 1.f; + DCHECK(!layer_tree_impl() || + !layer_tree_impl()->settings().is_layer_tree_for_subframe || + external_page_scale_factor == 1.f || + layer_tree_impl()->current_page_scale_factor() == 1.f); + ideal_page_scale_ *= external_page_scale_factor; + ideal_contents_scale_ *= external_page_scale_factor; + ideal_contents_scale_ = base::ClampToRange( ideal_contents_scale_, min_contents_scale, kMaxIdealContentsScale); ideal_source_scale_ = @@ -1968,17 +2034,10 @@ void PictureLayerImpl::InvalidatePaintWorklets( gfx::ContentColorUsage PictureLayerImpl::GetContentColorUsage() const { auto display_item_list = raster_source_->GetDisplayItemList(); - bool contains_only_srgb_images = true; - if (display_item_list) { - contains_only_srgb_images = - display_item_list->discardable_image_map().contains_only_srgb_images(); - } - - if (contains_only_srgb_images) + if (!display_item_list) return gfx::ContentColorUsage::kSRGB; - // TODO(cblume) This assumes only wide color gamut and not HDR - return gfx::ContentColorUsage::kWideColorGamut; + return display_item_list->discardable_image_map().content_color_usage(); } } // namespace cc |