Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_animation.cc
blobe9b877d0ba6b154e6c41aaf029d78519d0132b6a
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.
5 #include "cc/trees/layer_tree_host.h"
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/base/time_util.h"
12 #include "cc/layers/layer.h"
13 #include "cc/layers/layer_impl.h"
14 #include "cc/test/animation_test_common.h"
15 #include "cc/test/fake_content_layer.h"
16 #include "cc/test/fake_content_layer_client.h"
17 #include "cc/test/layer_tree_test.h"
18 #include "cc/trees/layer_tree_impl.h"
20 namespace cc {
21 namespace {
23 class LayerTreeHostAnimationTest : public LayerTreeTest {
24 public:
25 void SetupTree() override {
26 LayerTreeTest::SetupTree();
27 layer_tree_host()->root_layer()->set_layer_animation_delegate(this);
31 // Makes sure that SetNeedsAnimate does not cause the CommitRequested() state to
32 // be set.
33 class LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested
34 : public LayerTreeHostAnimationTest {
35 public:
36 LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested()
37 : num_commits_(0) {}
39 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
41 void BeginMainFrame(const BeginFrameArgs& args) override {
42 // We skip the first commit because 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;
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.
54 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());
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_++;
68 void AfterTest() override {}
70 private:
71 int num_commits_;
74 MULTI_THREAD_TEST_F(
75 LayerTreeHostAnimationTestSetNeedsAnimateShouldNotSetCommitRequested);
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.
82 class LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback
83 : public LayerTreeHostAnimationTest {
84 public:
85 LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback()
86 : num_begin_frames_(0) {}
88 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
90 void BeginMainFrame(const BeginFrameArgs& args) override {
91 if (!num_begin_frames_) {
92 layer_tree_host()->SetNeedsAnimate();
93 num_begin_frames_++;
94 return;
96 EndTest();
99 void AfterTest() override {}
101 private:
102 int num_begin_frames_;
105 MULTI_THREAD_TEST_F(
106 LayerTreeHostAnimationTestSetNeedsAnimateInsideAnimationCallback);
108 // Add a layer animation and confirm that
109 // LayerTreeHostImpl::UpdateAnimationState does get called.
110 class LayerTreeHostAnimationTestAddAnimation
111 : public LayerTreeHostAnimationTest {
112 public:
113 LayerTreeHostAnimationTestAddAnimation()
114 : update_animation_state_was_called_(false) {}
116 void BeginTest() override {
117 PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
120 void UpdateAnimationState(LayerTreeHostImpl* host_impl,
121 bool has_unfinished_animation) override {
122 EXPECT_FALSE(has_unfinished_animation);
123 update_animation_state_was_called_ = true;
126 void NotifyAnimationStarted(base::TimeTicks monotonic_time,
127 Animation::TargetProperty target_property,
128 int group) override {
129 EXPECT_LT(base::TimeTicks(), monotonic_time);
131 LayerAnimationController* controller =
132 layer_tree_host()->root_layer()->layer_animation_controller();
133 Animation* animation = controller->GetAnimation(Animation::OPACITY);
134 if (animation)
135 controller->RemoveAnimation(animation->id());
137 EndTest();
140 void AfterTest() override { EXPECT_TRUE(update_animation_state_was_called_); }
142 private:
143 bool update_animation_state_was_called_;
146 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAddAnimation);
148 // Add a layer animation to a layer, but continually fail to draw. Confirm that
149 // after a while, we do eventually force a draw.
150 class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
151 : public LayerTreeHostAnimationTest {
152 public:
153 LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws()
154 : started_animating_(false) {}
156 void BeginTest() override {
157 PostAddAnimationToMainThread(layer_tree_host()->root_layer());
160 void AnimateLayers(LayerTreeHostImpl* host_impl,
161 base::TimeTicks monotonic_time) override {
162 started_animating_ = true;
165 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
166 if (started_animating_)
167 EndTest();
170 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
171 LayerTreeHostImpl::FrameData* frame,
172 DrawResult draw_result) override {
173 return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
176 void AfterTest() override {}
178 private:
179 bool started_animating_;
182 // Starvation can only be an issue with the MT compositor.
183 MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws);
185 // Ensures that animations eventually get deleted.
186 class LayerTreeHostAnimationTestAnimationsGetDeleted
187 : public LayerTreeHostAnimationTest {
188 public:
189 LayerTreeHostAnimationTestAnimationsGetDeleted()
190 : started_animating_(false) {}
192 void BeginTest() override {
193 PostAddAnimationToMainThread(layer_tree_host()->root_layer());
196 void AnimateLayers(LayerTreeHostImpl* host_impl,
197 base::TimeTicks monotonic_time) override {
198 bool have_animations = !host_impl->animation_registrar()
199 ->active_animation_controllers_for_testing()
200 .empty();
201 if (!started_animating_ && have_animations) {
202 started_animating_ = true;
203 return;
206 if (started_animating_ && !have_animations)
207 EndTest();
210 void NotifyAnimationFinished(base::TimeTicks monotonic_time,
211 Animation::TargetProperty target_property,
212 int group) override {
213 // Animations on the impl-side controller only get deleted during a commit,
214 // so we need to schedule a commit.
215 layer_tree_host()->SetNeedsCommit();
218 void AfterTest() override {}
220 private:
221 bool started_animating_;
224 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted);
226 // Ensures that animations continue to be ticked when we are backgrounded.
227 class LayerTreeHostAnimationTestTickAnimationWhileBackgrounded
228 : public LayerTreeHostAnimationTest {
229 public:
230 LayerTreeHostAnimationTestTickAnimationWhileBackgrounded()
231 : num_begin_frames_(0) {}
233 void BeginTest() override {
234 PostAddLongAnimationToMainThread(layer_tree_host()->root_layer());
237 // Use WillAnimateLayers to set visible false before the animation runs and
238 // causes a commit, so we block the second visible animate in single-thread
239 // mode.
240 void WillAnimateLayers(LayerTreeHostImpl* host_impl,
241 base::TimeTicks monotonic_time) override {
242 // Verify that the host can draw, it's just not visible.
243 EXPECT_TRUE(host_impl->CanDraw());
244 if (num_begin_frames_ < 2) {
245 if (!num_begin_frames_) {
246 // We have a long animation running. It should continue to tick even
247 // if we are not visible.
248 PostSetVisibleToMainThread(false);
250 num_begin_frames_++;
251 return;
253 EndTest();
256 void AfterTest() override {}
258 private:
259 int num_begin_frames_;
262 SINGLE_AND_MULTI_THREAD_TEST_F(
263 LayerTreeHostAnimationTestTickAnimationWhileBackgrounded);
265 // Ensures that animation time remains monotonic when we switch from foreground
266 // to background ticking and back, even if we're skipping draws due to
267 // checkerboarding when in the foreground.
268 class LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic
269 : public LayerTreeHostAnimationTest {
270 public:
271 LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic()
272 : has_background_ticked_(false), num_foreground_animates_(0) {}
274 void InitializeSettings(LayerTreeSettings* settings) override {
275 // Make sure that drawing many times doesn't cause a checkerboarded
276 // animation to start so we avoid flake in this test.
277 settings->timeout_and_draw_when_animation_checkerboards = false;
280 void BeginTest() override {
281 PostAddLongAnimationToMainThread(layer_tree_host()->root_layer());
284 void AnimateLayers(LayerTreeHostImpl* host_impl,
285 base::TimeTicks monotonic_time) override {
286 EXPECT_GE(monotonic_time, last_tick_time_);
287 last_tick_time_ = monotonic_time;
288 if (host_impl->visible()) {
289 num_foreground_animates_++;
290 if (num_foreground_animates_ > 1 && !has_background_ticked_)
291 PostSetVisibleToMainThread(false);
292 else if (has_background_ticked_)
293 EndTest();
294 } else {
295 has_background_ticked_ = true;
296 PostSetVisibleToMainThread(true);
300 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
301 LayerTreeHostImpl::FrameData* frame,
302 DrawResult draw_result) override {
303 if (TestEnded())
304 return draw_result;
305 return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
308 void AfterTest() override {}
310 private:
311 bool has_background_ticked_;
312 int num_foreground_animates_;
313 base::TimeTicks last_tick_time_;
316 SINGLE_AND_MULTI_THREAD_TEST_F(
317 LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic);
319 // Ensures that animations do not tick when we are backgrounded and
320 // and we have an empty active tree.
321 class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree
322 : public LayerTreeHostAnimationTest {
323 protected:
324 LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree()
325 : active_tree_was_animated_(false) {}
327 base::TimeDelta BackgroundAnimationInterval(LayerTreeHostImpl* host_impl) {
328 return base::TimeDelta::FromSecondsD(
329 1.0 / host_impl->settings().background_animation_rate);
332 void BeginTest() override {
333 PostAddAnimationToMainThread(layer_tree_host()->root_layer());
336 void NotifyAnimationFinished(base::TimeTicks monotonic_time,
337 Animation::TargetProperty target_property,
338 int group) override {
339 // Replace animated commits with an empty tree.
340 layer_tree_host()->SetRootLayer(make_scoped_refptr<Layer>(NULL));
343 void DidCommit() override {
344 // This alternates setting an empty tree and a non-empty tree with an
345 // animation.
346 switch (layer_tree_host()->source_frame_number()) {
347 case 1:
348 // Wait for NotifyAnimationFinished to commit an empty tree.
349 break;
350 case 2:
351 SetupTree();
352 AddOpacityTransitionToLayer(
353 layer_tree_host()->root_layer(), 0.000001, 0, 0.5, true);
354 break;
355 case 3:
356 // Wait for NotifyAnimationFinished to commit an empty tree.
357 break;
358 case 4:
359 EndTest();
360 break;
364 void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
365 // At the start of every commit, block activations and make sure
366 // we are backgrounded.
367 if (host_impl->settings().impl_side_painting)
368 host_impl->BlockNotifyReadyToActivateForTesting(true);
369 PostSetVisibleToMainThread(false);
372 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
373 if (!host_impl->settings().impl_side_painting) {
374 // There are no activations to block if we're not impl-side-painting,
375 // so just advance the test immediately.
376 if (host_impl->active_tree()->source_frame_number() < 3)
377 UnblockActivations(host_impl);
378 return;
381 // We block activation for several ticks to make sure that, even though
382 // there is a pending tree with animations, we still do not background
383 // tick if the active tree is empty.
384 if (host_impl->pending_tree()->source_frame_number() < 3) {
385 base::MessageLoopProxy::current()->PostDelayedTask(
386 FROM_HERE,
387 base::Bind(
388 &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree::
389 UnblockActivations,
390 base::Unretained(this), host_impl),
391 4 * BackgroundAnimationInterval(host_impl));
395 virtual void UnblockActivations(LayerTreeHostImpl* host_impl) {
396 if (host_impl->settings().impl_side_painting)
397 host_impl->BlockNotifyReadyToActivateForTesting(false);
400 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
401 active_tree_was_animated_ = false;
403 // Verify that commits are actually alternating with empty / non-empty
404 // trees.
405 int frame_number = host_impl->active_tree()->source_frame_number();
406 switch (frame_number) {
407 case 0:
408 case 2:
409 EXPECT_TRUE(host_impl->active_tree()->root_layer())
410 << "frame: " << frame_number;
411 break;
412 case 1:
413 case 3:
414 EXPECT_FALSE(host_impl->active_tree()->root_layer())
415 << "frame: " << frame_number;
416 break;
419 if (host_impl->active_tree()->source_frame_number() < 3) {
420 // Initiate the next commit after a delay to give us a chance to
421 // background tick if the active tree isn't empty.
422 base::MessageLoopProxy::current()->PostDelayedTask(
423 FROM_HERE,
424 base::Bind(
425 &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree::
426 InitiateNextCommit,
427 base::Unretained(this), host_impl),
428 4 * BackgroundAnimationInterval(host_impl));
432 void WillAnimateLayers(LayerTreeHostImpl* host_impl,
433 base::TimeTicks monotonic_time) override {
434 EXPECT_TRUE(host_impl->active_tree()->root_layer());
435 active_tree_was_animated_ = true;
438 void InitiateNextCommit(LayerTreeHostImpl* host_impl) {
439 // Verify that we actually animated when we should have.
440 bool has_active_tree = host_impl->active_tree()->root_layer();
441 EXPECT_EQ(has_active_tree, active_tree_was_animated_);
443 // The next commit is blocked until we become visible again.
444 PostSetVisibleToMainThread(true);
447 void AfterTest() override {}
449 bool active_tree_was_animated_;
452 SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F(
453 LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree);
455 // Ensure that an animation's timing function is respected.
456 class LayerTreeHostAnimationTestAddAnimationWithTimingFunction
457 : public LayerTreeHostAnimationTest {
458 public:
459 LayerTreeHostAnimationTestAddAnimationWithTimingFunction() {}
461 void SetupTree() override {
462 LayerTreeHostAnimationTest::SetupTree();
463 content_ = FakeContentLayer::Create(&client_);
464 content_->SetBounds(gfx::Size(4, 4));
465 layer_tree_host()->root_layer()->AddChild(content_);
468 void BeginTest() override { PostAddAnimationToMainThread(content_.get()); }
470 void AnimateLayers(LayerTreeHostImpl* host_impl,
471 base::TimeTicks monotonic_time) override {
472 LayerAnimationController* controller_impl =
473 host_impl->active_tree()->root_layer()->children()[0]->
474 layer_animation_controller();
475 Animation* animation = controller_impl->GetAnimation(Animation::OPACITY);
476 if (!animation)
477 return;
479 const FloatAnimationCurve* curve =
480 animation->curve()->ToFloatAnimationCurve();
481 float start_opacity = curve->GetValue(base::TimeDelta());
482 float end_opacity = curve->GetValue(curve->Duration());
483 float linearly_interpolated_opacity =
484 0.25f * end_opacity + 0.75f * start_opacity;
485 base::TimeDelta time = TimeUtil::Scale(curve->Duration(), 0.25f);
486 // If the linear timing function associated with this animation was not
487 // picked up, then the linearly interpolated opacity would be different
488 // because of the default ease timing function.
489 EXPECT_FLOAT_EQ(linearly_interpolated_opacity, curve->GetValue(time));
491 EndTest();
494 void AfterTest() override {}
496 FakeContentLayerClient client_;
497 scoped_refptr<FakeContentLayer> content_;
500 SINGLE_AND_MULTI_THREAD_TEST_F(
501 LayerTreeHostAnimationTestAddAnimationWithTimingFunction);
503 // Ensures that main thread animations have their start times synchronized with
504 // impl thread animations.
505 class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes
506 : public LayerTreeHostAnimationTest {
507 public:
508 LayerTreeHostAnimationTestSynchronizeAnimationStartTimes() {}
510 void SetupTree() override {
511 LayerTreeHostAnimationTest::SetupTree();
512 content_ = FakeContentLayer::Create(&client_);
513 content_->SetBounds(gfx::Size(4, 4));
514 content_->set_layer_animation_delegate(this);
515 layer_tree_host()->root_layer()->AddChild(content_);
518 void BeginTest() override { PostAddAnimationToMainThread(content_.get()); }
520 void NotifyAnimationStarted(base::TimeTicks monotonic_time,
521 Animation::TargetProperty target_property,
522 int group) override {
523 LayerAnimationController* controller =
524 layer_tree_host()->root_layer()->children()[0]->
525 layer_animation_controller();
526 Animation* animation = controller->GetAnimation(Animation::OPACITY);
527 main_start_time_ = animation->start_time();
528 controller->RemoveAnimation(animation->id());
529 EndTest();
532 void UpdateAnimationState(LayerTreeHostImpl* impl_host,
533 bool has_unfinished_animation) override {
534 LayerAnimationController* controller =
535 impl_host->active_tree()->root_layer()->children()[0]->
536 layer_animation_controller();
537 Animation* animation = controller->GetAnimation(Animation::OPACITY);
538 if (!animation)
539 return;
541 impl_start_time_ = animation->start_time();
544 void AfterTest() override {
545 EXPECT_EQ(impl_start_time_, main_start_time_);
546 EXPECT_LT(base::TimeTicks(), impl_start_time_);
549 private:
550 base::TimeTicks main_start_time_;
551 base::TimeTicks impl_start_time_;
552 FakeContentLayerClient client_;
553 scoped_refptr<FakeContentLayer> content_;
556 SINGLE_AND_MULTI_THREAD_TEST_F(
557 LayerTreeHostAnimationTestSynchronizeAnimationStartTimes);
559 // Ensures that notify animation finished is called.
560 class LayerTreeHostAnimationTestAnimationFinishedEvents
561 : public LayerTreeHostAnimationTest {
562 public:
563 LayerTreeHostAnimationTestAnimationFinishedEvents() {}
565 void BeginTest() override {
566 PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer());
569 void NotifyAnimationFinished(base::TimeTicks monotonic_time,
570 Animation::TargetProperty target_property,
571 int group) override {
572 LayerAnimationController* controller =
573 layer_tree_host()->root_layer()->layer_animation_controller();
574 Animation* animation = controller->GetAnimation(Animation::OPACITY);
575 if (animation)
576 controller->RemoveAnimation(animation->id());
577 EndTest();
580 void AfterTest() override {}
583 SINGLE_AND_MULTI_THREAD_TEST_F(
584 LayerTreeHostAnimationTestAnimationFinishedEvents);
586 // Ensures that when opacity is being animated, this value does not cause the
587 // subtree to be skipped.
588 class LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity
589 : public LayerTreeHostAnimationTest {
590 public:
591 LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity()
592 : update_check_layer_(FakeContentLayer::Create(&client_)) {
595 void SetupTree() override {
596 update_check_layer_->SetOpacity(0.f);
597 layer_tree_host()->SetRootLayer(update_check_layer_);
598 LayerTreeHostAnimationTest::SetupTree();
601 void BeginTest() override {
602 PostAddAnimationToMainThread(update_check_layer_.get());
605 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
606 LayerAnimationController* controller_impl =
607 host_impl->active_tree()->root_layer()->layer_animation_controller();
608 Animation* animation_impl =
609 controller_impl->GetAnimation(Animation::OPACITY);
610 controller_impl->RemoveAnimation(animation_impl->id());
611 EndTest();
614 void AfterTest() override {
615 // Update() should have been called once, proving that the layer was not
616 // skipped.
617 EXPECT_EQ(1u, update_check_layer_->update_count());
619 // clear update_check_layer_ so LayerTreeHost dies.
620 update_check_layer_ = NULL;
623 private:
624 FakeContentLayerClient client_;
625 scoped_refptr<FakeContentLayer> update_check_layer_;
628 SINGLE_AND_MULTI_THREAD_TEST_F(
629 LayerTreeHostAnimationTestDoNotSkipLayersWithAnimatedOpacity);
631 // Layers added to tree with existing active animations should have the
632 // animation correctly recognized.
633 class LayerTreeHostAnimationTestLayerAddedWithAnimation
634 : public LayerTreeHostAnimationTest {
635 public:
636 LayerTreeHostAnimationTestLayerAddedWithAnimation() {}
638 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
640 void DidCommit() override {
641 if (layer_tree_host()->source_frame_number() == 1) {
642 scoped_refptr<Layer> layer = Layer::Create();
643 layer->set_layer_animation_delegate(this);
645 // Any valid AnimationCurve will do here.
646 scoped_ptr<AnimationCurve> curve(new FakeFloatAnimationCurve());
647 scoped_ptr<Animation> animation(
648 Animation::Create(curve.Pass(), 1, 1, Animation::OPACITY));
649 layer->layer_animation_controller()->AddAnimation(animation.Pass());
651 // We add the animation *before* attaching the layer to the tree.
652 layer_tree_host()->root_layer()->AddChild(layer);
656 void AnimateLayers(LayerTreeHostImpl* impl_host,
657 base::TimeTicks monotonic_time) override {
658 EndTest();
661 void AfterTest() override {}
664 SINGLE_AND_MULTI_THREAD_TEST_F(
665 LayerTreeHostAnimationTestLayerAddedWithAnimation);
667 class LayerTreeHostAnimationTestCancelAnimateCommit
668 : public LayerTreeHostAnimationTest {
669 public:
670 LayerTreeHostAnimationTestCancelAnimateCommit()
671 : num_begin_frames_(0), num_commit_calls_(0), num_draw_calls_(0) {}
673 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
675 void BeginMainFrame(const BeginFrameArgs& args) override {
676 num_begin_frames_++;
677 // No-op animate will cancel the commit.
678 if (layer_tree_host()->source_frame_number() == 1) {
679 EndTest();
680 return;
682 layer_tree_host()->SetNeedsAnimate();
685 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
686 num_commit_calls_++;
687 if (impl->active_tree()->source_frame_number() > 1)
688 FAIL() << "Commit should have been canceled.";
691 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
692 num_draw_calls_++;
693 if (impl->active_tree()->source_frame_number() > 1)
694 FAIL() << "Draw should have been canceled.";
697 void AfterTest() override {
698 EXPECT_EQ(2, num_begin_frames_);
699 EXPECT_EQ(1, num_commit_calls_);
700 EXPECT_EQ(1, num_draw_calls_);
703 private:
704 int num_begin_frames_;
705 int num_commit_calls_;
706 int num_draw_calls_;
707 FakeContentLayerClient client_;
708 scoped_refptr<FakeContentLayer> content_;
711 MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestCancelAnimateCommit);
713 class LayerTreeHostAnimationTestForceRedraw
714 : public LayerTreeHostAnimationTest {
715 public:
716 LayerTreeHostAnimationTestForceRedraw()
717 : num_animate_(0), num_draw_layers_(0) {}
719 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
721 void BeginMainFrame(const BeginFrameArgs& args) override {
722 if (++num_animate_ < 2)
723 layer_tree_host()->SetNeedsAnimate();
726 void Layout() override { layer_tree_host()->SetNextCommitForcesRedraw(); }
728 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
729 if (++num_draw_layers_ == 2)
730 EndTest();
733 void AfterTest() override {
734 // The first commit will always draw; make sure the second draw triggered
735 // by the animation was not cancelled.
736 EXPECT_EQ(2, num_draw_layers_);
737 EXPECT_EQ(2, num_animate_);
740 private:
741 int num_animate_;
742 int num_draw_layers_;
745 MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestForceRedraw);
747 class LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit
748 : public LayerTreeHostAnimationTest {
749 public:
750 LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit()
751 : num_animate_(0), num_draw_layers_(0) {}
753 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
755 void BeginMainFrame(const BeginFrameArgs& args) override {
756 if (++num_animate_ <= 2) {
757 layer_tree_host()->SetNeedsCommit();
758 layer_tree_host()->SetNeedsAnimate();
762 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
763 if (++num_draw_layers_ == 2)
764 EndTest();
767 void AfterTest() override {
768 // The first commit will always draw; make sure the second draw triggered
769 // by the SetNeedsCommit was not cancelled.
770 EXPECT_EQ(2, num_draw_layers_);
771 EXPECT_GE(num_animate_, 2);
774 private:
775 int num_animate_;
776 int num_draw_layers_;
779 MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimateAfterSetNeedsCommit);
781 // Make sure the main thread can still execute animations when CanDraw() is not
782 // true.
783 class LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw
784 : public LayerTreeHostAnimationTest {
785 public:
786 LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw() : started_times_(0) {}
788 void SetupTree() override {
789 LayerTreeHostAnimationTest::SetupTree();
790 content_ = FakeContentLayer::Create(&client_);
791 content_->SetBounds(gfx::Size(4, 4));
792 content_->set_layer_animation_delegate(this);
793 layer_tree_host()->root_layer()->AddChild(content_);
796 void BeginTest() override {
797 layer_tree_host()->SetViewportSize(gfx::Size());
798 PostAddAnimationToMainThread(content_.get());
801 void NotifyAnimationStarted(base::TimeTicks monotonic_time,
802 Animation::TargetProperty target_property,
803 int group) override {
804 started_times_++;
807 void NotifyAnimationFinished(base::TimeTicks monotonic_time,
808 Animation::TargetProperty target_property,
809 int group) override {
810 EndTest();
813 void AfterTest() override { EXPECT_EQ(1, started_times_); }
815 private:
816 int started_times_;
817 FakeContentLayerClient client_;
818 scoped_refptr<FakeContentLayer> content_;
821 SINGLE_AND_MULTI_THREAD_TEST_F(
822 LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw);
824 // Make sure the main thread can still execute animations when the renderer is
825 // backgrounded.
826 class LayerTreeHostAnimationTestRunAnimationWhenNotVisible
827 : public LayerTreeHostAnimationTest {
828 public:
829 LayerTreeHostAnimationTestRunAnimationWhenNotVisible() : started_times_(0) {}
831 void SetupTree() override {
832 LayerTreeHostAnimationTest::SetupTree();
833 content_ = FakeContentLayer::Create(&client_);
834 content_->SetBounds(gfx::Size(4, 4));
835 content_->set_layer_animation_delegate(this);
836 layer_tree_host()->root_layer()->AddChild(content_);
839 void BeginTest() override {
840 visible_ = true;
841 PostAddAnimationToMainThread(content_.get());
844 void DidCommit() override {
845 visible_ = false;
846 layer_tree_host()->SetVisible(false);
849 void NotifyAnimationStarted(base::TimeTicks monotonic_time,
850 Animation::TargetProperty target_property,
851 int group) override {
852 EXPECT_FALSE(visible_);
853 started_times_++;
856 void NotifyAnimationFinished(base::TimeTicks monotonic_time,
857 Animation::TargetProperty target_property,
858 int group) override {
859 EXPECT_FALSE(visible_);
860 EXPECT_EQ(1, started_times_);
861 EndTest();
864 void AfterTest() override {}
866 private:
867 bool visible_;
868 int started_times_;
869 FakeContentLayerClient client_;
870 scoped_refptr<FakeContentLayer> content_;
873 SINGLE_AND_MULTI_THREAD_TEST_F(
874 LayerTreeHostAnimationTestRunAnimationWhenNotVisible);
876 // Animations should not be started when frames are being skipped due to
877 // checkerboard.
878 class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
879 : public LayerTreeHostAnimationTest {
880 void SetupTree() override {
881 LayerTreeHostAnimationTest::SetupTree();
882 content_ = FakeContentLayer::Create(&client_);
883 content_->SetBounds(gfx::Size(4, 4));
884 content_->set_layer_animation_delegate(this);
885 layer_tree_host()->root_layer()->AddChild(content_);
888 void InitializeSettings(LayerTreeSettings* settings) override {
889 // Make sure that drawing many times doesn't cause a checkerboarded
890 // animation to start so we avoid flake in this test.
891 settings->timeout_and_draw_when_animation_checkerboards = false;
894 void BeginTest() override {
895 prevented_draw_ = 0;
896 added_animations_ = 0;
897 started_times_ = 0;
899 PostSetNeedsCommitToMainThread();
902 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
903 LayerTreeHostImpl::FrameData* frame_data,
904 DrawResult draw_result) override {
905 if (added_animations_ < 2)
906 return draw_result;
907 if (TestEnded())
908 return draw_result;
909 // Act like there is checkerboard when the second animation wants to draw.
910 ++prevented_draw_;
911 if (prevented_draw_ > 2)
912 EndTest();
913 return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
916 void DidCommitAndDrawFrame() override {
917 switch (layer_tree_host()->source_frame_number()) {
918 case 1:
919 // The animation is longer than 1 BeginFrame interval.
920 AddOpacityTransitionToLayer(content_.get(), 0.1, 0.2f, 0.8f, false);
921 added_animations_++;
922 break;
923 case 2:
924 // This second animation will not be drawn so it should not start.
925 AddAnimatedTransformToLayer(content_.get(), 0.1, 5, 5);
926 added_animations_++;
927 break;
931 void NotifyAnimationStarted(base::TimeTicks monotonic_time,
932 Animation::TargetProperty target_property,
933 int group) override {
934 if (TestEnded())
935 return;
936 started_times_++;
939 void AfterTest() override {
940 // Make sure we tried to draw the second animation but failed.
941 EXPECT_LT(0, prevented_draw_);
942 // The first animation should be started, but the second should not because
943 // of checkerboard.
944 EXPECT_EQ(1, started_times_);
947 int prevented_draw_;
948 int added_animations_;
949 int started_times_;
950 FakeContentLayerClient client_;
951 scoped_refptr<FakeContentLayer> content_;
954 MULTI_THREAD_TEST_F(
955 LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations);
957 // Verifies that scroll offset animations are only accepted when impl-scrolling
958 // is supported, and that when scroll offset animations are accepted,
959 // scroll offset updates are sent back to the main thread.
960 class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated
961 : public LayerTreeHostAnimationTest {
962 public:
963 LayerTreeHostAnimationTestScrollOffsetChangesArePropagated() {}
965 void SetupTree() override {
966 LayerTreeHostAnimationTest::SetupTree();
968 scroll_layer_ = FakeContentLayer::Create(&client_);
969 scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id());
970 scroll_layer_->SetBounds(gfx::Size(1000, 1000));
971 scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
972 layer_tree_host()->root_layer()->AddChild(scroll_layer_);
975 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
977 void DidCommit() override {
978 switch (layer_tree_host()->source_frame_number()) {
979 case 1: {
980 scoped_ptr<ScrollOffsetAnimationCurve> curve(
981 ScrollOffsetAnimationCurve::Create(
982 gfx::ScrollOffset(500.f, 550.f),
983 EaseInOutTimingFunction::Create()));
984 scoped_ptr<Animation> animation(
985 Animation::Create(curve.Pass(), 1, 0, Animation::SCROLL_OFFSET));
986 animation->set_needs_synchronized_start_time(true);
987 bool animation_added = scroll_layer_->AddAnimation(animation.Pass());
988 bool impl_scrolling_supported =
989 layer_tree_host()->proxy()->SupportsImplScrolling();
990 EXPECT_EQ(impl_scrolling_supported, animation_added);
991 if (!impl_scrolling_supported)
992 EndTest();
993 break;
995 default:
996 if (scroll_layer_->scroll_offset().x() > 10 &&
997 scroll_layer_->scroll_offset().y() > 20)
998 EndTest();
1002 void AfterTest() override {}
1004 private:
1005 FakeContentLayerClient client_;
1006 scoped_refptr<FakeContentLayer> scroll_layer_;
1009 SINGLE_AND_MULTI_THREAD_TEST_F(
1010 LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);
1012 // Verifies that when the main thread removes a scroll animation and sets a new
1013 // scroll position, the active tree takes on exactly this new scroll position
1014 // after activation, and the main thread doesn't receive a spurious scroll
1015 // delta.
1016 class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval
1017 : public LayerTreeHostAnimationTest {
1018 public:
1019 LayerTreeHostAnimationTestScrollOffsetAnimationRemoval()
1020 : final_postion_(50.0, 100.0) {}
1022 void SetupTree() override {
1023 LayerTreeHostAnimationTest::SetupTree();
1025 scroll_layer_ = FakeContentLayer::Create(&client_);
1026 scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id());
1027 scroll_layer_->SetBounds(gfx::Size(10000, 10000));
1028 scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0));
1029 layer_tree_host()->root_layer()->AddChild(scroll_layer_);
1031 scoped_ptr<ScrollOffsetAnimationCurve> curve(
1032 ScrollOffsetAnimationCurve::Create(gfx::ScrollOffset(6500.f, 7500.f),
1033 EaseInOutTimingFunction::Create()));
1034 scoped_ptr<Animation> animation(
1035 Animation::Create(curve.Pass(), 1, 0, Animation::SCROLL_OFFSET));
1036 animation->set_needs_synchronized_start_time(true);
1037 scroll_layer_->AddAnimation(animation.Pass());
1040 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1042 void BeginMainFrame(const BeginFrameArgs& args) override {
1043 switch (layer_tree_host()->source_frame_number()) {
1044 case 0:
1045 break;
1046 case 1: {
1047 Animation* animation =
1048 scroll_layer_->layer_animation_controller()->GetAnimation(
1049 Animation::SCROLL_OFFSET);
1050 scroll_layer_->layer_animation_controller()->RemoveAnimation(
1051 animation->id());
1052 scroll_layer_->SetScrollOffset(final_postion_);
1053 break;
1055 default:
1056 EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset());
1060 void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
1061 if (host_impl->settings().impl_side_painting)
1062 host_impl->BlockNotifyReadyToActivateForTesting(true);
1065 void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
1066 const BeginFrameArgs& args) override {
1067 if (!host_impl->pending_tree())
1068 return;
1070 if (!host_impl->active_tree()->root_layer()) {
1071 host_impl->BlockNotifyReadyToActivateForTesting(false);
1072 return;
1075 LayerImpl* scroll_layer_impl =
1076 host_impl->active_tree()->root_layer()->children()[0];
1077 Animation* animation =
1078 scroll_layer_impl->layer_animation_controller()->GetAnimation(
1079 Animation::SCROLL_OFFSET);
1081 if (!animation || animation->run_state() != Animation::RUNNING) {
1082 host_impl->BlockNotifyReadyToActivateForTesting(false);
1083 return;
1086 // Block activation until the running animation has a chance to produce a
1087 // scroll delta.
1088 gfx::Vector2dF scroll_delta = scroll_layer_impl->ScrollDelta();
1089 if (scroll_delta.x() < 1.f || scroll_delta.y() < 1.f)
1090 return;
1092 host_impl->BlockNotifyReadyToActivateForTesting(false);
1095 void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1096 if (!host_impl->settings().impl_side_painting)
1097 return;
1098 if (host_impl->pending_tree()->source_frame_number() != 1)
1099 return;
1100 LayerImpl* scroll_layer_impl =
1101 host_impl->pending_tree()->root_layer()->children()[0];
1102 EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
1105 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1106 if (host_impl->active_tree()->source_frame_number() != 1)
1107 return;
1108 LayerImpl* scroll_layer_impl =
1109 host_impl->active_tree()->root_layer()->children()[0];
1110 EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
1111 EndTest();
1114 void AfterTest() override {
1115 EXPECT_EQ(final_postion_, scroll_layer_->scroll_offset());
1118 private:
1119 FakeContentLayerClient client_;
1120 scoped_refptr<FakeContentLayer> scroll_layer_;
1121 const gfx::ScrollOffset final_postion_;
1124 MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationRemoval);
1126 // When animations are simultaneously added to an existing layer and to a new
1127 // layer, they should start at the same time, even when there's already a
1128 // running animation on the existing layer.
1129 class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
1130 : public LayerTreeHostAnimationTest {
1131 public:
1132 LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers()
1133 : frame_count_with_pending_tree_(0) {}
1135 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1137 void DidCommit() override {
1138 if (layer_tree_host()->source_frame_number() == 1) {
1139 AddAnimatedTransformToLayer(layer_tree_host()->root_layer(), 4, 1, 1);
1140 } else if (layer_tree_host()->source_frame_number() == 2) {
1141 AddOpacityTransitionToLayer(
1142 layer_tree_host()->root_layer(), 1, 0.f, 0.5f, true);
1144 scoped_refptr<Layer> layer = Layer::Create();
1145 layer_tree_host()->root_layer()->AddChild(layer);
1146 layer->set_layer_animation_delegate(this);
1147 layer->SetBounds(gfx::Size(4, 4));
1148 AddOpacityTransitionToLayer(layer.get(), 1, 0.f, 0.5f, true);
1152 void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
1153 if (host_impl->settings().impl_side_painting)
1154 host_impl->BlockNotifyReadyToActivateForTesting(true);
1157 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1158 // For the commit that added animations to new and existing layers, keep
1159 // blocking activation. We want to verify that even with activation blocked,
1160 // the animation on the layer that's already in the active tree won't get a
1161 // head start.
1162 if (host_impl->settings().impl_side_painting &&
1163 host_impl->pending_tree()->source_frame_number() != 2) {
1164 host_impl->BlockNotifyReadyToActivateForTesting(false);
1168 void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
1169 const BeginFrameArgs& args) override {
1170 if (!host_impl->pending_tree() ||
1171 host_impl->pending_tree()->source_frame_number() != 2)
1172 return;
1174 frame_count_with_pending_tree_++;
1175 if (frame_count_with_pending_tree_ == 2 &&
1176 host_impl->settings().impl_side_painting) {
1177 host_impl->BlockNotifyReadyToActivateForTesting(false);
1181 void UpdateAnimationState(LayerTreeHostImpl* host_impl,
1182 bool has_unfinished_animation) override {
1183 LayerAnimationController* root_controller_impl =
1184 host_impl->active_tree()->root_layer()->layer_animation_controller();
1185 Animation* root_animation =
1186 root_controller_impl->GetAnimation(Animation::OPACITY);
1187 if (!root_animation || root_animation->run_state() != Animation::RUNNING)
1188 return;
1190 LayerAnimationController* child_controller_impl =
1191 host_impl->active_tree()->root_layer()->children()
1192 [0]->layer_animation_controller();
1193 Animation* child_animation =
1194 child_controller_impl->GetAnimation(Animation::OPACITY);
1195 EXPECT_EQ(Animation::RUNNING, child_animation->run_state());
1196 EXPECT_EQ(root_animation->start_time(), child_animation->start_time());
1197 root_controller_impl->AbortAnimations(Animation::OPACITY);
1198 root_controller_impl->AbortAnimations(Animation::TRANSFORM);
1199 child_controller_impl->AbortAnimations(Animation::OPACITY);
1200 EndTest();
1203 void AfterTest() override {}
1205 private:
1206 int frame_count_with_pending_tree_;
1209 SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F(
1210 LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers);
1212 class LayerTreeHostAnimationTestAddAnimationAfterAnimating
1213 : public LayerTreeHostAnimationTest {
1214 public:
1215 LayerTreeHostAnimationTestAddAnimationAfterAnimating()
1216 : num_swap_buffers_(0) {}
1218 void SetupTree() override {
1219 LayerTreeHostAnimationTest::SetupTree();
1220 content_ = Layer::Create();
1221 content_->SetBounds(gfx::Size(4, 4));
1222 layer_tree_host()->root_layer()->AddChild(content_);
1225 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1227 void DidCommit() override {
1228 switch (layer_tree_host()->source_frame_number()) {
1229 case 1:
1230 // First frame: add an animation to the root layer.
1231 AddAnimatedTransformToLayer(layer_tree_host()->root_layer(), 0.1, 5, 5);
1232 break;
1233 case 2:
1234 // Second frame: add an animation to the content layer. The root layer
1235 // animation has caused us to animate already during this frame.
1236 AddOpacityTransitionToLayer(content_.get(), 0.1, 5, 5, false);
1237 break;
1241 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1242 // After both animations have started, verify that they have valid
1243 // start times.
1244 num_swap_buffers_++;
1245 AnimationRegistrar::AnimationControllerMap controllers_copy =
1246 host_impl->animation_registrar()
1247 ->active_animation_controllers_for_testing();
1248 if (controllers_copy.size() == 2u) {
1249 EndTest();
1250 EXPECT_GE(num_swap_buffers_, 3);
1251 for (auto& it : controllers_copy) {
1252 int id = it.first;
1253 if (id == host_impl->RootLayer()->id()) {
1254 Animation* anim = it.second->GetAnimation(Animation::TRANSFORM);
1255 EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0);
1256 } else if (id == host_impl->RootLayer()->children()[0]->id()) {
1257 Animation* anim = it.second->GetAnimation(Animation::OPACITY);
1258 EXPECT_GT((anim->start_time() - base::TimeTicks()).InSecondsF(), 0);
1264 void AfterTest() override {}
1266 private:
1267 scoped_refptr<Layer> content_;
1268 int num_swap_buffers_;
1271 SINGLE_AND_MULTI_THREAD_TEST_F(
1272 LayerTreeHostAnimationTestAddAnimationAfterAnimating);
1274 } // namespace
1275 } // namespace cc