// 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::Create(); root_layer_->AddChild(layer); layer->SetElementId(LayerIdToElementIdForTesting(layer->id())); scoped_refptr 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 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 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 animation_host_; std::unique_ptr layer_tree_host_; scoped_refptr root_layer_; LayerImpl* root_layer_impl_; scoped_refptr 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