1 // Copyright 2016 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/animation/animation_host.h"
6 
7 #include "base/threading/thread_task_runner_handle.h"
8 #include "base/timer/lap_timer.h"
9 #include "cc/animation/animation.h"
10 #include "cc/animation/animation_id_provider.h"
11 #include "cc/animation/animation_timeline.h"
12 #include "cc/test/fake_impl_task_runner_provider.h"
13 #include "cc/test/fake_layer_tree_host.h"
14 #include "cc/test/fake_layer_tree_host_client.h"
15 #include "cc/test/fake_layer_tree_host_impl.h"
16 #include "cc/test/stub_layer_tree_host_single_thread_client.h"
17 #include "cc/test/test_task_graph_runner.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "testing/perf/perf_result_reporter.h"
20 
21 namespace cc {
22 
23 class AnimationHostPerfTest : public testing::Test {
24  protected:
AnimationHostPerfTest()25   AnimationHostPerfTest()
26       : root_layer_impl_(),
27         first_timeline_id_(),
28         last_timeline_id_(),
29         first_animation_id_(),
30         last_animation_id_() {}
31 
SetUp()32   void SetUp() override {
33     LayerTreeSettings settings;
34     animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
35     layer_tree_host_ = FakeLayerTreeHost::Create(
36         &fake_client_, &task_graph_runner_, animation_host_.get(), settings);
37     layer_tree_host_->InitializeSingleThreaded(
38         &single_thread_client_, base::ThreadTaskRunnerHandle::Get());
39 
40     root_layer_ = Layer::Create();
41     layer_tree_host_->SetRootLayer(root_layer_);
42 
43     root_layer_impl_ = layer_tree_host_->CommitAndCreateLayerImplTree();
44   }
45 
TearDown()46   void TearDown() override {
47     root_layer_ = nullptr;
48     root_layer_impl_ = nullptr;
49 
50     layer_tree_host_->SetRootLayer(nullptr);
51     layer_tree_host_ = nullptr;
52   }
53 
host() const54   AnimationHost* host() const { return animation_host_.get(); }
host_impl() const55   AnimationHost* host_impl() const {
56     return layer_tree_host_->host_impl()->animation_host();
57   }
58 
CreateAnimations(int num_animations)59   void CreateAnimations(int num_animations) {
60     all_animations_timeline_ =
61         AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
62     host()->AddAnimationTimeline(all_animations_timeline_);
63 
64     first_animation_id_ = AnimationIdProvider::NextAnimationId();
65     last_animation_id_ = first_animation_id_;
66 
67     for (int i = 0; i < num_animations; ++i) {
68       scoped_refptr<Layer> layer = Layer::Create();
69       root_layer_->AddChild(layer);
70       layer->SetElementId(LayerIdToElementIdForTesting(layer->id()));
71 
72       scoped_refptr<Animation> animation =
73           Animation::Create(last_animation_id_);
74       last_animation_id_ = AnimationIdProvider::NextAnimationId();
75 
76       all_animations_timeline_->AttachAnimation(animation);
77       animation->AttachElement(layer->element_id());
78       EXPECT_TRUE(animation->element_animations());
79     }
80 
81     // Create impl animations.
82     layer_tree_host_->CommitAndCreateLayerImplTree();
83 
84     // Check impl instances created.
85     scoped_refptr<AnimationTimeline> timeline_impl =
86         host_impl()->GetTimelineById(all_animations_timeline_->id());
87     EXPECT_TRUE(timeline_impl);
88     for (int i = first_animation_id_; i < last_animation_id_; ++i)
89       EXPECT_TRUE(timeline_impl->GetAnimationById(i));
90   }
91 
CreateTimelines(int num_timelines)92   void CreateTimelines(int num_timelines) {
93     first_timeline_id_ = AnimationIdProvider::NextTimelineId();
94     last_timeline_id_ = first_timeline_id_;
95 
96     for (int i = 0; i < num_timelines; ++i) {
97       scoped_refptr<AnimationTimeline> timeline =
98           AnimationTimeline::Create(last_timeline_id_);
99       last_timeline_id_ = AnimationIdProvider::NextTimelineId();
100       host()->AddAnimationTimeline(timeline);
101     }
102 
103     // Create impl timelines.
104     layer_tree_host_->CommitAndCreateLayerImplTree();
105 
106     // Check impl instances created.
107     for (int i = first_timeline_id_; i < last_timeline_id_; ++i)
108       EXPECT_TRUE(host_impl()->GetTimelineById(i));
109   }
110 
SetAllTimelinesNeedPushProperties() const111   void SetAllTimelinesNeedPushProperties() const {
112     for (int i = first_timeline_id_; i < last_timeline_id_; ++i)
113       host_impl()->GetTimelineById(i)->SetNeedsPushProperties();
114   }
115 
SetAllAnimationsNeedPushProperties() const116   void SetAllAnimationsNeedPushProperties() const {
117     for (int i = first_animation_id_; i < last_animation_id_; ++i)
118       all_animations_timeline_->GetAnimationById(i)->SetNeedsPushProperties();
119   }
120 
DoTest(const std::string & test_name)121   void DoTest(const std::string& test_name) {
122     timer_.Reset();
123     do {
124       // Invalidate dirty flags.
125       SetAllTimelinesNeedPushProperties();
126       SetAllAnimationsNeedPushProperties();
127       host()->PushPropertiesTo(host_impl());
128       timer_.NextLap();
129     } while (!timer_.HasTimeLimitExpired());
130 
131     perf_test::PerfResultReporter reporter("push_properties_to", test_name);
132     reporter.RegisterImportantMetric("", "runs/s");
133     reporter.AddResult("", timer_.LapsPerSecond());
134   }
135 
136  private:
137   StubLayerTreeHostSingleThreadClient single_thread_client_;
138   FakeLayerTreeHostClient fake_client_;
139   std::unique_ptr<AnimationHost> animation_host_;
140   std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
141   scoped_refptr<Layer> root_layer_;
142   LayerImpl* root_layer_impl_;
143   scoped_refptr<AnimationTimeline> all_animations_timeline_;
144 
145   int first_timeline_id_;
146   int last_timeline_id_;
147 
148   int first_animation_id_;
149   int last_animation_id_;
150 
151   base::LapTimer timer_;
152   TestTaskGraphRunner task_graph_runner_;
153 };
154 
TEST_F(AnimationHostPerfTest,Push1000AnimationsPropertiesTo)155 TEST_F(AnimationHostPerfTest, Push1000AnimationsPropertiesTo) {
156   CreateAnimations(1000);
157   DoTest("Push1000AnimationsPropertiesTo");
158 }
159 
TEST_F(AnimationHostPerfTest,Push10TimelinesPropertiesTo)160 TEST_F(AnimationHostPerfTest, Push10TimelinesPropertiesTo) {
161   CreateTimelines(10);
162   DoTest("Push10TimelinesPropertiesTo");
163 }
164 
TEST_F(AnimationHostPerfTest,Push1000TimelinesPropertiesTo)165 TEST_F(AnimationHostPerfTest, Push1000TimelinesPropertiesTo) {
166   CreateTimelines(1000);
167   DoTest("Push1000TimelinesPropertiesTo");
168 }
169 
170 }  // namespace cc
171