// Only the non-impl-paint multi-threaded compositor freezes animations.
MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostAnimationTestFrozenAnimationTickTime);
+// When animations are simultaneously added to an existing layer and to a new
+// layer, they should start at the same time, even when there's already a
+// running animation on the existing layer.
+class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
+ : public LayerTreeHostAnimationTest {
+ public:
+ LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers()
+ : frame_count_with_pending_tree_(0) {}
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommit() OVERRIDE {
+ if (layer_tree_host()->source_frame_number() == 1) {
+ AddAnimatedTransformToLayer(layer_tree_host()->root_layer(), 4, 1, 1);
+ } else if (layer_tree_host()->source_frame_number() == 2) {
+ AddOpacityTransitionToLayer(
+ layer_tree_host()->root_layer(), 1, 0.f, 0.5f, true);
+
+ scoped_refptr<Layer> layer = Layer::Create();
+ layer_tree_host()->root_layer()->AddChild(layer);
+ layer->set_layer_animation_delegate(this);
+ layer->SetBounds(gfx::Size(4, 4));
+ AddOpacityTransitionToLayer(layer, 1, 0.f, 0.5f, true);
+ }
+ }
+
+ virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ host_impl->BlockNotifyReadyToActivateForTesting(true);
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ // For the commit that added animations to new and existing layers, keep
+ // blocking activation. We want to verify that even with activation blocked,
+ // the animation on the layer that's already in the active tree won't get a
+ // head start.
+ if (!host_impl->settings().impl_side_painting ||
+ host_impl->pending_tree()->source_frame_number() != 2)
+ host_impl->BlockNotifyReadyToActivateForTesting(false);
+ }
+
+ virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+ const BeginFrameArgs& args) OVERRIDE {
+ if (!host_impl->pending_tree() ||
+ host_impl->pending_tree()->source_frame_number() != 2)
+ return;
+
+ frame_count_with_pending_tree_++;
+ if (frame_count_with_pending_tree_ == 2)
+ host_impl->BlockNotifyReadyToActivateForTesting(false);
+ }
+
+ virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl,
+ bool has_unfinished_animation) OVERRIDE {
+ Animation* root_animation = host_impl->active_tree()
+ ->root_layer()
+ ->layer_animation_controller()
+ ->GetAnimation(Animation::Opacity);
+ if (!root_animation || root_animation->run_state() != Animation::Running)
+ return;
+
+ Animation* child_animation = host_impl->active_tree()
+ ->root_layer()
+ ->children()[0]
+ ->layer_animation_controller()
+ ->GetAnimation(Animation::Opacity);
+ EXPECT_EQ(Animation::Running, child_animation->run_state());
+ EXPECT_EQ(root_animation->start_time(), child_animation->start_time());
+ EndTest();
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ int frame_count_with_pending_tree_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers);
+
+class LayerTreeHostAnimationTestAddAnimationAfterAnimating
+ : public LayerTreeHostAnimationTest {
+ public:
+ LayerTreeHostAnimationTestAddAnimationAfterAnimating()
+ : num_swap_buffers_(0) {}
+
+ virtual void SetupTree() OVERRIDE {
+ LayerTreeHostAnimationTest::SetupTree();
+ content_ = Layer::Create();
+ content_->SetBounds(gfx::Size(4, 4));
+ layer_tree_host()->root_layer()->AddChild(content_);
+ }
+
+ virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
+
+ virtual void DidCommit() OVERRIDE {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ // First frame: add an animation to the root layer.
+ AddAnimatedTransformToLayer(layer_tree_host()->root_layer(), 0.1, 5, 5);
+ break;
+ case 2:
+ // Second frame: add an animation to the content layer. The root layer
+ // animation has caused us to animate already during this frame.
+ AddOpacityTransitionToLayer(content_.get(), 0.1, 5, 5, false);
+ break;
+ }
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ // The third frame is when both animations have started. Check that both
+ // have a valid start time.
+ if (++num_swap_buffers_ == 3) {
+ EndTest();
+ AnimationRegistrar::AnimationControllerMap copy =
+ host_impl->animation_registrar()->active_animation_controllers();
+ EXPECT_EQ(2u, copy.size());
+ for (AnimationRegistrar::AnimationControllerMap::iterator iter =
+ copy.begin();
+ iter != copy.end();
+ ++iter) {
+ int id = ((*iter).second->id());
+ if (id == host_impl->RootLayer()->id()) {
+ Animation* anim = (*iter).second->GetAnimation(Animation::Transform);
+ EXPECT_GT(anim->start_time(), 0);
+ } else if (id == host_impl->RootLayer()->children()[0]->id()) {
+ Animation* anim = (*iter).second->GetAnimation(Animation::Opacity);
+ EXPECT_GT(anim->start_time(), 0);
+ }
+ }
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ scoped_refptr<Layer> content_;
+ int num_swap_buffers_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostAnimationTestAddAnimationAfterAnimating);
+
} // namespace
} // namespace cc