Don't PushProperties every commit for animating layers

This removes the need to PushProperties every commit during an animation.
Instead, a single PushProperties is needed whenever there are animations
waiting for deletion.

This also removes LayerAnimationController::set_force_sync, which no
longer had any non-test callers and wasn't actually needed by its test
callers.

BUG=259088

Review URL: https://codereview.chromium.org/60083018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235845 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index 3bac4a9..5279591 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -19,8 +19,7 @@
 namespace cc {
 
 LayerAnimationController::LayerAnimationController(int id)
-    : force_sync_(false),
-      registrar_(0),
+    : registrar_(0),
       id_(id),
       is_active_(false),
       last_tick_time_(0),
@@ -106,20 +105,17 @@
 void LayerAnimationController::PushAnimationUpdatesTo(
     LayerAnimationController* controller_impl) {
   DCHECK(this != controller_impl);
-  if (force_sync_) {
-    ReplaceImplThreadAnimations(controller_impl);
-    force_sync_ = false;
-  } else {
-    PurgeAnimationsMarkedForDeletion();
-    PushNewAnimationsToImplThread(controller_impl);
+  if (!has_any_animation() && !controller_impl->has_any_animation())
+    return;
+  PurgeAnimationsMarkedForDeletion();
+  PushNewAnimationsToImplThread(controller_impl);
 
-    // Remove finished impl side animations only after pushing,
-    // and only after the animations are deleted on the main thread
-    // this insures we will never push an animation twice.
-    RemoveAnimationsCompletedOnMainThread(controller_impl);
+  // Remove finished impl side animations only after pushing,
+  // and only after the animations are deleted on the main thread
+  // this insures we will never push an animation twice.
+  RemoveAnimationsCompletedOnMainThread(controller_impl);
 
-    PushPropertiesToImplThread(controller_impl);
-  }
+  PushPropertiesToImplThread(controller_impl);
   controller_impl->UpdateActivation(NormalActivation);
   UpdateActivation(NormalActivation);
 }
@@ -601,6 +597,8 @@
 
 void LayerAnimationController::MarkAnimationsForDeletion(
     double monotonic_time, AnimationEventsVector* events) {
+  bool marked_animations_for_deletions = false;
+
   // Non-aborted animations are marked for deletion after a corresponding
   // AnimationEvent::Finished event is sent or received. This means that if
   // we don't have an events vector, we must ensure that non-aborted animations
@@ -619,6 +617,7 @@
       }
       active_animations_[i]->SetRunState(Animation::WaitingForDeletion,
                                          monotonic_time);
+      marked_animations_for_deletions = true;
       continue;
     }
 
@@ -667,8 +666,11 @@
                                              monotonic_time);
         }
       }
+      marked_animations_for_deletions = true;
     }
   }
+  if (marked_animations_for_deletions)
+    NotifyObserversAnimationWaitingForDeletion();
 }
 
 static bool IsWaitingForDeletion(Animation* animation) {
@@ -684,27 +686,6 @@
                    animations.end());
 }
 
-void LayerAnimationController::ReplaceImplThreadAnimations(
-    LayerAnimationController* controller_impl) const {
-  controller_impl->active_animations_.clear();
-  for (size_t i = 0; i < active_animations_.size(); ++i) {
-    scoped_ptr<Animation> to_add;
-    if (active_animations_[i]->needs_synchronized_start_time()) {
-      // We haven't received an animation started notification yet, so it
-      // is important that we add it in a 'waiting' and not 'running' state.
-      Animation::RunState initial_run_state =
-          Animation::WaitingForTargetAvailability;
-      double start_time = 0;
-      to_add = active_animations_[i]->CloneAndInitialize(
-          initial_run_state, start_time).Pass();
-    } else {
-      to_add = active_animations_[i]->Clone().Pass();
-    }
-
-    controller_impl->AddAnimation(to_add.Pass());
-  }
-}
-
 void LayerAnimationController::TickAnimations(double monotonic_time) {
   for (size_t i = 0; i < active_animations_.size(); ++i) {
     if (active_animations_[i]->run_state() == Animation::Starting ||
@@ -792,6 +773,12 @@
                     OnFilterAnimated(filters));
 }
 
+void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
+  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
+                    value_observers_,
+                    OnAnimationWaitingForDeletion());
+}
+
 bool LayerAnimationController::HasValueObserver() {
   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 d48951f..6df5c05 100644
--- a/cc/animation/layer_animation_controller.h
+++ b/cc/animation/layer_animation_controller.h
@@ -79,10 +79,6 @@
   // the future.
   bool IsAnimatingProperty(Animation::TargetProperty target_property) const;
 
-  // If a sync is forced, then the next time animation updates are pushed to the
-  // impl thread, all animations will be transferred.
-  void set_force_sync() { force_sync_ = true; }
-
   void SetAnimationRegistrar(AnimationRegistrar* registrar);
   AnimationRegistrar* animation_registrar() { return registrar_; }
 
@@ -120,8 +116,6 @@
       LayerAnimationController* controller_impl) const;
   void PushPropertiesToImplThread(
       LayerAnimationController* controller_impl) const;
