| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/animation/animation_host.h" |
| |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "cc/animation/animation_id_provider.h" |
| #include "cc/animation/animation_timeline.h" |
| #include "cc/animation/keyframe_effect.h" |
| #include "cc/animation/single_keyframe_effect_animation.h" |
| #include "cc/base/lap_timer.h" |
| #include "cc/test/fake_impl_task_runner_provider.h" |
| #include "cc/test/fake_layer_tree_host.h" |
| #include "cc/test/fake_layer_tree_host_client.h" |
| #include "cc/test/fake_layer_tree_host_impl.h" |
| #include "cc/test/stub_layer_tree_host_single_thread_client.h" |
| #include "cc/test/test_task_graph_runner.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/perf/perf_test.h" |
| |
| namespace cc { |
| |
| class AnimationHostPerfTest : public testing::Test { |
| protected: |
| AnimationHostPerfTest() |
| : root_layer_impl_(), |
| first_timeline_id_(), |
| last_timeline_id_(), |
| first_animation_id_(), |
| last_animation_id_() {} |
| |
| void SetUp() override { |
| LayerTreeSettings settings; |
| animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN); |
| layer_tree_host_ = FakeLayerTreeHost::Create( |
| &fake_client_, &task_graph_runner_, animation_host_.get(), settings); |
| layer_tree_host_->InitializeSingleThreaded( |
| &single_thread_client_, base::ThreadTaskRunnerHandle::Get()); |
| |
| root_layer_ = Layer::Create(); |
| layer_tree_host_->SetRootLayer(root_layer_); |
| |
| root_layer_impl_ = layer_tree_host_->CommitAndCreateLayerImplTree(); |
| } |
| |
| void TearDown() override { |
| root_layer_ = nullptr; |
| root_layer_impl_ = nullptr; |
| |
| layer_tree_host_->SetRootLayer(nullptr); |
| layer_tree_host_ = nullptr; |
| } |
| |
| AnimationHost* host() const { return animation_host_.get(); } |
| AnimationHost* host_impl() const { |
| return layer_tree_host_->host_impl()->animation_host(); |
| } |
| |
| void CreateAnimations(int num_animations) { |
| all_animations_timeline_ = |
| AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); |
| host()->AddAnimationTimeline(all_animations_timeline_); |
| |
| first_animation_id_ = AnimationIdProvider::NextAnimationId(); |
| last_animation_id_ = first_animation_id_; |
| |
| for (int i = 0; i < num_animations; ++i) { |
| scoped_refptr<Layer> layer = Layer::Create(); |
| root_layer_->AddChild(layer); |
| layer->SetElementId(LayerIdToElementIdForTesting(layer->id())); |
| |
| scoped_refptr<SingleKeyframeEffectAnimation> animation = |
| SingleKeyframeEffectAnimation::Create(last_animation_id_); |
| last_animation_id_ = AnimationIdProvider::NextAnimationId(); |
| |
| all_animations_timeline_->AttachAnimation(animation); |
| animation->AttachElement(layer->element_id()); |
| EXPECT_TRUE( |
| animation->element_animations(animation->keyframe_effect()->id())); |
| } |
| |
| // Create impl animations. |
| layer_tree_host_->CommitAndCreateLayerImplTree(); |
| |
| // Check impl instances created. |
| scoped_refptr<AnimationTimeline> timeline_impl = |
| host_impl()->GetTimelineById(all_animations_timeline_->id()); |
| EXPECT_TRUE(timeline_impl); |
| for (int i = first_animation_id_; i < last_animation_id_; ++i) |
| EXPECT_TRUE(timeline_impl->GetAnimationById(i)); |
| } |
| |
| void CreateTimelines(int num_timelines) { |
| first_timeline_id_ = AnimationIdProvider::NextTimelineId(); |
| last_timeline_id_ = first_timeline_id_; |
| |
| for (int i = 0; i < num_timelines; ++i) { |
| scoped_refptr<AnimationTimeline> timeline = |
| AnimationTimeline::Create(last_timeline_id_); |
| last_timeline_id_ = AnimationIdProvider::NextTimelineId(); |
| host()->AddAnimationTimeline(timeline); |
| } |
| |
| // Create impl timelines. |
| layer_tree_host_->CommitAndCreateLayerImplTree(); |
| |
| // Check impl instances created. |
| for (int i = first_timeline_id_; i < last_timeline_id_; ++i) |
| EXPECT_TRUE(host_impl()->GetTimelineById(i)); |
| } |
| |
| void SetAllTimelinesNeedPushProperties() const { |
| for (int i = first_timeline_id_; i < last_timeline_id_; ++i) |
| host_impl()->GetTimelineById(i)->SetNeedsPushProperties(); |
| } |
| |
| void SetAllAnimationsNeedPushProperties() const { |
| for (int i = first_animation_id_; i < last_animation_id_; ++i) |
| all_animations_timeline_->GetAnimationById(i)->SetNeedsPushProperties(); |
| } |
| |
| void DoTest() { |
| timer_.Reset(); |
| do { |
| // Invalidate dirty flags. |
| SetAllTimelinesNeedPushProperties(); |
| SetAllAnimationsNeedPushProperties(); |
| host()->PushPropertiesTo(host_impl()); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("push_properties_to", "", "", timer_.LapsPerSecond(), |
| "runs/s", true); |
| } |
| |
| private: |
| StubLayerTreeHostSingleThreadClient single_thread_client_; |
| FakeLayerTreeHostClient fake_client_; |
| std::unique_ptr<AnimationHost> animation_host_; |
| std::unique_ptr<FakeLayerTreeHost> layer_tree_host_; |
| scoped_refptr<Layer> root_layer_; |
| LayerImpl* root_layer_impl_; |
| scoped_refptr<AnimationTimeline> all_animations_timeline_; |
| |
| int first_timeline_id_; |
| int last_timeline_id_; |
| |
| int first_animation_id_; |
| int last_animation_id_; |
| |
| LapTimer timer_; |
| TestTaskGraphRunner task_graph_runner_; |
| }; |
| |
| TEST_F(AnimationHostPerfTest, Push1000AnimationsPropertiesTo) { |
| CreateAnimations(1000); |
| DoTest(); |
| } |
| |
| TEST_F(AnimationHostPerfTest, Push10TimelinesPropertiesTo) { |
| CreateTimelines(10); |
| DoTest(); |
| } |
| |
| TEST_F(AnimationHostPerfTest, Push1000TimelinesPropertiesTo) { |
| CreateTimelines(1000); |
| DoTest(); |
| } |
| |
| } // namespace cc |