1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/trees/layer_tree_host.h"
6
7#include "cc/animation/animation_curve.h"
8#include "cc/animation/layer_animation_controller.h"
9#include "cc/animation/scroll_offset_animation_curve.h"
10#include "cc/animation/timing_function.h"
11#include "cc/layers/layer.h"
12#include "cc/layers/layer_impl.h"
13#include "cc/test/animation_test_common.h"
14#include "cc/test/fake_content_layer.h"
15#include "cc/test/fake_content_layer_client.h"
16#include "cc/test/layer_tree_test.h"
17#include "cc/trees/layer_tree_impl.h"
18
19namespace cc {
20namespace {
21
22class LayerTreeHostAnimationTest : public LayerTreeTest {
23 public:
24  virtual void SetupTree() OVERRIDE {
25    LayerTreeTest::SetupTree();
26    layer_tree_host()->root_layer()->set_layer_animation_delegate(this);
27  }
28};
29
30// Makes sure that SetNeedsAnimate does not cause the CommitRequested() state to
31// be set.
32class LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested
33    : public LayerTreeHostAnimationTest {
34 public:
35  LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested()
36      : num_commits_(0) {}
37
38  virtual void BeginTest() OVERRIDE {
39    PostSetNeedsCommitToMainThread();
40  }
41
42  virtual void Animate(base::TimeTicks monotonic_time) OVERRIDE {
43    // We skip the first commit becasue its the commit that populates the
44    // impl thread with a tree. After the second commit, the test is done.
45    if (num_commits_ != 1)
46      return;
47
48    layer_tree_host()->SetNeedsAnimate();
49    // Right now, CommitRequested is going to be true, because during
50    // BeginFrame, we force CommitRequested to true to prevent requests from
51    // hitting the impl thread. But, when the next DidCommit happens, we should
52    // verify that CommitRequested has gone back to false.
53  }
54
55  virtual void DidCommit() OVERRIDE {
56    if (!num_commits_) {
57      EXPECT_FALSE(layer_tree_host()->CommitRequested());
58      layer_tree_host()->SetNeedsAnimate();
59      EXPECT_FALSE(layer_tree_host()->CommitRequested());
60    }
61
62    // Verifies that the SetNeedsAnimate we made in ::Animate did not
63    // trigger CommitRequested.
64    EXPECT_FALSE(layer_tree_host()->CommitRequested());
65    EndTest();
66    num_commits_++;
67  }
68
69  virtual void AfterTest() OVERRIDE {}
70
71 private:
72  int num_commits_;
73};
74
75MULTI_THREAD_TEST_F(
76    LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested);
77
78// Trigger a frame with SetNeedsCommit. Then, inside the resulting animate
79// callback, request another frame using SetNeedsAnimate. End the test when
80// animate gets called yet-again, indicating that the proxy is correctly
81// handling the case where SetNeedsAnimate() is called inside the BeginFrame
82// flow.
83class LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback
84    : public LayerTreeHostAnimationTest {
85 public:
86  LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback()
87      : num_animates_(0) {}
88
89  virtual void BeginTest() OVERRIDE {
90    PostSetNeedsCommitToMainThread();
91  }
92
93  virtual void Animate(base::TimeTicks) OVERRIDE {
94    if (!num_animates_) {
95      layer_tree_host()->SetNeedsAnimate();
96      num_animates_++;
97      return;
98    }
99    EndTest();
100  }
101
102  virtual void AfterTest() OVERRIDE {}
103
104 private:
105  int num_animates_;
106};
107
108MULTI_THREAD_TEST_F(
109    LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback);
110
111// Add a layer animation and confirm that
112// LayerTreeHostImpl::updateAnimationState does get called and continues to
113// get called.
114class LayerTreeHostAnimationTestAddAnimation
115    : public LayerTreeHostAnimationTest {
116 public:
117  LayerTreeHostAnimationTestAddAnimation()
118      : num_animates_(0),
119        received_animation_started_notification_(false) {
120  }
121
122  virtual void BeginTest() OVERRIDE {
123    PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
124  }
125
126  virtual void UpdateAnimationState(
127      LayerTreeHostImpl* host_impl,
128      bool has_unfinished_animation) OVERRIDE {
129    if (!num_animates_) {
130      // The animation had zero duration so LayerTreeHostImpl should no
131      // longer need to animate its layers.
132      EXPECT_FALSE(has_unfinished_animation);
133      num_animates_++;
134      return;
135    }
136
137    if (received_animation_started_notification_) {
138      EXPECT_LT(base::TimeTicks(), start_time_);
139
140      LayerAnimationController* controller_impl =
141          host_impl->active_tree()->root_layer()->layer_animation_controller();
142      Animation* animation_impl =
143          controller_impl->GetAnimation(Animation::Opacity);
144      if (animation_impl)
145        controller_impl->RemoveAnimation(animation_impl->id());
146
147      EndTest();
148    }
149  }
150
151  virtual void NotifyAnimationStarted(
152      double wall_clock_time,
153      base::TimeTicks monotonic_time,
154      Animation::TargetProperty target_property) OVERRIDE {
155    received_animation_started_notification_ = true;
156    start_time_ = monotonic_time;
157    if (num_animates_) {
158      EXPECT_LT(base::TimeTicks(), start_time_);
159
160      LayerAnimationController* controller =
161          layer_tree_host()->root_layer()->layer_animation_controller();
162      Animation* animation =
163          controller->GetAnimation(Animation::Opacity);
164      if (animation)
165        controller->RemoveAnimation(animation->id());
166
167      EndTest();
168    }
169  }
170
171  virtual void AfterTest() OVERRIDE {}
172
173 private:
174  int num_animates_;
175  bool received_animation_started_notification_;
176  base::TimeTicks start_time_;
177};
178
179SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddAnimation);
180
181// Add a layer animation to a layer, but continually fail to draw. Confirm that
182// after a while, we do eventually force a draw.
183class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
184    : public LayerTreeHostAnimationTest {
185 public:
186  LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws()
187      : started_animating_(false) {}
188
189  virtual void BeginTest() OVERRIDE {
190    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
191  }
192
193  virtual void AnimateLayers(
194      LayerTreeHostImpl* host_impl,
195      base::TimeTicks monotonic_time) OVERRIDE {
196    started_animating_ = true;
197  }
198
199  virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
200    if (started_animating_)
201      EndTest();
202  }
203
204  virtual bool PrepareToDrawOnThread(
205      LayerTreeHostImpl* host_impl,
206      LayerTreeHostImpl::FrameData* frame,
207      bool result) OVERRIDE {
208    return false;
209  }
210
211  virtual void AfterTest() OVERRIDE { }
212
213 private:
214  bool started_animating_;
215};
216
217// Starvation can only be an issue with the MT compositor.
218MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws);
219
220// Ensures that animations eventually get deleted.
221class LayerTreeHostAnimationTestAnimationsGetDeleted
222    : public LayerTreeHostAnimationTest {
223 public:
224  LayerTreeHostAnimationTestAnimationsGetDeleted()
225      : started_animating_(false) {}
226
227  virtual void BeginTest() OVERRIDE {
228    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
229  }
230
231  virtual void AnimateLayers(
232      LayerTreeHostImpl* host_impl,
233      base::TimeTicks monotonic_time) OVERRIDE {
234    bool have_animations = !host_impl->animation_registrar()->
235        active_animation_controllers().empty();
236    if (!started_animating_ && have_animations) {
237      started_animating_ = true;
238      return;
239    }
240
241    if (started_animating_ && !have_animations)
242      EndTest();
243  }
244
245  virtual void NotifyAnimationFinished(
246      double wall_clock_time,
247      base::TimeTicks monotonic_time,
248      Animation::TargetProperty target_property) OVERRIDE {
249    // Animations on the impl-side controller only get deleted during a commit,
250    // so we need to schedule a commit.
251    layer_tree_host()->SetNeedsCommit();
252  }
253
254  virtual void AfterTest() OVERRIDE {}
255
256 private:
257  bool started_animating_;
258};
259
260SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);
261
262// Ensures that animations continue to be ticked when we are backgrounded.
263class LayerTreeHostAnimationTestTickAnimationWhileBackgrounded
264    : public LayerTreeHostAnimationTest {
265 public:
266  LayerTreeHostAnimationTestTickAnimationWhileBackgrounded()
267      : num_animates_(0) {}
268
269  virtual void BeginTest() OVERRIDE {
270    PostAddLongAnimationToMainThread(layer_tree_host()->root_layer());
271  }
272
273  // Use WillAnimateLayers to set visible false before the animation runs and
274  // causes a commit, so we block the second visible animate in single-thread
275  // mode.
276  virtual void WillAnimateLayers(
277      LayerTreeHostImpl* host_impl,
278      base::TimeTicks monotonic_time) OVERRIDE {
279    // Verify that the host can draw, it's just not visible.
280    EXPECT_TRUE(host_impl->CanDraw());
281    if (num_animates_ < 2) {
282      if (!num_animates_) {
283        // We have a long animation running. It should continue to tick even
284        // if we are not visible.
285        PostSetVisibleToMainThread(false);
286      }
287      num_animates_++;
288      return;
289    }
290    EndTest();
291  }
292
293  virtual void AfterTest() OVERRIDE {}
294
295 private:
296  int num_animates_;
297};
298
299SINGLE_AND_MULTI_THREAD_TEST_F(
300    LayerTreeHostAnimationTestTickAnimationWhileBackgrounded);
301
302// Ensures that animations do not tick when we are backgrounded and
303// and we have an empty active tree.
304class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree
305    : public LayerTreeHostAnimationTest {
306 protected:
307  LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree()
308      : active_tree_was_animated_(false) {}
309
310  virtual base::TimeDelta LowFrequencyAnimationInterval() const OVERRIDE {
311    return base::TimeDelta::FromMilliseconds(4);
312  }
313
314  virtual void BeginTest() OVERRIDE {
315    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
316  }
317
318  virtual void NotifyAnimationFinished(
319      double wall_clock_time,
320      base::TimeTicks monotonic_time,
321      Animation::TargetProperty target_property) OVERRIDE {
322    // Replace animated commits with an empty tree.
323    layer_tree_host()->SetRootLayer(make_scoped_refptr<Layer>(NULL));
324  }
325
326  virtual void DidCommit() OVERRIDE {
327    // This alternates setting an empty tree and a non-empty tree with an
328    // animation.
329    switch (layer_tree_host()->source_frame_number()) {
330      case 1:
331        // Wait for NotifyAnimationFinished to commit an empty tree.
332        break;
333      case 2:
334        SetupTree();
335        AddOpacityTransitionToLayer(
336            layer_tree_host()->root_layer(), 0.000001, 0, 0.5, true);
337        break;
338      case 3:
339        // Wait for NotifyAnimationFinished to commit an empty tree.
340        break;
341      case 4:
342        EndTest();
343        break;
344    }
345  }
346
347  virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
348    // At the start of every commit, block activations and make sure
349    // we are backgrounded.
350    host_impl->BlockNotifyReadyToActivateForTesting(true);
351    PostSetVisibleToMainThread(false);
352  }
353
354  virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
355    if (!host_impl->settings().impl_side_painting) {
356      // There are no activations to block if we're not impl-side-painting,
357      // so just advance the test immediately.
358      if (host_impl->active_tree()->source_frame_number() < 3)
359        UnblockActivations(host_impl);
360      return;
361    }
362
363    // We block activation for several ticks to make sure that, even though
364    // there is a pending tree with animations, we still do not background
365    // tick if the active tree is empty.
366    if (host_impl->pending_tree()->source_frame_number() < 3) {
367      base::MessageLoopProxy::current()->PostDelayedTask(
368          FROM_HERE,
369          base::Bind(
370              &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree::
371                   UnblockActivations,
372              base::Unretained(this),
373              host_impl),
374          4 * LowFrequencyAnimationInterval());
375    }
376  }
377
378  virtual void UnblockActivations(LayerTreeHostImpl* host_impl) {
379    host_impl->BlockNotifyReadyToActivateForTesting(false);
380  }
381
382  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
383    active_tree_was_animated_ = false;
384
385    // Verify that commits are actually alternating with empty / non-empty
386    // trees.
387    int frame_number = host_impl->active_tree()->source_frame_number();
388    switch (frame_number) {
389      case 0:
390      case 2:
391        EXPECT_TRUE(host_impl->active_tree()->root_layer())
392            << "frame: " << frame_number;
393        break;
394      case 1:
395      case 3:
396        EXPECT_FALSE(host_impl->active_tree()->root_layer())
397            << "frame: " << frame_number;
398        break;
399    }
400
401    if (host_impl->active_tree()->source_frame_number() < 3) {
402      // Initiate the next commit after a delay to give us a chance to
403      // background tick if the active tree isn't empty.
404      base::MessageLoopProxy::current()->PostDelayedTask(
405          FROM_HERE,
406          base::Bind(
407              &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree::
408                   InitiateNextCommit,
409              base::Unretained(this),
410              host_impl),
411          4 * LowFrequencyAnimationInterval());
412    }
413  }
414
415  virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
416                                 base::TimeTicks monotonic_time) OVERRIDE {
417    EXPECT_TRUE(host_impl->active_tree()->root_layer());
418    active_tree_was_animated_ = true;
419  }
420
421  void InitiateNextCommit(LayerTreeHostImpl* host_impl) {
422    // Verify that we actually animated when we should have.
423    bool has_active_tree = host_impl->active_tree()->root_layer();
424    EXPECT_EQ(has_active_tree, active_tree_was_animated_);
425
426    // The next commit is blocked until we become visible again.
427    PostSetVisibleToMainThread(true);
428  }
429
430  virtual void AfterTest() OVERRIDE {}
431
432  bool active_tree_was_animated_;
433};
434
435SINGLE_AND_MULTI_THREAD_TEST_F(
436    LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree);
437
438// Ensure that an animation's timing function is respected.
439class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
440    : public LayerTreeHostAnimationTest {
441 public:
442  LayerTreeHostAnimationTestAddAnimationWithTimingFunction() {}
443
444  virtual void SetupTree() OVERRIDE {
445    LayerTreeHostAnimationTest::SetupTree();
446    content_ = FakeContentLayer::Create(&client_);
447    content_->SetBounds(gfx::Size(4, 4));
448    layer_tree_host()->root_layer()->AddChild(content_);
449  }
450
451  virtual void BeginTest() OVERRIDE {
452    PostAddAnimationToMainThread(content_.get());
453  }
454
455  virtual void AnimateLayers(
456      LayerTreeHostImpl* host_impl,
457      base::TimeTicks monotonic_time) OVERRIDE {
458    LayerAnimationController* controller_impl =
459        host_impl->active_tree()->root_layer()->children()[0]->
460        layer_animation_controller();
461    Animation* animation =
462        controller_impl->GetAnimation(Animation::Opacity);
463    if (!animation)
464      return;
465
466    const FloatAnimationCurve* curve =
467        animation->curve()->ToFloatAnimationCurve();
468    float start_opacity = curve->GetValue(0.0);
469    float end_opacity = curve->GetValue(curve->Duration());
470    float linearly_interpolated_opacity =
471        0.25f * end_opacity + 0.75f * start_opacity;
472    double time = curve->Duration() * 0.25;
473    // If the linear timing function associated with this animation was not
474    // picked up, then the linearly interpolated opacity would be different
475    // because of the default ease timing function.
476    EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time));
477
478    EndTest();
479  }
480
481  virtual void AfterTest() OVERRIDE {}
482
483  FakeContentLayerClient client_;
484  scoped_refptr<FakeContentLayer> content_;
485};
486
487SINGLE_AND_MULTI_THREAD_TEST_F(
488    LayerTreeHostAnimationTestAddAnimationWithTimingFunction);
489
490// Ensures that main thread animations have their start times synchronized with
491// impl thread animations.
492class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
493    : public LayerTreeHostAnimationTest {
494 public:
495  LayerTreeHostAnimationTestSynchronizeAnimationStartTimes()
496      : main_start_time_(-1.0),
497        impl_start_time_(-1.0) {}
498
499  virtual void SetupTree() OVERRIDE {
500    LayerTreeHostAnimationTest::SetupTree();
501    content_ = FakeContentLayer::Create(&client_);
502    content_->SetBounds(gfx::Size(4, 4));
503    content_->set_layer_animation_delegate(this);
504    layer_tree_host()->root_layer()->AddChild(content_);
505  }
506
507  virtual void BeginTest() OVERRIDE {
508    PostAddAnimationToMainThread(content_.get());
509  }
510
511  virtual void NotifyAnimationStarted(
512      double wall_clock_time,
513      base::TimeTicks monotonic_time,
514      Animation::TargetProperty target_property) OVERRIDE {
515    LayerAnimationController* controller =
516        layer_tree_host()->root_layer()->children()[0]->
517        layer_animation_controller();
518    Animation* animation =
519        controller->GetAnimation(Animation::Opacity);
520    main_start_time_ = animation->start_time();
521    controller->RemoveAnimation(animation->id());
522
523    if (impl_start_time_ > 0.0)
524      EndTest();
525  }
526
527  virtual void UpdateAnimationState(
528      LayerTreeHostImpl* impl_host,
529      bool has_unfinished_animation) OVERRIDE {
530    LayerAnimationController* controller =
531        impl_host->active_tree()->root_layer()->children()[0]->
532        layer_animation_controller();
533    Animation* animation =
534        controller->GetAnimation(Animation::Opacity);
535    if (!animation)
536      return;
537
538    impl_start_time_ = animation->start_time();
539    controller->RemoveAnimation(animation->id());
540
541    if (main_start_time_ > 0.0)
542      EndTest();
543  }
544
545  virtual void AfterTest() OVERRIDE {
546    EXPECT_FLOAT_EQ(impl_start_time_, main_start_time_);
547  }
548
549 private:
550  double main_start_time_;
551  double impl_start_time_;
552  FakeContentLayerClient client_;
553  scoped_refptr<FakeContentLayer> content_;
554};
555
556SINGLE_AND_MULTI_THREAD_TEST_F(
557    LayerTreeHostAnimationTestSynchronizeAnimationStartTimes);
558
559// Ensures that notify animation finished is called.
560class LayerTreeHostAnimationTestAnimationFinishedEvents
561    : public LayerTreeHostAnimationTest {
562 public:
563  LayerTreeHostAnimationTestAnimationFinishedEvents() {}
564
565  virtual void BeginTest() OVERRIDE {
566    PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
567  }
568
569  virtual void NotifyAnimationFinished(
570      double wall_clock_time,
571      base::TimeTicks monotonic_time,
572      Animation::TargetProperty target_property) OVERRIDE {
573    LayerAnimationController* controller =
574        layer_tree_host()->root_layer()->layer_animation_controller();
575    Animation* animation =
576        controller->GetAnimation(Animation::Opacity);
577    if (animation)
578      controller->RemoveAnimation(animation->id());
579    EndTest();
580  }
581
582  virtual void AfterTest() OVERRIDE {}
583};
584
585SINGLE_AND_MULTI_THREAD_TEST_F(
586    LayerTreeHostAnimationTestAnimationFinishedEvents);
587
588// Ensures that when opacity is being animated, this value does not cause the
589// subtree to be skipped.
590class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity
591    : public LayerTreeHostAnimationTest {
592 public:
593  LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity()
594      : update_check_layer_(FakeContentLayer::Create(&client_)) {
595  }
596
597  virtual void SetupTree() OVERRIDE {
598    update_check_layer_->SetOpacity(0.f);
599    layer_tree_host()->SetRootLayer(update_check_layer_);
600    LayerTreeHostAnimationTest::SetupTree();
601  }
602
603  virtual void BeginTest() OVERRIDE {
604    PostAddAnimationToMainThread(update_check_layer_.get());
605  }
606
607  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
608    LayerAnimationController* controller_impl =
609        host_impl->active_tree()->root_layer()->layer_animation_controller();
610    Animation* animation_impl =
611        controller_impl->GetAnimation(Animation::Opacity);
612    controller_impl->RemoveAnimation(animation_impl->id());
613    EndTest();
614  }
615
616  virtual void AfterTest() OVERRIDE {
617    // Update() should have been called once, proving that the layer was not
618    // skipped.
619    EXPECT_EQ(1u, update_check_layer_->update_count());
620
621    // clear update_check_layer_ so LayerTreeHost dies.
622    update_check_layer_ = NULL;
623  }
624
625 private:
626  FakeContentLayerClient client_;
627  scoped_refptr<FakeContentLayer> update_check_layer_;
628};
629
630SINGLE_AND_MULTI_THREAD_TEST_F(
631    LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity);
632
633// Layers added to tree with existing active animations should have the
634// animation correctly recognized.
635class LayerTreeHostAnimationTestLayerAddedWithAnimation
636    : public LayerTreeHostAnimationTest {
637 public:
638  LayerTreeHostAnimationTestLayerAddedWithAnimation() {}
639
640  virtual void BeginTest() OVERRIDE {
641    PostSetNeedsCommitToMainThread();
642  }
643
644  virtual void DidCommit() OVERRIDE {
645    if (layer_tree_host()->source_frame_number() == 1) {
646      scoped_refptr<Layer> layer = Layer::Create();
647      layer->set_layer_animation_delegate(this);
648
649      // Any valid AnimationCurve will do here.
650      scoped_ptr<AnimationCurve> curve(EaseTimingFunction::Create());
651      scoped_ptr<Animation> animation(
652          Animation::Create(curve.Pass(), 1, 1,
653                                  Animation::Opacity));
654      layer->layer_animation_controller()->AddAnimation(animation.Pass());
655
656      // We add the animation *before* attaching the layer to the tree.
657      layer_tree_host()->root_layer()->AddChild(layer);
658    }
659  }
660
661  virtual void AnimateLayers(
662      LayerTreeHostImpl* impl_host,
663      base::TimeTicks monotonic_time) OVERRIDE {
664    EndTest();
665  }
666
667  virtual void AfterTest() OVERRIDE {}
668};
669
670SINGLE_AND_MULTI_THREAD_TEST_F(
671    LayerTreeHostAnimationTestLayerAddedWithAnimation);
672
673class LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount
674    : public LayerTreeHostAnimationTest {
675 public:
676  LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount()
677      : animated_commit_(-1) {
678  }
679
680  virtual void Animate(base::TimeTicks) OVERRIDE {
681    // We shouldn't animate on the CompositeAndReadback-forced commit, but we
682    // should for the SetNeedsCommit-triggered commit.
683    animated_commit_ = layer_tree_host()->source_frame_number();
684    EXPECT_NE(2, animated_commit_);
685  }
686
687  virtual void BeginTest() OVERRIDE {
688    PostSetNeedsCommitToMainThread();
689  }
690
691  virtual void DidCommit() OVERRIDE {
692    switch (layer_tree_host()->source_frame_number()) {
693      case 1:
694        layer_tree_host()->SetNeedsCommit();
695        break;
696      case 2: {
697        char pixels[4];
698        layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
699        break;
700      }
701      case 3:
702        // This is finishing the readback's commit.
703        break;
704      case 4:
705        // This is finishing the followup commit.
706        EndTest();
707        break;
708      default:
709        NOTREACHED();
710    }
711  }
712
713  virtual void AfterTest() OVERRIDE {
714    EXPECT_EQ(3, animated_commit_);
715  }
716
717 private:
718  int animated_commit_;
719};
720
721MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount);
722
723class LayerTreeHostAnimationTestContinuousAnimate
724    : public LayerTreeHostAnimationTest {
725 public:
726  LayerTreeHostAnimationTestContinuousAnimate()
727      : num_commit_complete_(0),
728        num_draw_layers_(0) {
729  }
730
731  virtual void BeginTest() OVERRIDE {
732    PostSetNeedsCommitToMainThread();
733  }
734
735  virtual void Animate(base::TimeTicks) OVERRIDE {
736    if (num_draw_layers_ == 2)
737      return;
738    layer_tree_host()->SetNeedsAnimate();
739  }
740
741  virtual void Layout() OVERRIDE {
742    layer_tree_host()->root_layer()->SetNeedsDisplay();
743  }
744
745  virtual void CommitCompleteOnThread(LayerTreeHostImpl* tree_impl) OVERRIDE {
746    if (num_draw_layers_ == 1)
747      num_commit_complete_++;
748  }
749
750  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
751    num_draw_layers_++;
752    if (num_draw_layers_ == 2)
753      EndTest();
754  }
755
756  virtual void AfterTest() OVERRIDE {
757    // Check that we didn't commit twice between first and second draw.
758    EXPECT_EQ(1, num_commit_complete_);
759  }
760
761 private:
762  int num_commit_complete_;
763  int num_draw_layers_;
764};
765
766MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestContinuousAnimate);
767
768// Make sure the main thread can still execute animations when CanDraw() is not
769// true.
770class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
771    : public LayerTreeHostAnimationTest {
772 public:
773  LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw() : started_times_(0) {}
774
775  virtual void SetupTree() OVERRIDE {
776    LayerTreeHostAnimationTest::SetupTree();
777    content_ = FakeContentLayer::Create(&client_);
778    content_->SetBounds(gfx::Size(4, 4));
779    content_->set_layer_animation_delegate(this);
780    layer_tree_host()->root_layer()->AddChild(content_);
781  }
782
783  virtual void BeginTest() OVERRIDE {
784    layer_tree_host()->SetViewportSize(gfx::Size());
785    PostAddAnimationToMainThread(content_.get());
786  }
787
788  virtual void NotifyAnimationStarted(
789      double wall_clock_time,
790      base::TimeTicks monotonic_time,
791      Animation::TargetProperty target_property) OVERRIDE {
792    started_times_++;
793  }
794
795  virtual void NotifyAnimationFinished(
796      double wall_clock_time,
797      base::TimeTicks monotonic_time,
798      Animation::TargetProperty target_property) OVERRIDE {
799    EndTest();
800  }
801
802  virtual void AfterTest() OVERRIDE {
803    EXPECT_EQ(1, started_times_);
804  }
805
806 private:
807  int started_times_;
808  FakeContentLayerClient client_;
809  scoped_refptr<FakeContentLayer> content_;
810};
811
812SINGLE_AND_MULTI_THREAD_TEST_F(
813    LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw);
814
815// Make sure the main thread can still execute animations when the renderer is
816// backgrounded.
817class LayerTreeHostAnimationTestRunAnimationWhenNotVisible
818    : public LayerTreeHostAnimationTest {
819 public:
820  LayerTreeHostAnimationTestRunAnimationWhenNotVisible() : started_times_(0) {}
821
822  virtual void SetupTree() OVERRIDE {
823    LayerTreeHostAnimationTest::SetupTree();
824    content_ = FakeContentLayer::Create(&client_);
825    content_->SetBounds(gfx::Size(4, 4));
826    content_->set_layer_animation_delegate(this);
827    layer_tree_host()->root_layer()->AddChild(content_);
828  }
829
830  virtual void BeginTest() OVERRIDE {
831    visible_ = true;
832    PostAddAnimationToMainThread(content_.get());
833  }
834
835  virtual void DidCommit() OVERRIDE {
836    visible_ = false;
837    layer_tree_host()->SetVisible(false);
838  }
839
840  virtual void NotifyAnimationStarted(
841      double wall_clock_time,
842      base::TimeTicks monotonic_time,
843      Animation::TargetProperty target_property) OVERRIDE {
844    EXPECT_FALSE(visible_);
845    started_times_++;
846  }
847
848  virtual void NotifyAnimationFinished(
849      double wall_clock_time,
850      base::TimeTicks monotonic_time,
851      Animation::TargetProperty target_property) OVERRIDE {
852    EXPECT_FALSE(visible_);
853    EXPECT_EQ(1, started_times_);
854    EndTest();
855  }
856
857  virtual void AfterTest() OVERRIDE {}
858
859 private:
860  bool visible_;
861  int started_times_;
862  FakeContentLayerClient client_;
863  scoped_refptr<FakeContentLayer> content_;
864};
865
866SINGLE_AND_MULTI_THREAD_TEST_F(
867    LayerTreeHostAnimationTestRunAnimationWhenNotVisible);
868
869// Animations should not be started when frames are being skipped due to
870// checkerboard.
871class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
872    : public LayerTreeHostAnimationTest {
873  virtual void SetupTree() OVERRIDE {
874    LayerTreeHostAnimationTest::SetupTree();
875    content_ = FakeContentLayer::Create(&client_);
876    content_->SetBounds(gfx::Size(4, 4));
877    content_->set_layer_animation_delegate(this);
878    layer_tree_host()->root_layer()->AddChild(content_);
879  }
880
881  virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
882    // Make sure that drawing many times doesn't cause a checkerboarded
883    // animation to start so we avoid flake in this test.
884    settings->timeout_and_draw_when_animation_checkerboards = false;
885  }
886
887  virtual void BeginTest() OVERRIDE {
888    prevented_draw_ = 0;
889    added_animations_ = 0;
890    started_times_ = 0;
891    finished_times_ = 0;
892
893    PostSetNeedsCommitToMainThread();
894  }
895
896  virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
897                                     LayerTreeHostImpl::FrameData* frame_data,
898                                     bool result) OVERRIDE {
899    if (added_animations_ < 2)
900      return result;
901    if (TestEnded())
902      return result;
903    // Act like there is checkerboard when the second animation wants to draw.
904    ++prevented_draw_;
905    return false;
906  }
907
908  virtual void DidCommitAndDrawFrame() OVERRIDE {
909    switch (layer_tree_host()->source_frame_number()) {
910      case 1:
911        // The animation is longer than 1 BeginFrame interval.
912        AddOpacityTransitionToLayer(content_.get(), 0.1, 0.2f, 0.8f, false);
913        added_animations_++;
914        break;
915      case 2:
916        // This second animation will not be drawn so it should not start.
917        AddAnimatedTransformToLayer(content_.get(), 0.1, 5, 5);
918        added_animations_++;
919        break;
920    }
921  }
922
923  virtual void NotifyAnimationStarted(
924      double wall_clock_time,
925      base::TimeTicks monotonic_time,
926      Animation::TargetProperty target_property) OVERRIDE {
927    if (TestEnded())
928      return;
929    started_times_++;
930  }
931
932  virtual void NotifyAnimationFinished(
933      double wall_clock_time,
934      base::TimeTicks monotonic_time,
935      Animation::TargetProperty target_property) OVERRIDE {
936    // We should be checkerboarding already, but it should still finish the
937    // first animation.
938    EXPECT_EQ(2, added_animations_);
939    finished_times_++;
940    EndTest();
941  }
942
943  virtual void AfterTest() OVERRIDE {
944    // Make sure we tried to draw the second animation but failed.
945    EXPECT_LT(0, prevented_draw_);
946    // The first animation should be started, but the second should not because
947    // of checkerboard.
948    EXPECT_EQ(1, started_times_);
949    // The first animation should still be finished.
950    EXPECT_EQ(1, finished_times_);
951  }
952
953  int prevented_draw_;
954  int added_animations_;
955  int started_times_;
956  int finished_times_;
957  FakeContentLayerClient client_;
958  scoped_refptr<FakeContentLayer> content_;
959};
960
961MULTI_THREAD_TEST_F(
962    LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);
963
964// Verifies that when scroll offset is animated on the impl thread, updates
965// are sent back to the main thread.
966class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
967    : public LayerTreeHostAnimationTest {
968 public:
969  LayerTreeHostAnimationTestScrollOffsetChangesArePropagated() {}
970
971  virtual void SetupTree() OVERRIDE {
972    LayerTreeHostAnimationTest::SetupTree();
973
974    scroll_layer_ = FakeContentLayer::Create(&client_);
975    scroll_layer_->SetScrollable(true);
976    scroll_layer_->SetBounds(gfx::Size(1000, 1000));
977    scroll_layer_->SetScrollOffset(gfx::Vector2d(10, 20));
978    layer_tree_host()->root_layer()->AddChild(scroll_layer_);
979  }
980
981  virtual void BeginTest() OVERRIDE {
982    PostSetNeedsCommitToMainThread();
983  }
984
985  virtual void DidCommit() OVERRIDE {
986    switch (layer_tree_host()->source_frame_number()) {
987      case 1: {
988        scoped_ptr<ScrollOffsetAnimationCurve> curve(
989            ScrollOffsetAnimationCurve::Create(
990                gfx::Vector2dF(500.f, 550.f),
991                EaseInOutTimingFunction::Create()));
992        scoped_ptr<Animation> animation(Animation::Create(
993            curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
994        animation->set_needs_synchronized_start_time(true);
995        scroll_layer_->AddAnimation(animation.Pass());
996        break;
997      }
998      default:
999        if (scroll_layer_->scroll_offset().x() > 10 &&
1000            scroll_layer_->scroll_offset().y() > 20)
1001          EndTest();
1002    }
1003  }
1004
1005  virtual void AfterTest() OVERRIDE {}
1006
1007 private:
1008  FakeContentLayerClient client_;
1009  scoped_refptr<FakeContentLayer> scroll_layer_;
1010};
1011
1012// SingleThreadProxy doesn't send scroll updates from LayerTreeHostImpl to
1013// LayerTreeHost.
1014MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);
1015
1016}  // namespace
1017}  // namespace cc
1018