-  void ReplaceImplThreadAnimations(
-      LayerAnimationController* controller_impl) const;
 
   void StartAnimationsWaitingForNextTick(double monotonic_time);
   void StartAnimationsWaitingForStartTime(double monotonic_time);
@@ -146,12 +140,11 @@
   void NotifyObserversTransformAnimated(const gfx::Transform& transform);
   void NotifyObserversFilterAnimated(const FilterOperations& filter);
 
+  void NotifyObserversAnimationWaitingForDeletion();
+
   bool HasValueObserver();
   bool HasActiveValueObserver();
 
-  // If this is true, we force a sync to the impl thread.
-  bool force_sync_;
-
   AnimationRegistrar* registrar_;
   int id_;
   ScopedPtrVector<Animation> active_animations_;
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index a1dd9a2..6b77cd2 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -293,10 +293,15 @@
   controller->Animate(1.0);
   controller->UpdateState(true, NULL);
 
+  EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+  EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
+
   events.reset(new AnimationEventsVector);
   controller_impl->Animate(2.0);
   controller_impl->UpdateState(true, events.get());
 
+  EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
+
   // There should be a Finished event for the animation.
   EXPECT_EQ(1u, events->size());
   EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type);
@@ -309,6 +314,7 @@
 
   controller->Animate(3.0);
   controller->UpdateState(true, NULL);
+  EXPECT_TRUE(dummy.animation_waiting_for_deletion());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
 
@@ -1140,7 +1146,7 @@
   EXPECT_EQ(0.75f, dummy.opacity());
 }
 
-TEST(LayerAnimationControllerTest, ForceSyncWhenSynchronizedStartTimeNeeded) {
+TEST(LayerAnimationControllerTest, PushUpdatesWhenSynchronizedStartTimeNeeded) {
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
@@ -1166,8 +1172,6 @@
   EXPECT_TRUE(active_animation);
   EXPECT_TRUE(active_animation->needs_synchronized_start_time());
 
-  controller->set_force_sync();
-
   controller->PushAnimationUpdatesTo(controller_impl.get());
 
   active_animation = controller_impl->GetAnimation(0, Animation::Opacity);
@@ -1437,9 +1441,12 @@
   controller->AbortAnimations(Animation::Opacity);
   EXPECT_EQ(Animation::Aborted,
             controller->GetAnimation(Animation::Opacity)->run_state());
+  EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+  EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
 
   controller->Animate(1.0);
   controller->UpdateState(true, NULL);
+  EXPECT_TRUE(dummy.animation_waiting_for_deletion());
   EXPECT_EQ(Animation::WaitingForDeletion,
             controller->GetAnimation(Animation::Opacity)->run_state());
 
@@ -1468,10 +1475,13 @@
   controller_impl->AbortAnimations(Animation::Opacity);
   EXPECT_EQ(Animation::Aborted,
             controller_impl->GetAnimation(Animation::Opacity)->run_state());
+  EXPECT_FALSE(dummy.animation_waiting_for_deletion());
+  EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
 
   AnimationEventsVector events;
   controller_impl->Animate(1.0);
   controller_impl->UpdateState(true, &events);
+  EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
   EXPECT_EQ(1u, events.size());
   EXPECT_EQ(AnimationEvent::Aborted, events[0].type);
   EXPECT_EQ(Animation::WaitingForDeletion,
@@ -1483,6 +1493,7 @@
 
   controller->Animate(1.5);
   controller->UpdateState(true, NULL);
+  EXPECT_TRUE(dummy.animation_waiting_for_deletion());
   EXPECT_EQ(Animation::WaitingForDeletion,
             controller->GetAnimation(Animation::Opacity)->run_state());
 
diff --git a/cc/animation/layer_animation_value_observer.h b/cc/animation/layer_animation_value_observer.h
index adaf9c7..cc6219d 100644
--- a/cc/animation/layer_animation_value_observer.h
+++ b/cc/animation/layer_animation_value_observer.h
@@ -16,6 +16,7 @@
   virtual void OnFilterAnimated(const FilterOperations& filters) = 0;
   virtual void OnOpacityAnimated(float opacity) = 0;
   virtual void OnTransformAnimated(const gfx::Transform& transform) = 0;
+  virtual void OnAnimationWaitingForDeletion() = 0;
   virtual bool IsActive() const = 0;
 };
 
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 8d07366..e0ffb5cd 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -927,9 +927,7 @@
   stacking_order_changed_ = false;
   update_rect_ = gfx::RectF();
 
-  // Animating layers require further push properties to clean up the animation.
-  // crbug.com/259088
-  needs_push_properties_ = layer_animation_controller_->has_any_animation();
+  needs_push_properties_ = false;
   num_dependents_need_push_properties_ = 0;
 }
 
@@ -998,6 +996,11 @@
   transform_ = transform;
 }
 
+void Layer::OnAnimationWaitingForDeletion() {
+  // Animations are only deleted during PushProperties.
+  SetNeedsPushProperties();
+}
+
 bool Layer::IsActive() const {
   return true;
 }
@@ -1027,7 +1030,6 @@
     scoped_refptr<LayerAnimationController> controller) {
   layer_animation_controller_->RemoveValueObserver(this);
   layer_animation_controller_ = controller;
-  layer_animation_controller_->set_force_sync();
   layer_animation_controller_->AddValueObserver(this);
   SetNeedsCommit();
 }
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 889e09ba..b552a35 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -522,6 +522,7 @@
   virtual void OnFilterAnimated(const FilterOperations& filters) OVERRIDE;
   virtual void OnOpacityAnimated(float opacity) OVERRIDE;
   virtual void OnTransformAnimated(const gfx::Transform& transform) OVERRIDE;
+  virtual void OnAnimationWaitingForDeletion() OVERRIDE;
   virtual bool IsActive() const OVERRIDE;
 
   LayerList children_;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 1033b61..99f9502 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -694,6 +694,8 @@
   SetTransform(transform);
 }
 
+void LayerImpl::OnAnimationWaitingForDeletion() {}
+
 bool LayerImpl::IsActive() const {
   return layer_tree_impl_->IsActiveTree();
 }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index e774dfac..6d06b6d2 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -76,6 +76,7 @@
   virtual void OnFilterAnimated(const FilterOperations& filters) OVERRIDE;
   virtual void OnOpacityAnimated(float opacity) OVERRIDE;
   virtual void OnTransformAnimated(const gfx::Transform& transform) OVERRIDE;
+  virtual void OnAnimationWaitingForDeletion() OVERRIDE;
   virtual bool IsActive() const OVERRIDE;
 
   // Tree structure.
diff --git a/cc/test/animation_test_common.cc b/cc/test/animation_test_common.cc
index 22b7793..7ab26a5 100644
--- a/cc/test/animation_test_common.cc
+++ b/cc/test/animation_test_common.cc
@@ -186,7 +186,8 @@
 }
 
 FakeLayerAnimationValueObserver::FakeLayerAnimationValueObserver()
-    : opacity_(0.0f) {}
+    : opacity_(0.0f),
+      animation_waiting_for_deletion_(false) {}
 
 FakeLayerAnimationValueObserver::~FakeLayerAnimationValueObserver() {}
 
@@ -204,6 +205,10 @@
   transform_ = transform;
 }
 
+void FakeLayerAnimationValueObserver::OnAnimationWaitingForDeletion() {
+  animation_waiting_for_deletion_ = true;
+}
+
 bool FakeLayerAnimationValueObserver::IsActive() const {
   return true;
 }
diff --git a/cc/test/animation_test_common.h b/cc/test/animation_test_common.h
index a686b46..008af87 100644
--- a/cc/test/animation_test_common.h
+++ b/cc/test/animation_test_common.h
@@ -73,16 +73,22 @@
   virtual void OnFilterAnimated(const FilterOperations& filters) OVERRIDE;
   virtual void OnOpacityAnimated(float opacity) OVERRIDE;
   virtual void OnTransformAnimated(const gfx::Transform& transform) OVERRIDE;
+  virtual void OnAnimationWaitingForDeletion() OVERRIDE;
   virtual bool IsActive() const OVERRIDE;
 
   const FilterOperations& filters() const { return filters_; }
   float opacity() const  { return opacity_; }
   const gfx::Transform& transform() const { return transform_; }
 
+  bool animation_waiting_for_deletion() {
+    return animation_waiting_for_deletion_;
+  }
+
  private:
   FilterOperations filters_;
   float opacity_;
   gfx::Transform transform_;
+  bool animation_waiting_for_deletion_;
 };
 
 class FakeInactiveLayerAnimationValueObserver