Commit 118640fa authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Chromium LUCI CQ

Force raster scale update on viewport rect change during animation

We clamp raster scale during animation by the device viewport size, so
we need to force raster scale update on device viewport rect change.

This is expecially important for remote frames which have zero device
viewport size initially, and the size is the frame size instead of the
actual device viewport. This happens in the testing frame on codepen
etc.

Also limit the minimum viewport geometry to avoid too small scale in
small remote frames.

Bug: 1164960
Change-Id: Idb1cfeb878fde76252a467bf8aca8c97ef506c6e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2623720Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842710}
parent d10b391b
......@@ -1352,13 +1352,15 @@ bool PictureLayerImpl::ShouldAdjustRasterScale() const {
if (raster_contents_scale_ < MinimumContentsScale())
return true;
// Don't change the raster scale if any of the following are true:
// - We have an animating transform.
// - The raster scale is already ideal.
if (draw_properties().screen_space_transform_is_animating ||
raster_source_scale_ == ideal_source_scale_) {
// Don't change the raster scale if we have an animating transform, except
// when the device viewport rect has changed because the raster scale may
// depend on the rect.
if (draw_properties().screen_space_transform_is_animating)
return layer_tree_impl()->device_viewport_rect_changed();
// Don't change the raster scale if the raster scale is already ideal.
if (raster_source_scale_ == ideal_source_scale_)
return false;
}
// Don't update will-change: transform layers if the raster contents scale is
// bigger than the minimum scale.
......@@ -1496,12 +1498,6 @@ void PictureLayerImpl::AdjustRasterScaleForTransformAnimation(
float preserved_raster_contents_scale) {
DCHECK(draw_properties().screen_space_transform_is_animating);
// We will cap the adjusted scale with the viewport area, which is impossible
// if the viewport is empty.
gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
if (viewport.IsEmpty())
return;
CombinedAnimationScale animation_scales =
layer_tree_impl()->property_trees()->GetAnimationScales(
transform_tree_index(), layer_tree_impl());
......@@ -1520,7 +1516,11 @@ void PictureLayerImpl::AdjustRasterScaleForTransformAnimation(
// However we want to avoid excessive memory use. Choose a scale at which this
// layer's rastered content is not larger than the viewport.
float max_viewport_dimension = std::max(viewport.width(), viewport.height());
gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
// To avoid too small scale in a small viewport.
constexpr int kMinViewportDimension = 500;
float max_viewport_dimension =
std::max({viewport.width(), viewport.height(), kMinViewportDimension});
DCHECK(max_viewport_dimension);
// Use square to compensate for viewports with different aspect ratios.
float squared_viewport_area = max_viewport_dimension * max_viewport_dimension;
......
......@@ -2981,6 +2981,47 @@ TEST_F(LegacySWPictureLayerImplTest, HighResTilingDuringAnimation) {
page_scale * device_scale);
}
TEST_F(LegacySWPictureLayerImplTest, ViewportSizeChangeDuringAnimation) {
gfx::Size layer_bounds(100, 100);
SetupDefaultTrees(layer_bounds);
host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect());
float contents_scale = 1.f;
float device_scale = 1.f;
float page_scale = 1.f;
float maximum_animation_scale = 1.f;
float starting_animation_scale = kNotScaled;
bool animating_transform = false;
EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 1.f);
animating_transform = true;
maximum_animation_scale = 20.f;
// Starting an animation should cause tiling resolution to get set to the
// maximum animation scale factor, clamped by the viewport size (using default
// minimum 500x500 as the viewport is empty for now).
SetupDrawPropertiesAndUpdateTiles(
pending_layer(), contents_scale, device_scale, page_scale,
maximum_animation_scale, starting_animation_scale, animating_transform);
EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 5.f);
// Setting viewport rect smaller than the minimum won't change raster scale.
host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect(400, 400));
SetupDrawPropertiesAndUpdateTiles(
pending_layer(), contents_scale, device_scale, page_scale,
maximum_animation_scale, starting_animation_scale, animating_transform);
EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 5.f);
// For a larger viewport size, the clamped scale is also larger.
host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect(1000, 200));
SetupDrawPropertiesAndUpdateTiles(
pending_layer(), contents_scale, device_scale, page_scale,
maximum_animation_scale, starting_animation_scale, animating_transform);
EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 10.f);
}
TEST_F(LegacySWPictureLayerImplTest,
AnimationTilingChangesWithWillChangeTransformHint) {
gfx::Size viewport_size(1000, 1000);
......
......@@ -1194,6 +1194,7 @@ void LayerTreeImpl::SetDeviceViewportRect(
if (device_viewport_rect == device_viewport_rect_)
return;
device_viewport_rect_ = device_viewport_rect;
device_viewport_rect_changed_ = true;
set_needs_update_draw_properties();
if (!IsActiveTree())
......@@ -1450,6 +1451,8 @@ bool LayerTreeImpl::UpdateDrawProperties(
image_animation_controller()->UpdateStateFromDrivers();
}
device_viewport_rect_changed_ = false;
DCHECK(!needs_update_draw_properties_)
<< "CalcDrawProperties should not set_needs_update_draw_properties()";
return true;
......
......@@ -745,6 +745,10 @@ class CC_EXPORT LayerTreeImpl {
return events_metrics_from_main_thread_.size();
}
bool device_viewport_rect_changed() const {
return device_viewport_rect_changed_;
}
protected:
float ClampPageScaleFactorToLimits(float page_scale_factor) const;
void PushPageScaleFactorAndLimits(const float* page_scale_factor,
......@@ -796,6 +800,7 @@ class CC_EXPORT LayerTreeImpl {
bool new_local_surface_id_request_ = false;
// Contains the physical rect of the device viewport, to be used in
// determining what needs to be drawn.
bool device_viewport_rect_changed_ = false;
gfx::Rect device_viewport_rect_;
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment