diff options
author | danakj <danakj@chromium.org> | 2014-10-10 12:35:06 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-10 19:35:19 +0000 |
commit | e488f71403f5a3a9bd43629b4b9fbb7b9d3d6ff7 (patch) | |
tree | 72586c4ded7f4c8bccc5f7d98a3422e4c7414c84 /cc | |
parent | 571b18256a44c782c1ac0c12bcaf13a73c0c497c (diff) | |
download | chromium_src-e488f71403f5a3a9bd43629b4b9fbb7b9d3d6ff7.zip chromium_src-e488f71403f5a3a9bd43629b4b9fbb7b9d3d6ff7.tar.gz chromium_src-e488f71403f5a3a9bd43629b4b9fbb7b9d3d6ff7.tar.bz2 |
cc: Make PictureLayerImpl use a better choice for animated raster scale.
Two changes here:
1. When finding the max scale of an animation, only consider the scales
at each of the animations keyframes excluding the animations origin.
This is done because the origin is not an interesting scale to use, we
are animating away from it. And in the case of a layer at a high scale,
we are unable to raster all of its content at that scale. It would be
better to use the scale at the end of the transform since that is what
we will want to raster eventually.
2. When PictureLayerImpl chooses to use the animation scale:
a) Always allow using it if the scale is less than the current raster
scale choice. It can only put us in a better position memory-wise.
b) Don't use the max() with the current raster scale choice, that means
we will never use the animation scale if it is zooming out, which is
not what we want. This would also mean we choose a new raster scale on
every frame, which is bad. Just use the scale of the animation straight
up, and if it's not known, use a source scale of 1.
R=ajuma, vmpstr
BUG=421812
Review URL: https://codereview.chromium.org/642983003
Cr-Commit-Position: refs/heads/master@{#299162}
Diffstat (limited to 'cc')
-rw-r--r-- | cc/animation/animation_curve.h | 10 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve.cc | 35 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve.h | 3 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve_unittest.cc | 29 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller.cc | 18 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller.h | 7 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller_unittest.cc | 81 | ||||
-rw-r--r-- | cc/animation/transform_operations.cc | 35 | ||||
-rw-r--r-- | cc/animation/transform_operations.h | 18 | ||||
-rw-r--r-- | cc/animation/transform_operations_unittest.cc | 132 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.cc | 34 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_unittest.cc | 38 | ||||
-rw-r--r-- | cc/test/animation_test_common.cc | 3 | ||||
-rw-r--r-- | cc/test/animation_test_common.h | 3 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_common.cc | 2 |
15 files changed, 252 insertions, 196 deletions
diff --git a/cc/animation/animation_curve.h b/cc/animation/animation_curve.h index ca53e44..7f38af9 100644 --- a/cc/animation/animation_curve.h +++ b/cc/animation/animation_curve.h @@ -81,9 +81,13 @@ class CC_EXPORT TransformAnimationCurve : public AnimationCurve { // Returns true if this animation is a translation. virtual bool IsTranslation() const = 0; - // Set |max_scale| to the maximum scale along any dimension during this - // animation. Returns false if the maximum scale cannot be computed. - virtual bool MaximumScale(float* max_scale) const = 0; + // Set |max_scale| to the maximum scale along any dimension at the end of + // intermediate animation target points (eg keyframe end points). When + // |forward_direction| is true, the animation curve assumes it plays from + // the first keyframe to the last, otherwise it assumes the opposite. Returns + // false if the maximum scale cannot be computed. + virtual bool MaximumTargetScale(bool forward_direction, + float* max_scale) const = 0; // Partial Animation implementation. virtual CurveType Type() const override; diff --git a/cc/animation/keyframed_animation_curve.cc b/cc/animation/keyframed_animation_curve.cc index bcf067e..de18a2b 100644 --- a/cc/animation/keyframed_animation_curve.cc +++ b/cc/animation/keyframed_animation_curve.cc @@ -366,23 +366,30 @@ bool KeyframedTransformAnimationCurve::IsTranslation() const { return true; } -bool KeyframedTransformAnimationCurve::MaximumScale(float* max_scale) const { +bool KeyframedTransformAnimationCurve::MaximumTargetScale( + bool forward_direction, + float* max_scale) const { DCHECK_GE(keyframes_.size(), 2ul); *max_scale = 0.f; - for (size_t i = 1; i < keyframes_.size(); ++i) { - float min_progress = 0.f; - float max_progress = 1.f; - if (keyframes_[i - 1]->timing_function()) - keyframes_[i - 1]->timing_function()->Range(&min_progress, &max_progress); - - float max_scale_for_segment = 0.f; - if (!keyframes_[i]->Value().MaximumScale(keyframes_[i - 1]->Value(), - min_progress, - max_progress, - &max_scale_for_segment)) - return false; - *max_scale = std::max(*max_scale, max_scale_for_segment); + // If |forward_direction| is true, then skip the first frame, otherwise + // skip the last frame, since that is the original position in the animation. + size_t start = 1; + size_t end = keyframes_.size(); + if (!forward_direction) { + --start; + --end; + } + + for (size_t i = start; i < end; ++i) { + gfx::Vector3dF target_scale_for_segment; + if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment)) + return false; + float max_scale_for_segment = + fmax(std::abs(target_scale_for_segment.x()), + fmax(std::abs(target_scale_for_segment.y()), + std::abs(target_scale_for_segment.z()))); + *max_scale = fmax(*max_scale, max_scale_for_segment); } return true; } diff --git a/cc/animation/keyframed_animation_curve.h b/cc/animation/keyframed_animation_curve.h index d596256..5d25b89 100644 --- a/cc/animation/keyframed_animation_curve.h +++ b/cc/animation/keyframed_animation_curve.h @@ -196,7 +196,8 @@ class CC_EXPORT KeyframedTransformAnimationCurve gfx::BoxF* bounds) const override; virtual bool AffectsScale() const override; virtual bool IsTranslation() const override; - virtual bool MaximumScale(float* max_scale) const override; + virtual bool MaximumTargetScale(bool forward_direction, + float* max_scale) const override; private: KeyframedTransformAnimationCurve(); diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc index 9ce1fdb..7a82fa2 100644 --- a/cc/animation/keyframed_animation_curve_unittest.cc +++ b/cc/animation/keyframed_animation_curve_unittest.cc @@ -510,8 +510,8 @@ TEST(KeyframedAnimationCurveTest, IsTranslation) { EXPECT_FALSE(curve->IsTranslation()); } -// Tests that maximum scale is computed as expected. -TEST(KeyframedAnimationCurveTest, MaximumScale) { +// Tests that maximum target scale is computed as expected. +TEST(KeyframedAnimationCurveTest, MaximumTargetScale) { scoped_ptr<KeyframedTransformAnimationCurve> curve( KeyframedTransformAnimationCurve::Create()); @@ -523,7 +523,7 @@ TEST(KeyframedAnimationCurveTest, MaximumScale) { 1.0, operations1, EaseTimingFunction::Create())); float maximum_scale = 0.f; - EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); + EXPECT_TRUE(curve->MaximumTargetScale(true, &maximum_scale)); EXPECT_EQ(3.f, maximum_scale); TransformOperations operations2; @@ -531,7 +531,7 @@ TEST(KeyframedAnimationCurveTest, MaximumScale) { curve->AddKeyframe(TransformKeyframe::Create( 2.0, operations2, EaseTimingFunction::Create())); - EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); + EXPECT_TRUE(curve->MaximumTargetScale(true, &maximum_scale)); EXPECT_EQ(6.f, maximum_scale); TransformOperations operations3; @@ -539,7 +539,26 @@ TEST(KeyframedAnimationCurveTest, MaximumScale) { curve->AddKeyframe(TransformKeyframe::Create( 3.0, operations3, EaseTimingFunction::Create())); - EXPECT_FALSE(curve->MaximumScale(&maximum_scale)); + EXPECT_FALSE(curve->MaximumTargetScale(true, &maximum_scale)); + + // The original scale is not used in computing the max. + scoped_ptr<KeyframedTransformAnimationCurve> curve2( + KeyframedTransformAnimationCurve::Create()); + + TransformOperations operations4; + operations4.AppendScale(0.4f, 0.2f, 0.6f); + curve2->AddKeyframe(TransformKeyframe::Create( + 0.0, operations4, EaseTimingFunction::Create())); + TransformOperations operations5; + operations5.AppendScale(0.5f, 0.3f, -0.8f); + curve2->AddKeyframe(TransformKeyframe::Create( + 1.0, operations5, EaseTimingFunction::Create())); + + EXPECT_TRUE(curve2->MaximumTargetScale(true, &maximum_scale)); + EXPECT_EQ(0.8f, maximum_scale); + + EXPECT_TRUE(curve2->MaximumTargetScale(false, &maximum_scale)); + EXPECT_EQ(0.6f, maximum_scale); } // Tests that an animation with a curve timing function works as expected. diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index 911c5c4..9aa67aa 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -5,6 +5,7 @@ #include "cc/animation/layer_animation_controller.h" #include <algorithm> +#include <vector> #include "cc/animation/animation.h" #include "cc/animation/animation_delegate.h" @@ -494,17 +495,30 @@ bool LayerAnimationController::HasOnlyTranslationTransforms() const { return true; } -bool LayerAnimationController::MaximumScale(float* max_scale) const { +bool LayerAnimationController::MaximumTargetScale(float* max_scale) const { *max_scale = 0.f; for (size_t i = 0; i < animations_.size(); ++i) { if (animations_[i]->is_finished() || animations_[i]->target_property() != Animation::Transform) continue; + bool forward_direction = true; + switch (animations_[i]->direction()) { + case Animation::Normal: + case Animation::Alternate: + forward_direction = animations_[i]->playback_rate() >= 0.0; + break; + case Animation::Reverse: + case Animation::AlternateReverse: + forward_direction = animations_[i]->playback_rate() < 0.0; + break; + } + const TransformAnimationCurve* transform_animation_curve = animations_[i]->curve()->ToTransformAnimationCurve(); float animation_scale = 0.f; - if (!transform_animation_curve->MaximumScale(&animation_scale)) + if (!transform_animation_curve->MaximumTargetScale(forward_direction, + &animation_scale)) return false; *max_scale = std::max(*max_scale, animation_scale); } diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h index e57491a..01fce98 100644 --- a/cc/animation/layer_animation_controller.h +++ b/cc/animation/layer_animation_controller.h @@ -134,9 +134,10 @@ class CC_EXPORT LayerAnimationController bool HasOnlyTranslationTransforms() const; - // Sets |max_scale| to the maximum scale along any dimension during active - // animations. Returns false if the maximum scale cannot be computed. - bool MaximumScale(float* max_scale) const; + // Sets |max_scale| to the maximum scale along any dimension at any + // destination in active animations. Returns false if the maximum scale cannot + // be computed. + bool MaximumTargetScale(float* max_scale) const; bool needs_to_start_animations_for_testing() { return needs_to_start_animations_; diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index de21762..6d2f0c0 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc @@ -1890,12 +1890,12 @@ TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) { EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms()); } -TEST(LayerAnimationControllerTest, MaximumScale) { +TEST(LayerAnimationControllerTest, MaximumTargetScale) { scoped_refptr<LayerAnimationController> controller_impl( LayerAnimationController::Create(0)); float max_scale = 0.f; - EXPECT_TRUE(controller_impl->MaximumScale(&max_scale)); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); EXPECT_EQ(0.f, max_scale); scoped_ptr<KeyframedTransformAnimationCurve> curve1( @@ -1912,7 +1912,7 @@ TEST(LayerAnimationControllerTest, MaximumScale) { Animation::Create(curve1.Pass(), 1, 1, Animation::Transform)); controller_impl->AddAnimation(animation.Pass()); - EXPECT_TRUE(controller_impl->MaximumScale(&max_scale)); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); EXPECT_EQ(4.f, max_scale); scoped_ptr<KeyframedTransformAnimationCurve> curve2( @@ -1928,7 +1928,7 @@ TEST(LayerAnimationControllerTest, MaximumScale) { animation = Animation::Create(curve2.Pass(), 2, 2, Animation::Transform); controller_impl->AddAnimation(animation.Pass()); - EXPECT_TRUE(controller_impl->MaximumScale(&max_scale)); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); EXPECT_EQ(6.f, max_scale); scoped_ptr<KeyframedTransformAnimationCurve> curve3( @@ -1944,7 +1944,7 @@ TEST(LayerAnimationControllerTest, MaximumScale) { animation = Animation::Create(curve3.Pass(), 3, 3, Animation::Transform); controller_impl->AddAnimation(animation.Pass()); - EXPECT_FALSE(controller_impl->MaximumScale(&max_scale)); + EXPECT_FALSE(controller_impl->MaximumTargetScale(&max_scale)); controller_impl->GetAnimation(3, Animation::Transform) ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0)); @@ -1952,11 +1952,78 @@ TEST(LayerAnimationControllerTest, MaximumScale) { ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0)); // Only unfinished animations should be considered by - // MaximumScale. - EXPECT_TRUE(controller_impl->MaximumScale(&max_scale)); + // MaximumTargetScale. + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); EXPECT_EQ(4.f, max_scale); } +TEST(LayerAnimationControllerTest, MaximumTargetScaleWithDirection) { + scoped_refptr<LayerAnimationController> controller_impl( + LayerAnimationController::Create(0)); + + scoped_ptr<KeyframedTransformAnimationCurve> curve1( + KeyframedTransformAnimationCurve::Create()); + TransformOperations operations1; + operations1.AppendScale(1.0, 2.0, 3.0); + curve1->AddKeyframe(TransformKeyframe::Create( + 0.0, operations1, scoped_ptr<TimingFunction>())); + TransformOperations operations2; + operations2.AppendScale(4.0, 5.0, 6.0); + curve1->AddKeyframe(TransformKeyframe::Create( + 1.0, operations2, scoped_ptr<TimingFunction>())); + + scoped_ptr<Animation> animation_owned( + Animation::Create(curve1.Pass(), 1, 1, Animation::Transform)); + Animation* animation = animation_owned.get(); + controller_impl->AddAnimation(animation_owned.Pass()); + + float max_scale = 0.f; + + EXPECT_GT(animation->playback_rate(), 0.0); + + // Normal direction with positive playback rate. + animation->set_direction(Animation::Normal); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(6.f, max_scale); + + // Alternate direction with positive playback rate. + animation->set_direction(Animation::Alternate); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(6.f, max_scale); + + // Reverse direction with positive playback rate. + animation->set_direction(Animation::Reverse); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(3.f, max_scale); + + // Alternate reverse direction. + animation->set_direction(Animation::Reverse); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(3.f, max_scale); + + animation->set_playback_rate(-1.0); + + // Normal direction with negative playback rate. + animation->set_direction(Animation::Normal); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(3.f, max_scale); + + // Alternate direction with negative playback rate. + animation->set_direction(Animation::Alternate); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(3.f, max_scale); + + // Reverse direction with negative playback rate. + animation->set_direction(Animation::Reverse); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(6.f, max_scale); + + // Alternate reverse direction with negative playback rate. + animation->set_direction(Animation::Reverse); + EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale)); + EXPECT_EQ(6.f, max_scale); +} + TEST(LayerAnimationControllerTest, NewlyPushedAnimationWaitsForActivation) { scoped_ptr<AnimationEventsVector> events( make_scoped_ptr(new AnimationEventsVector)); diff --git a/cc/animation/transform_operations.cc b/cc/animation/transform_operations.cc index 6d8ad0f4..7c328af 100644 --- a/cc/animation/transform_operations.cc +++ b/cc/animation/transform_operations.cc @@ -114,41 +114,6 @@ bool TransformOperations::IsTranslation() const { return true; } -bool TransformOperations::MaximumScale(const TransformOperations& from, - SkMScalar min_progress, - SkMScalar max_progress, - float* max_scale) const { - if (!MatchesTypes(from)) - return false; - - gfx::Vector3dF from_scale; - gfx::Vector3dF to_scale; - - if (!from.ScaleComponent(&from_scale) || !ScaleComponent(&to_scale)) - return false; - - gfx::Vector3dF scale_at_min_progress( - std::abs(gfx::Tween::FloatValueBetween( - min_progress, from_scale.x(), to_scale.x())), - std::abs(gfx::Tween::FloatValueBetween( - min_progress, from_scale.y(), to_scale.y())), - std::abs(gfx::Tween::FloatValueBetween( - min_progress, from_scale.z(), to_scale.z()))); - gfx::Vector3dF scale_at_max_progress( - std::abs(gfx::Tween::FloatValueBetween( - max_progress, from_scale.x(), to_scale.x())), - std::abs(gfx::Tween::FloatValueBetween( - max_progress, from_scale.y(), to_scale.y())), - std::abs(gfx::Tween::FloatValueBetween( - max_progress, from_scale.z(), to_scale.z()))); - - gfx::Vector3dF max_scale_3d = scale_at_min_progress; - max_scale_3d.SetToMax(scale_at_max_progress); - *max_scale = - std::max(max_scale_3d.x(), std::max(max_scale_3d.y(), max_scale_3d.z())); - return true; -} - bool TransformOperations::ScaleComponent(gfx::Vector3dF* scale) const { *scale = gfx::Vector3dF(1.f, 1.f, 1.f); bool has_scale_component = false; diff --git a/cc/animation/transform_operations.h b/cc/animation/transform_operations.h index f086eb1..1c110ff 100644 --- a/cc/animation/transform_operations.h +++ b/cc/animation/transform_operations.h @@ -63,14 +63,6 @@ class CC_EXPORT TransformOperations { // Returns true if these operations are only translations. bool IsTranslation() const; - // Sets |max_scale| to be the maximum scale in any dimension when calling - // Blend on |from| with progress in the range [min_progress, max_progress]. If - // this maximum scale cannot be computed, returns false. - bool MaximumScale(const TransformOperations& from, - SkMScalar min_progress, - SkMScalar max_progress, - float* max_scale) const; - // Returns true if this operation and its descendants have the same types // as other and its descendants. bool MatchesTypes(const TransformOperations& other) const; @@ -80,6 +72,11 @@ class CC_EXPORT TransformOperations { // fails (this can happen if either matrix cannot be decomposed). bool CanBlendWith(const TransformOperations& other) const; + // If these operations have no more than one scale operation, and if the only + // other operations are translations, sets |scale| to the scale component + // of these operations. Otherwise, returns false. + bool ScaleComponent(gfx::Vector3dF* scale) const; + void AppendTranslate(SkMScalar x, SkMScalar y, SkMScalar z); void AppendRotate(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar degrees); void AppendScale(SkMScalar x, SkMScalar y, SkMScalar z); @@ -98,11 +95,6 @@ class CC_EXPORT TransformOperations { bool ComputeDecomposedTransform() const; - // If these operations have no more than one scale operation, and if the only - // other operations are translations, sets |scale| to the scale component - // of these operations. Otherwise, returns false. - bool ScaleComponent(gfx::Vector3dF* scale) const; - // For efficiency, we cache the decomposed transform. mutable scoped_ptr<gfx::DecomposedTransform> decomposed_transform_; mutable bool decomposed_transform_dirty_; diff --git a/cc/animation/transform_operations_unittest.cc b/cc/animation/transform_operations_unittest.cc index 87dd69d..208f81a 100644 --- a/cc/animation/transform_operations_unittest.cc +++ b/cc/animation/transform_operations_unittest.cc @@ -1402,131 +1402,83 @@ TEST(TransformOperationTest, IsTranslationWithMultipleOperations) { EXPECT_TRUE(operations2.IsTranslation()); } -TEST(TransformOperationTest, MaximumScale) { - TransformOperations operations1; - operations1.AppendScale(3.f, 2.f, 5.f); - TransformOperations operations2; - operations2.AppendScale(6.f, 5.f, 2.f); - - float max_scale = 0.f; - EXPECT_TRUE(operations2.MaximumScale(operations1, 0.f, 1.f, &max_scale)); - // x at progress 1.f - EXPECT_EQ(6.f, max_scale); - - EXPECT_TRUE(operations2.MaximumScale(operations1, -1.f, 1.f, &max_scale)); - // z at progress -1.f - EXPECT_EQ(8.f, max_scale); - - EXPECT_TRUE(operations2.MaximumScale(operations1, 0.f, 2.f, &max_scale)); - // x at progress 2.f - EXPECT_EQ(9.f, max_scale); - - TransformOperations operations3; - operations3.AppendScale(1.f, 4.f, 1.f); - TransformOperations operations4; - - EXPECT_TRUE(operations4.MaximumScale(operations3, 0.f, 1.f, &max_scale)); - // y at progress 0.f - EXPECT_EQ(4.f, max_scale); +TEST(TransformOperationTest, ScaleComponent) { + gfx::Vector3dF scale; - EXPECT_TRUE(operations4.MaximumScale(operations3, -1.f, 1.f, &max_scale)); - // y at progress -1.f - EXPECT_EQ(7.f, max_scale); - - EXPECT_TRUE(operations4.MaximumScale(operations3, 0.f, 2.f, &max_scale)); - // y at progress 0.f - EXPECT_EQ(4.f, max_scale); + // Scale. + TransformOperations operations1; + operations1.AppendScale(-3.f, 2.f, 5.f); + EXPECT_TRUE(operations1.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(-3.f, 2.f, 5.f), scale); + // Translate + Scale. TransformOperations operations5; operations5.AppendTranslate(1.f, 2.f, 3.f); - operations5.AppendScale(1.f, 1.f, 4.f); + operations5.AppendScale(2.f, 5.f, 4.f); + EXPECT_TRUE(operations5.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale); + + // Translate + Scale + Matrix with translate. gfx::Transform translation_transform; translation_transform.Translate3d(1.f, 2.f, 3.f); operations5.AppendMatrix(translation_transform); - TransformOperations operations6; - operations6.AppendTranslate(2.f, 3.f, 4.f); - operations6.AppendScale(2.f, 5.f, 1.f); - operations6.AppendMatrix(translation_transform); - - EXPECT_TRUE(operations6.MaximumScale(operations5, 0.f, 1.f, &max_scale)); - // y at progress 1.f - EXPECT_EQ(5.f, max_scale); - - EXPECT_TRUE(operations6.MaximumScale(operations5, -1.f, 1.f, &max_scale)); - // z at progress -1.f - EXPECT_EQ(7.f, max_scale); - - EXPECT_TRUE(operations6.MaximumScale(operations5, 0.f, 2.f, &max_scale)); - // y at progress 2.f - EXPECT_EQ(9.f, max_scale); + EXPECT_TRUE(operations5.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(2.f, 5.f, 4.f), scale); } -TEST(TransformOperationTest, MaximumScaleCannotBeComputed) { +TEST(TransformOperationTest, ScaleComponentCannotBeComputed) { + gfx::Vector3dF scale; + + // Scale can. TransformOperations operations1; operations1.AppendScale(2.f, 2.f, 2.f); + EXPECT_TRUE(operations1.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(2.f, 2.f, 2.f), scale); + + // Translate can. TransformOperations operations2; operations2.AppendTranslate(1.f, 2.f, 3.f); + EXPECT_TRUE(operations2.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(1.f, 1.f, 1.f), scale); - float max_scale = 0.f; - - // Non-matching operations. - EXPECT_FALSE(operations2.MaximumScale(operations1, 0.f, 1.f, &max_scale)); - + // Scale + translate can. TransformOperations operations3; - operations3.AppendScale(2.f, 2.f, 2.f); + operations3.AppendScale(2.f, 3.f, 2.f); operations3.AppendTranslate(1.f, 2.f, 3.f); - operations3.AppendScale(3.f, 3.f, 3.f); - TransformOperations operations4; - operations4.AppendScale(4.f, 4.f, 4.f); - operations4.AppendTranslate(2.f, 3.f, 4.f); - operations4.AppendScale(5.f, 5.f, 5.f); + EXPECT_TRUE(operations3.ScaleComponent(&scale)); + EXPECT_EQ(gfx::Vector3dF(2.f, 3.f, 2.f), scale); - // More that one scale operation in a sequence. - EXPECT_FALSE(operations4.MaximumScale(operations3, 0.f, 1.f, &max_scale)); + // Two Scales can't. + TransformOperations operations4; + operations4.AppendScale(2.f, 3.f, 2.f); + operations4.AppendScale(3.f, 2.f, 3.f); + EXPECT_FALSE(operations4.ScaleComponent(&scale)); + // Matrix can't. TransformOperations operations5; operations5.AppendScale(2.f, 2.f, 2.f); gfx::Transform scaling_transform; scaling_transform.Scale(2.f, 2.f); operations5.AppendMatrix(scaling_transform); - TransformOperations operations6; - operations6.AppendScale(3.f, 3.f, 3.f); - gfx::Transform translation_transform; - translation_transform.Translate3d(1.f, 2.f, 3.f); - operations6.AppendMatrix(translation_transform); - - // Non-translation matrix operation. - EXPECT_FALSE(operations6.MaximumScale(operations5, 0.f, 1.f, &max_scale)); + EXPECT_FALSE(operations5.ScaleComponent(&scale)); + // Scale + Rotate can't. TransformOperations operations7; operations7.AppendScale(2.f, 2.f, 2.f); operations7.AppendRotate(1.f, 2.f, 3.f, 4.f); - TransformOperations operations8; - operations8.AppendScale(3.f, 3.f, 3.f); - operations8.AppendRotate(3.f, 4.f, 5.f, 6.f); - - // Rotation operation. - EXPECT_FALSE(operations8.MaximumScale(operations7, 0.f, 1.f, &max_scale)); + EXPECT_FALSE(operations7.ScaleComponent(&scale)); + // Scale + Skew can't. TransformOperations operations9; operations9.AppendScale(2.f, 2.f, 2.f); operations9.AppendSkew(1.f, 2.f); - TransformOperations operations10; - operations10.AppendScale(3.f, 3.f, 3.f); - operations10.AppendSkew(3.f, 4.f); - - // Skew operation. - EXPECT_FALSE(operations10.MaximumScale(operations9, 0.f, 1.f, &max_scale)); + EXPECT_FALSE(operations9.ScaleComponent(&scale)); + // Scale + Perspective can't. TransformOperations operations11; operations11.AppendScale(2.f, 2.f, 2.f); operations11.AppendPerspective(1.f); - TransformOperations operations12; - operations12.AppendScale(3.f, 3.f, 3.f); - operations12.AppendPerspective(3.f); - - // Perspective operation. - EXPECT_FALSE(operations12.MaximumScale(operations11, 0.f, 1.f, &max_scale)); + EXPECT_FALSE(operations11.ScaleComponent(&scale)); } } // namespace diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index a4f8792..8bb0272 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -1045,27 +1045,33 @@ void PictureLayerImpl::RecalculateRasterScales() { // If we're not re-rasterizing during animation, rasterize at the maximum // scale that will occur during the animation, if the maximum scale is - // known. However, to avoid excessive memory use, don't rasterize at a scale - // at which this layer would become larger than the viewport. + // known. However we want to avoid excessive memory use. If the scale is + // smaller than what we would choose otherwise, then it's always better off + // for us memory-wise. But otherwise, we don't choose a scale at which this + // layer's rastered content would become larger than the viewport. if (draw_properties().screen_space_transform_is_animating && !ShouldAdjustRasterScaleDuringScaleAnimations()) { bool can_raster_at_maximum_scale = false; - if (draw_properties().maximum_animation_contents_scale > 0.f) { - gfx::Size bounds_at_maximum_scale = gfx::ToCeiledSize(gfx::ScaleSize( - bounds(), draw_properties().maximum_animation_contents_scale)); + // TODO(ajuma): If we need to deal with scale-down animations starting right + // as a layer gets promoted, then we'd want to have the + // |starting_animation_contents_scale| passed in here as a separate draw + // property so we could try use that when the max is too large. + // See crbug.com/422341. + float maximum_scale = draw_properties().maximum_animation_contents_scale; + if (maximum_scale) { + gfx::Size bounds_at_maximum_scale = + gfx::ToCeiledSize(gfx::ScaleSize(bounds(), maximum_scale)); if (bounds_at_maximum_scale.GetArea() <= layer_tree_impl()->device_viewport_size().GetArea()) can_raster_at_maximum_scale = true; } - if (can_raster_at_maximum_scale) { - raster_contents_scale_ = - std::max(raster_contents_scale_, - draw_properties().maximum_animation_contents_scale); - } else { - raster_contents_scale_ = - std::max(raster_contents_scale_, - 1.f * ideal_page_scale_ * ideal_device_scale_); - } + // Use the computed scales for the raster scale directly, do not try to use + // the ideal scale here. The current ideal scale may be way too large in the + // case of an animation with scale, and will be constantly changing. + if (can_raster_at_maximum_scale) + raster_contents_scale_ = maximum_scale; + else + raster_contents_scale_ = 1.f * ideal_page_scale_ * ideal_device_scale_; } // If this layer would create zero or one tiles at this content scale, diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 3ceb79b..11a84b0 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -1095,6 +1095,7 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { // Page scale animation, new high res, but not new low res because animating. contents_scale = 2.f; page_scale = 2.f; + maximum_animation_scale = 2.f; animating_transform = true; SetContentsScaleOnBothLayers(contents_scale, device_scale, @@ -2380,7 +2381,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f); // When animating with an unknown maximum animation scale factor, a new - // high-res tiling should be created at the animation's initial scale. + // high-res tiling should be created at a source scale of 1. animating_transform = true; contents_scale = 2.f; maximum_animation_scale = 0.f; @@ -2390,7 +2391,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { page_scale, maximum_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); // Further changes to scale during the animation should not cause a new // high-res tiling to get created. @@ -2401,7 +2402,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { page_scale, maximum_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2416,8 +2417,8 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { // When animating with a maxmium animation scale factor that is so large // that the layer grows larger than the viewport at this scale, a new - // high-res tiling should get created at the animation's initial scale, not - // at its maximum scale. + // high-res tiling should get created at a source scale of 1, not at its + // maximum scale. animating_transform = true; contents_scale = 2.f; maximum_animation_scale = 11.f; @@ -2427,7 +2428,7 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { page_scale, maximum_animation_scale, animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale); // Once we stop animating, a new high-res tiling should be created. animating_transform = false; @@ -2457,6 +2458,31 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { // Once we stop animating, a new high-res tiling should be created. animating_transform = false; + contents_scale = 12.f; + + SetContentsScaleOnBothLayers(contents_scale, + device_scale, + page_scale, + maximum_animation_scale, + animating_transform); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 12.f); + + // When animating toward a smaller scale, but that is still so large that the + // layer grows larger than the viewport at this scale, a new high-res tiling + // should get created at source scale 1. + animating_transform = true; + contents_scale = 11.f; + maximum_animation_scale = 11.f; + + SetContentsScaleOnBothLayers(contents_scale, + device_scale, + page_scale, + maximum_animation_scale, + animating_transform); + EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale); + + // Once we stop animating, a new high-res tiling should be created. + animating_transform = false; contents_scale = 11.f; SetContentsScaleOnBothLayers(contents_scale, diff --git a/cc/test/animation_test_common.cc b/cc/test/animation_test_common.cc index 9966b34..7c1b3f6 100644 --- a/cc/test/animation_test_common.cc +++ b/cc/test/animation_test_common.cc @@ -169,7 +169,8 @@ bool FakeTransformTransition::AffectsScale() const { return false; } bool FakeTransformTransition::IsTranslation() const { return true; } -bool FakeTransformTransition::MaximumScale(float* max_scale) const { +bool FakeTransformTransition::MaximumTargetScale(bool forward_direction, + float* max_scale) const { *max_scale = 1.f; return true; } diff --git a/cc/test/animation_test_common.h b/cc/test/animation_test_common.h index 1ee89da..7b53c48 100644 --- a/cc/test/animation_test_common.h +++ b/cc/test/animation_test_common.h @@ -45,7 +45,8 @@ class FakeTransformTransition : public TransformAnimationCurve { gfx::BoxF* bounds) const override; virtual bool AffectsScale() const override; virtual bool IsTranslation() const override; - virtual bool MaximumScale(float* max_scale) const override; + virtual bool MaximumTargetScale(bool forward_direction, + float* max_scale) const override; virtual scoped_ptr<AnimationCurve> Clone() const override; diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 3bd1e79..ba349db 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -1094,7 +1094,7 @@ static inline void CalculateAnimationContentsScale( } float layer_maximum_animated_scale = 0.f; - if (!layer->layer_animation_controller()->MaximumScale( + if (!layer->layer_animation_controller()->MaximumTargetScale( &layer_maximum_animated_scale)) { *combined_maximum_animation_contents_scale = 0.f; return; |