summaryrefslogtreecommitdiffstats
path: root/chromium/cc/layers/picture_layer_impl.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-29 10:46:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-02 12:02:10 +0000
commit99677208ff3b216fdfec551fbe548da5520cd6fb (patch)
tree476a4865c10320249360e859d8fdd3e01833b03a /chromium/cc/layers/picture_layer_impl.cc
parentc30a6232df03e1efbd9f3b226777b07e087a1122 (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.cc301
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