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