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/timing_function.h"
10#include "cc/layers/layer.h"
11#include "cc/layers/layer_impl.h"
12#include "cc/test/animation_test_common.h"
13#include "cc/test/fake_content_layer.h"
14#include "cc/test/fake_content_layer_client.h"
15#include "cc/test/layer_tree_test.h"
16#include "cc/trees/layer_tree_impl.h"
17
18namespace cc {
19namespace {
20
21class LayerTreeHostAnimationTest : public LayerTreeTest {
22 public:
23  virtual void SetupTree() OVERRIDE {
24    LayerTreeTest::SetupTree();
25    layer_tree_host()->root_layer()->set_layer_animation_delegate(this);
26  }
27};
28
29// Makes sure that SetNeedsAnimate does not cause the CommitRequested() state to
30// be set.
31class LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested
32    : public LayerTreeHostAnimationTest {
33 public:
34  LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested()
35      : num_commits_(0) {}
36
37  virtual void BeginTest() OVERRIDE {
38    PostSetNeedsCommitToMainThread();
39  }
40
41  virtual void Animate(base::TimeTicks monotonic_time) OVERRIDE {
42    // We skip the first commit becasue its the commit that populates the
43    // impl thread with a tree. After the second commit, the test is done.
44    if (num_commits_ != 1)
45      return;
46
47    layer_tree_host()->SetNeedsAnimate();
48    // Right now, CommitRequested is going to be true, because during
49    // BeginFrame, we force CommitRequested to true to prevent requests from
50    // hitting the impl thread. But, when the next DidCommit happens, we should
51    // verify that CommitRequested has gone back to false.
52  }
53
54  virtual void DidCommit() OVERRIDE {
55    if (!num_commits_) {
56      EXPECT_FALSE(layer_tree_host()->CommitRequested());
57      layer_tree_host()->SetNeedsAnimate();
58      EXPECT_FALSE(layer_tree_host()->CommitRequested());
59    }
60
61    // Verifies that the SetNeedsAnimate we made in ::Animate did not
62    // trigger CommitRequested.
63    EXPECT_FALSE(layer_tree_host()->CommitRequested());
64    EndTest();
65    num_commits_++;
66  }
67
68  virtual void AfterTest() OVERRIDE {}
69
70 private:
71  int num_commits_;
72};
73
74MULTI_THREAD_TEST_F(
75    LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested);
76
77// Trigger a frame with SetNeedsCommit. Then, inside the resulting animate
78// callback, request another frame using SetNeedsAnimate. End the test when
79// animate gets called yet-again, indicating that the proxy is correctly
80// handling the case where SetNeedsAnimate() is called inside the BeginFrame
81// flow.
82class LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback
83    : public LayerTreeHostAnimationTest {
84 public:
85  LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback()
86      : num_animates_(0) {}
87
88  virtual void BeginTest() OVERRIDE {
89    PostSetNeedsCommitToMainThread();
90  }
91
92  virtual void Animate(base::TimeTicks) OVERRIDE {
93    if (!num_animates_) {
94      layer_tree_host()->SetNeedsAnimate();
95      num_animates_++;
96      return;
97    }
98    EndTest();
99  }
100
101  virtual void AfterTest() OVERRIDE {}
102
103 private:
104  int num_animates_;
105};
106
107MULTI_THREAD_TEST_F(
108    LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback);
109
110// Add a layer animation and confirm that
111// LayerTreeHostImpl::updateAnimationState does get called and continues to
112// get called.
113class LayerTreeHostAnimationTestAddAnimation
114    : public LayerTreeHostAnimationTest {
115 public:
116  LayerTreeHostAnimationTestAddAnimation()
117      : num_animates_(0),
118        received_animation_started_notification_(false),
119        start_time_(0.0) {
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(0.0, 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(double wall_clock_time) OVERRIDE {
152    received_animation_started_notification_ = true;
153    start_time_ = wall_clock_time;
154    if (num_animates_) {
155      EXPECT_LT(0.0, start_time_);
156
157      LayerAnimationController* controller =
158          layer_tree_host()->root_layer()->layer_animation_controller();
159      Animation* animation =
160          controller->GetAnimation(Animation::Opacity);
161      if (animation)
162        controller->RemoveAnimation(animation->id());
163
164      EndTest();
165    }
166  }
167
168  virtual void AfterTest() OVERRIDE {}
169
170 private:
171  int num_animates_;
172  bool received_animation_started_notification_;
173  double start_time_;
174};
175
176SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddAnimation);
177
178// Add a layer animation to a layer, but continually fail to draw. Confirm that
179// after a while, we do eventually force a draw.
180class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
181    : public LayerTreeHostAnimationTest {
182 public:
183  LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws()
184      : started_animating_(false) {}
185
186  virtual void BeginTest() OVERRIDE {
187    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
188  }
189
190  virtual void AnimateLayers(
191      LayerTreeHostImpl* host_impl,
192      base::TimeTicks monotonic_time) OVERRIDE {
193    started_animating_ = true;
194  }
195
196  virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
197    if (started_animating_)
198      EndTest();
199  }
200
201  virtual bool PrepareToDrawOnThread(
202      LayerTreeHostImpl* host_impl,
203      LayerTreeHostImpl::FrameData* frame,
204      bool result) OVERRIDE {
205    return false;
206  }
207
208  virtual void AfterTest() OVERRIDE { }
209
210 private:
211  bool started_animating_;
212};
213
214// Starvation can only be an issue with the MT compositor.
215MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws);
216
217// Ensures that animations eventually get deleted.
218class LayerTreeHostAnimationTestAnimationsGetDeleted
219    : public LayerTreeHostAnimationTest {
220 public:
221  LayerTreeHostAnimationTestAnimationsGetDeleted()
222      : started_animating_(false) {}
223
224  virtual void BeginTest() OVERRIDE {
225    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
226  }
227
228  virtual void AnimateLayers(
229      LayerTreeHostImpl* host_impl,
230      base::TimeTicks monotonic_time) OVERRIDE {
231    bool have_animations = !host_impl->animation_registrar()->
232        active_animation_controllers().empty();
233    if (!started_animating_ && have_animations) {
234      started_animating_ = true;
235      return;
236    }
237
238    if (started_animating_ && !have_animations)
239      EndTest();
240  }
241
242  virtual void NotifyAnimationFinished(double time) OVERRIDE {
243    // Animations on the impl-side controller only get deleted during a commit,
244    // so we need to schedule a commit.
245    layer_tree_host()->SetNeedsCommit();
246  }
247
248  virtual void AfterTest() OVERRIDE {}
249
250 private:
251  bool started_animating_;
252};
253
254SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);
255
256// Ensures that animations continue to be ticked when we are backgrounded.
257class LayerTreeHostAnimationTestTickAnimationWhileBackgrounded
258    : public LayerTreeHostAnimationTest {
259 public:
260  LayerTreeHostAnimationTestTickAnimationWhileBackgrounded()
261      : num_animates_(0) {}
262
263  virtual void BeginTest() OVERRIDE {
264    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
265  }
266
267  // Use WillAnimateLayers to set visible false before the animation runs and
268  // causes a commit, so we block the second visible animate in single-thread
269  // mode.
270  virtual void WillAnimateLayers(
271      LayerTreeHostImpl* host_impl,
272      base::TimeTicks monotonic_time) OVERRIDE {
273    // Verify that the host can draw, it's just not visible.
274    EXPECT_TRUE(host_impl->CanDraw());
275    if (num_animates_ < 2) {
276      if (!num_animates_) {
277        // We have a long animation running. It should continue to tick even
278        // if we are not visible.
279        PostSetVisibleToMainThread(false);
280      }
281      num_animates_++;
282      return;
283    }
284    EndTest();
285  }
286
287  virtual void AfterTest() OVERRIDE {}
288
289 private:
290  int num_animates_;
291};
292
293SINGLE_AND_MULTI_THREAD_TEST_F(
294    LayerTreeHostAnimationTestTickAnimationWhileBackgrounded);
295
296// Ensure that an animation's timing function is respected.
297class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
298    : public LayerTreeHostAnimationTest {
299 public:
300  LayerTreeHostAnimationTestAddAnimationWithTimingFunction() {}
301
302  virtual void SetupTree() OVERRIDE {
303    LayerTreeHostAnimationTest::SetupTree();
304    content_ = FakeContentLayer::Create(&client_);
305    content_->SetBounds(gfx::Size(4, 4));
306    layer_tree_host()->root_layer()->AddChild(content_);
307  }
308
309  virtual void BeginTest() OVERRIDE {
310    PostAddAnimationToMainThread(content_.get());
311  }
312
313  virtual void AnimateLayers(
314      LayerTreeHostImpl* host_impl,
315      base::TimeTicks monotonic_time) OVERRIDE {
316    LayerAnimationController* controller_impl =
317        host_impl->active_tree()->root_layer()->children()[0]->
318        layer_animation_controller();
319    Animation* animation =
320        controller_impl->GetAnimation(Animation::Opacity);
321    if (!animation)
322      return;
323
324    const FloatAnimationCurve* curve =
325        animation->curve()->ToFloatAnimationCurve();
326    float start_opacity = curve->GetValue(0.0);
327    float end_opacity = curve->GetValue(curve->Duration());
328    float linearly_interpolated_opacity =
329        0.25f * end_opacity + 0.75f * start_opacity;
330    double time = curve->Duration() * 0.25;
331    // If the linear timing function associated with this animation was not
332    // picked up, then the linearly interpolated opacity would be different
333    // because of the default ease timing function.
334    EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time));
335
336    EndTest();
337  }
338
339  virtual void AfterTest() OVERRIDE {}
340
341  FakeContentLayerClient client_;
342  scoped_refptr<FakeContentLayer> content_;
343};
344
345SINGLE_AND_MULTI_THREAD_TEST_F(
346    LayerTreeHostAnimationTestAddAnimationWithTimingFunction);
347
348// Ensures that main thread animations have their start times synchronized with
349// impl thread animations.
350class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
351    : public LayerTreeHostAnimationTest {
352 public:
353  LayerTreeHostAnimationTestSynchronizeAnimationStartTimes()
354      : main_start_time_(-1.0),
355        impl_start_time_(-1.0) {}
356
357  virtual void SetupTree() OVERRIDE {
358    LayerTreeHostAnimationTest::SetupTree();
359    content_ = FakeContentLayer::Create(&client_);
360    content_->SetBounds(gfx::Size(4, 4));
361    content_->set_layer_animation_delegate(this);
362    layer_tree_host()->root_layer()->AddChild(content_);
363  }
364
365  virtual void BeginTest() OVERRIDE {
366    PostAddAnimationToMainThread(content_.get());
367  }
368
369  virtual void NotifyAnimationStarted(double time) OVERRIDE {
370    LayerAnimationController* controller =
371        layer_tree_host()->root_layer()->children()[0]->
372        layer_animation_controller();
373    Animation* animation =
374        controller->GetAnimation(Animation::Opacity);
375    main_start_time_ = animation->start_time();
376    controller->RemoveAnimation(animation->id());
377
378    if (impl_start_time_ > 0.0)
379      EndTest();
380  }
381
382  virtual void UpdateAnimationState(
383      LayerTreeHostImpl* impl_host,
384      bool has_unfinished_animation) OVERRIDE {
385    LayerAnimationController* controller =
386        impl_host->active_tree()->root_layer()->children()[0]->
387        layer_animation_controller();
388    Animation* animation =
389        controller->GetAnimation(Animation::Opacity);
390    if (!animation)
391      return;
392
393    impl_start_time_ = animation->start_time();
394    controller->RemoveAnimation(animation->id());
395
396    if (main_start_time_ > 0.0)
397      EndTest();
398  }
399
400  virtual void AfterTest() OVERRIDE {
401    EXPECT_FLOAT_EQ(impl_start_time_, main_start_time_);
402  }
403
404 private:
405  double main_start_time_;
406  double impl_start_time_;
407  FakeContentLayerClient client_;
408  scoped_refptr<FakeContentLayer> content_;
409};
410
411SINGLE_AND_MULTI_THREAD_TEST_F(
412    LayerTreeHostAnimationTestSynchronizeAnimationStartTimes);
413
414// Ensures that notify animation finished is called.
415class LayerTreeHostAnimationTestAnimationFinishedEvents
416    : public LayerTreeHostAnimationTest {
417 public:
418  LayerTreeHostAnimationTestAnimationFinishedEvents() {}
419
420  virtual void BeginTest() OVERRIDE {
421    PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
422  }
423
424  virtual void NotifyAnimationFinished(double time) OVERRIDE {
425    LayerAnimationController* controller =
426        layer_tree_host()->root_layer()->layer_animation_controller();
427    Animation* animation =
428        controller->GetAnimation(Animation::Opacity);
429    if (animation)
430      controller->RemoveAnimation(animation->id());
431    EndTest();
432  }
433
434  virtual void AfterTest() OVERRIDE {}
435};
436
437SINGLE_AND_MULTI_THREAD_TEST_F(
438    LayerTreeHostAnimationTestAnimationFinishedEvents);
439
440// Ensures that when opacity is being animated, this value does not cause the
441// subtree to be skipped.
442class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity
443    : public LayerTreeHostAnimationTest {
444 public:
445  LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity()
446      : update_check_layer_(FakeContentLayer::Create(&client_)) {
447  }
448
449  virtual void SetupTree() OVERRIDE {
450    update_check_layer_->SetOpacity(0.f);
451    layer_tree_host()->SetRootLayer(update_check_layer_);
452    LayerTreeHostAnimationTest::SetupTree();
453  }
454
455  virtual void BeginTest() OVERRIDE {
456    PostAddAnimationToMainThread(update_check_layer_.get());
457  }
458
459  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
460    LayerAnimationController* controller_impl =
461        host_impl->active_tree()->root_layer()->layer_animation_controller();
462    Animation* animation_impl =
463        controller_impl->GetAnimation(Animation::Opacity);
464    controller_impl->RemoveAnimation(animation_impl->id());
465    EndTest();
466  }
467
468  virtual void AfterTest() OVERRIDE {
469    // Update() should have been called once, proving that the layer was not
470    // skipped.
471    EXPECT_EQ(1u, update_check_layer_->update_count());
472
473    // clear update_check_layer_ so LayerTreeHost dies.
474    update_check_layer_ = NULL;
475  }
476
477 private:
478  FakeContentLayerClient client_;
479  scoped_refptr<FakeContentLayer> update_check_layer_;
480};
481
482SINGLE_AND_MULTI_THREAD_TEST_F(
483    LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity);
484
485// Layers added to tree with existing active animations should have the
486// animation correctly recognized.
487class LayerTreeHostAnimationTestLayerAddedWithAnimation
488    : public LayerTreeHostAnimationTest {
489 public:
490  LayerTreeHostAnimationTestLayerAddedWithAnimation() {}
491
492  virtual void BeginTest() OVERRIDE {
493    PostSetNeedsCommitToMainThread();
494  }
495
496  virtual void DidCommit() OVERRIDE {
497    if (layer_tree_host()->source_frame_number() == 1) {
498      scoped_refptr<Layer> layer = Layer::Create();
499      layer->set_layer_animation_delegate(this);
500
501      // Any valid AnimationCurve will do here.
502      scoped_ptr<AnimationCurve> curve(EaseTimingFunction::Create());
503      scoped_ptr<Animation> animation(
504          Animation::Create(curve.Pass(), 1, 1,
505                                  Animation::Opacity));
506      layer->layer_animation_controller()->AddAnimation(animation.Pass());
507
508      // We add the animation *before* attaching the layer to the tree.
509      layer_tree_host()->root_layer()->AddChild(layer);
510    }
511  }
512
513  virtual void AnimateLayers(
514      LayerTreeHostImpl* impl_host,
515      base::TimeTicks monotonic_time) OVERRIDE {
516    EndTest();
517  }
518
519  virtual void AfterTest() OVERRIDE {}
520};
521
522SINGLE_AND_MULTI_THREAD_TEST_F(
523    LayerTreeHostAnimationTestLayerAddedWithAnimation);
524
525class LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount
526    : public LayerTreeHostAnimationTest {
527 public:
528  LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount()
529      : animated_commit_(-1) {
530  }
531
532  virtual void Animate(base::TimeTicks) OVERRIDE {
533    // We shouldn't animate on the CompositeAndReadback-forced commit, but we
534    // should for the SetNeedsCommit-triggered commit.
535    animated_commit_ = layer_tree_host()->source_frame_number();
536    EXPECT_NE(2, animated_commit_);
537  }
538
539  virtual void BeginTest() OVERRIDE {
540    PostSetNeedsCommitToMainThread();
541  }
542
543  virtual void DidCommit() OVERRIDE {
544    switch (layer_tree_host()->source_frame_number()) {
545      case 1:
546        layer_tree_host()->SetNeedsCommit();
547        break;
548      case 2: {
549        char pixels[4];
550        layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
551        break;
552      }
553      case 3:
554        // This is finishing the readback's commit.
555        break;
556      case 4:
557        // This is finishing the followup commit.
558        EndTest();
559        break;
560      default:
561        NOTREACHED();
562    }
563  }
564
565  virtual void AfterTest() OVERRIDE {
566    EXPECT_EQ(3, animated_commit_);
567  }
568
569 private:
570  int animated_commit_;
571};
572
573MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCompositeAndReadbackAnimateCount);
574
575class LayerTreeHostAnimationTestContinuousAnimate
576    : public LayerTreeHostAnimationTest {
577 public:
578  LayerTreeHostAnimationTestContinuousAnimate()
579      : num_commit_complete_(0),
580        num_draw_layers_(0) {
581  }
582
583  virtual void BeginTest() OVERRIDE {
584    PostSetNeedsCommitToMainThread();
585  }
586
587  virtual void Animate(base::TimeTicks) OVERRIDE {
588    if (num_draw_layers_ == 2)
589      return;
590    layer_tree_host()->SetNeedsAnimate();
591  }
592
593  virtual void Layout() OVERRIDE {
594    layer_tree_host()->root_layer()->SetNeedsDisplay();
595  }
596
597  virtual void CommitCompleteOnThread(LayerTreeHostImpl* tree_impl) OVERRIDE {
598    if (num_draw_layers_ == 1)
599      num_commit_complete_++;
600  }
601
602  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
603    num_draw_layers_++;
604    if (num_draw_layers_ == 2)
605      EndTest();
606  }
607
608  virtual void AfterTest() OVERRIDE {
609    // Check that we didn't commit twice between first and second draw.
610    EXPECT_EQ(1, num_commit_complete_);
611  }
612
613 private:
614  int num_commit_complete_;
615  int num_draw_layers_;
616};
617
618MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestContinuousAnimate);
619
620// Make sure the main thread can still execute animations when CanDraw() is not
621// true.
622class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
623    : public LayerTreeHostAnimationTest {
624 public:
625  LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw() : started_times_(0) {}
626
627  virtual void SetupTree() OVERRIDE {
628    LayerTreeHostAnimationTest::SetupTree();
629    content_ = FakeContentLayer::Create(&client_);
630    content_->SetBounds(gfx::Size(4, 4));
631    content_->set_layer_animation_delegate(this);
632    layer_tree_host()->root_layer()->AddChild(content_);
633  }
634
635  virtual void BeginTest() OVERRIDE {
636    layer_tree_host()->SetViewportSize(gfx::Size());
637    PostAddAnimationToMainThread(content_.get());
638  }
639
640  virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
641    started_times_++;
642  }
643
644  virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
645    EndTest();
646  }
647
648  virtual void AfterTest() OVERRIDE {
649    EXPECT_EQ(1, started_times_);
650  }
651
652 private:
653  int started_times_;
654  FakeContentLayerClient client_;
655  scoped_refptr<FakeContentLayer> content_;
656};
657
658SINGLE_AND_MULTI_THREAD_TEST_F(
659    LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw);
660
661// Make sure the main thread can still execute animations when the renderer is
662// backgrounded.
663class LayerTreeHostAnimationTestRunAnimationWhenNotVisible
664    : public LayerTreeHostAnimationTest {
665 public:
666  LayerTreeHostAnimationTestRunAnimationWhenNotVisible() : started_times_(0) {}
667
668  virtual void SetupTree() OVERRIDE {
669    LayerTreeHostAnimationTest::SetupTree();
670    content_ = FakeContentLayer::Create(&client_);
671    content_->SetBounds(gfx::Size(4, 4));
672    content_->set_layer_animation_delegate(this);
673    layer_tree_host()->root_layer()->AddChild(content_);
674  }
675
676  virtual void BeginTest() OVERRIDE {
677    visible_ = true;
678    PostAddAnimationToMainThread(content_.get());
679  }
680
681  virtual void DidCommit() OVERRIDE {
682    visible_ = false;
683    layer_tree_host()->SetVisible(false);
684  }
685
686  virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
687    EXPECT_FALSE(visible_);
688    started_times_++;
689  }
690
691  virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
692    EXPECT_FALSE(visible_);
693    EXPECT_EQ(1, started_times_);
694    EndTest();
695  }
696
697  virtual void AfterTest() OVERRIDE {}
698
699 private:
700  bool visible_;
701  int started_times_;
702  FakeContentLayerClient client_;
703  scoped_refptr<FakeContentLayer> content_;
704};
705
706SINGLE_AND_MULTI_THREAD_TEST_F(
707    LayerTreeHostAnimationTestRunAnimationWhenNotVisible);
708
709// Animations should not be started when frames are being skipped due to
710// checkerboard.
711class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
712    : public LayerTreeHostAnimationTest {
713  virtual void SetupTree() OVERRIDE {
714    LayerTreeHostAnimationTest::SetupTree();
715    content_ = FakeContentLayer::Create(&client_);
716    content_->SetBounds(gfx::Size(4, 4));
717    content_->set_layer_animation_delegate(this);
718    layer_tree_host()->root_layer()->AddChild(content_);
719  }
720
721  virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
722    // Make sure that drawing many times doesn't cause a checkerboarded
723    // animation to start so we avoid flake in this test.
724    settings->timeout_and_draw_when_animation_checkerboards = false;
725  }
726
727  virtual void BeginTest() OVERRIDE {
728    prevented_draw_ = 0;
729    added_animations_ = 0;
730    started_times_ = 0;
731    finished_times_ = 0;
732
733    PostSetNeedsCommitToMainThread();
734  }
735
736  virtual void DispatchAddInstantAnimation(Layer* layer_to_receive_animation)
737      OVERRIDE {
738    LayerTreeHostAnimationTest::DispatchAddInstantAnimation(
739        layer_to_receive_animation);
740    added_animations_++;
741  }
742
743  virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
744                                     LayerTreeHostImpl::FrameData* frame_data,
745                                     bool result) OVERRIDE {
746    if (added_animations_ < 2)
747      return result;
748    if (TestEnded())
749      return result;
750    // Act like there is checkerboard when the second animation wants to draw.
751    ++prevented_draw_;
752    return false;
753  }
754
755  virtual void DidCommitAndDrawFrame() OVERRIDE {
756    switch (layer_tree_host()->source_frame_number()) {
757      case 1:
758        // The animation is longer than 1 BeginFrame interval.
759        AddOpacityTransitionToLayer(content_.get(), 0.1, 0.2f, 0.8f, false);
760        added_animations_++;
761        break;
762      case 2:
763        // This second animation will not be drawn so it should not start.
764        AddAnimatedTransformToLayer(content_.get(), 0.1, 5, 5);
765        added_animations_++;
766        break;
767    }
768  }
769
770  virtual void NotifyAnimationStarted(double wall_clock_time) OVERRIDE {
771    if (TestEnded())
772      return;
773    started_times_++;
774  }
775
776  virtual void NotifyAnimationFinished(double wall_clock_time) OVERRIDE {
777    // We should be checkerboarding already, but it should still finish the
778    // first animation.
779    EXPECT_EQ(2, added_animations_);
780    finished_times_++;
781    EndTest();
782  }
783
784  virtual void AfterTest() OVERRIDE {
785    // Make sure we tried to draw the second animation but failed.
786    EXPECT_LT(0, prevented_draw_);
787    // The first animation should be started, but the second should not because
788    // of checkerboard.
789    EXPECT_EQ(1, started_times_);
790    // The first animation should still be finished.
791    EXPECT_EQ(1, finished_times_);
792  }
793
794  int prevented_draw_;
795  int added_animations_;
796  int started_times_;
797  int finished_times_;
798  FakeContentLayerClient client_;
799  scoped_refptr<FakeContentLayer> content_;
800};
801
802MULTI_THREAD_TEST_F(
803    LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);
804
805}  // namespace
806}  // namespace cc
807