summaryrefslogtreecommitdiffstats
path: root/cc/animation
diff options
context:
space:
mode:
authorajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-27 23:47:40 +0000
committerajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-27 23:47:40 +0000
commit41512b041cfaf1705ec435295549f8bf2f1484c9 (patch)
tree468e4d74cdb66b8b1d36c1141d67566e77a2dd19 /cc/animation
parentf37e941d37e68058b3709465c87c13c73af2420c (diff)
downloadchromium_src-41512b041cfaf1705ec435295549f8bf2f1484c9.zip
chromium_src-41512b041cfaf1705ec435295549f8bf2f1484c9.tar.gz
chromium_src-41512b041cfaf1705ec435295549f8bf2f1484c9.tar.bz2
Allow animations with inactive observers to reach the Starting state
Currently, when a LayerAnimationController only has an observer in the pending tree, we early-out from Animate and UpdateState in order to prevent animating a layer before it's drawn. However, this means that the position of a layer can change immediately after tree activation (even before a draw), if an animation is started on that layer. This means that tile priorities calculated by UpdateTilePriorites before tree activation can immediately become stale. This CL allows animations with only inactive observers to reach the Starting state and get ticked at their starting point, but progress no further. This means we still won't have running animations on layers before they're drawn. However, this change means that if we ensure that animation always happens before tree activation in each frame (in a follow-up CL), then the tile priorities calculated during tree activation will still be valid when the frame is drawn. BUG=242966 Review URL: https://chromiumcodereview.appspot.com/15732013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202473 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/animation')
-rw-r--r--cc/animation/layer_animation_controller.cc11
-rw-r--r--cc/animation/layer_animation_controller.h1
-rw-r--r--cc/animation/layer_animation_controller_unittest.cc63
3 files changed, 74 insertions, 1 deletions
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index 5e20dd5..ce73322 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -142,7 +142,7 @@ void LayerAnimationController::TransferAnimationsTo(
}
void LayerAnimationController::Animate(double monotonic_time) {
- if (!HasActiveValueObserver())
+ if (!HasValueObserver())
return;
StartAnimationsWaitingForNextTick(monotonic_time);
@@ -716,6 +716,15 @@ void LayerAnimationController::NotifyObserversTransformAnimated(
OnTransformAnimated(transform));
}
+bool LayerAnimationController::HasValueObserver() {
+ if (value_observers_.might_have_observers()) {
+ ObserverListBase<LayerAnimationValueObserver>::Iterator it(
+ value_observers_);
+ return it.GetNext() != NULL;
+ }
+ return false;
+}
+
bool LayerAnimationController::HasActiveValueObserver() {
if (value_observers_.might_have_observers()) {
ObserverListBase<LayerAnimationValueObserver>::Iterator it(
diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h
index e762f59..cd2f3cc 100644
--- a/cc/animation/layer_animation_controller.h
+++ b/cc/animation/layer_animation_controller.h
@@ -151,6 +151,7 @@ class CC_EXPORT LayerAnimationController
void NotifyObserversOpacityAnimated(float opacity);
void NotifyObserversTransformAnimated(const gfx::Transform& transform);
+ bool HasValueObserver();
bool HasActiveValueObserver();
// If this is true, we force a sync to the impl thread.
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index 6e2e8e2..8ba0a7c 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -1093,5 +1093,68 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
EXPECT_FALSE(controller->HasActiveAnimation());
}
+// Tests that an animation controller with only an inactive observer gets ticked
+// but doesn't progress animations past the Starting state.
+TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
+ scoped_ptr<AnimationEventsVector> events(
+ make_scoped_ptr(new AnimationEventsVector));
+ FakeLayerAnimationValueObserver dummy;
+ FakeInactiveLayerAnimationValueObserver inactive_dummy;
+ scoped_refptr<LayerAnimationController> controller(
+ LayerAnimationController::Create(0));
+
+ const int id = 1;
+ controller->AddAnimation(CreateAnimation(scoped_ptr<AnimationCurve>(
+ new FakeFloatTransition(1.0, 0.5f, 1.f)).Pass(),
+ id,
+ Animation::Opacity));
+
+ // Without an observer, the animation shouldn't progress to the Starting
+ // state.
+ controller->Animate(0.0);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(0u, events->size());
+ EXPECT_EQ(Animation::WaitingForTargetAvailability,
+ controller->GetAnimation(id, Animation::Opacity)->run_state());
+
+ controller->AddValueObserver(&inactive_dummy);
+
+ // With only an inactive observer, the animation should progress to the
+ // Starting state and get ticked at its starting point, but should not
+ // progress to Running.
+ controller->Animate(1.0);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(0u, events->size());
+ EXPECT_EQ(Animation::Starting,
+ controller->GetAnimation(id, Animation::Opacity)->run_state());
+ EXPECT_EQ(0.5f, inactive_dummy.opacity());
+
+ // Even when already in the Starting state, the animation should stay
+ // there, and shouldn't be ticked past its starting point.
+ controller->Animate(2.0);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(0u, events->size());
+ EXPECT_EQ(Animation::Starting,
+ controller->GetAnimation(id, Animation::Opacity)->run_state());
+ EXPECT_EQ(0.5f, inactive_dummy.opacity());
+
+ controller->AddValueObserver(&dummy);
+
+ // Now that an active observer has been added, the animation should still
+ // initially tick at its starting point, but should now progress to Running.
+ controller->Animate(3.0);
+ controller->UpdateState(true, events.get());
+ EXPECT_EQ(1u, events->size());
+ EXPECT_EQ(Animation::Running,
+ controller->GetAnimation(id, Animation::Opacity)->run_state());
+ EXPECT_EQ(0.5f, inactive_dummy.opacity());
+ EXPECT_EQ(0.5f, dummy.opacity());
+
+ // The animation should now tick past its starting point.
+ controller->Animate(3.5);
+ EXPECT_NE(0.5f, inactive_dummy.opacity());
+ EXPECT_NE(0.5f, dummy.opacity());
+}
+
} // namespace
} // namespace cc