// Copyright 2014 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 #include #include #include #include "base/location.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "cc/animation/animation_host.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/surface_layer.h" #include "cc/layers/surface_layer_impl.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/layer_tree_test.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/surface_info.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { namespace { using testing::_; using testing::Eq; using testing::ElementsAre; using testing::SizeIs; constexpr viz::FrameSinkId kArbitraryFrameSinkId(1, 1); class SurfaceLayerTest : public testing::Test { public: SurfaceLayerTest() : host_impl_(&task_runner_provider_, &task_graph_runner_) {} // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids. void SynchronizeTrees() { TreeSynchronizer::PushLayerProperties(layer_tree_host_.get(), host_impl_.pending_tree()); layer_tree_host_->PushSurfaceRangesTo(host_impl_.pending_tree()); } protected: void SetUp() override { animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN); layer_tree_host_ = FakeLayerTreeHost::Create( &fake_client_, &task_graph_runner_, animation_host_.get()); layer_tree_host_->SetViewportRectAndScale(gfx::Rect(10, 10), 1.f, viz::LocalSurfaceId()); host_impl_.CreatePendingTree(); } void TearDown() override { if (layer_tree_host_) { layer_tree_host_->SetRootLayer(nullptr); layer_tree_host_ = nullptr; } } FakeLayerTreeHostClient fake_client_; FakeImplTaskRunnerProvider task_runner_provider_; TestTaskGraphRunner task_graph_runner_; std::unique_ptr animation_host_; std::unique_ptr layer_tree_host_; FakeLayerTreeHostImpl host_impl_; }; // This test verifies that if UseExistingDeadline() is used on a new // SurfaceLayer then the deadline will be 0 frames. TEST_F(SurfaceLayerTest, UseExistingDeadlineForNewSurfaceLayer) { scoped_refptr layer = SurfaceLayer::Create(); layer_tree_host_->SetRootLayer(layer); viz::SurfaceId primary_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseExistingDeadline()); EXPECT_EQ(0u, layer->deadline_in_frames()); } // This test verifies that if UseInfiniteDeadline() is used on a new // SurfaceLayer then the deadline will be max number of frames. TEST_F(SurfaceLayerTest, UseInfiniteDeadlineForNewSurfaceLayer) { scoped_refptr layer = SurfaceLayer::Create(); layer_tree_host_->SetRootLayer(layer); viz::SurfaceId primary_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseInfiniteDeadline()); EXPECT_EQ(std::numeric_limits::max(), layer->deadline_in_frames()); } // This test verifies that if an invalid primary surface ID is set then the // deadline will be reset to 0 frames. TEST_F(SurfaceLayerTest, ResetDeadlineOnInvalidSurfaceId) { scoped_refptr layer = SurfaceLayer::Create(); layer_tree_host_->SetRootLayer(layer); viz::SurfaceId primary_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseSpecifiedDeadline(3u)); EXPECT_EQ(3u, layer->deadline_in_frames()); // Reset the surface layer to an invalid SurfaceId. Verify that the deadline // is reset. layer->SetSurfaceId(viz::SurfaceId(), DeadlinePolicy::UseSpecifiedDeadline(3u)); EXPECT_EQ(0u, layer->deadline_in_frames()); } // This test verifies that SurfaceLayer properties are pushed across to // SurfaceLayerImpl. TEST_F(SurfaceLayerTest, PushProperties) { scoped_refptr layer = SurfaceLayer::Create(); layer_tree_host_->SetRootLayer(layer); viz::SurfaceId primary_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseSpecifiedDeadline(1u)); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseSpecifiedDeadline(2u)); layer->SetSurfaceId(primary_id, DeadlinePolicy::UseExistingDeadline()); layer->SetOldestAcceptableFallback(primary_id); layer->SetBackgroundColor(SK_ColorBLUE); layer->SetStretchContentToFillBounds(true); EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u); // Verify that pending tree has no surface ids already. EXPECT_FALSE(host_impl_.pending_tree()->needs_surface_ranges_sync()); EXPECT_EQ(host_impl_.pending_tree()->SurfaceRanges().size(), 0u); std::unique_ptr layer_impl = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer->id()); SynchronizeTrees(); // Verify that pending tree received the surface id and also has // needs_surface_ranges_sync set to true as it needs to sync with active tree. EXPECT_TRUE(host_impl_.pending_tree()->needs_surface_ranges_sync()); EXPECT_EQ(host_impl_.pending_tree()->SurfaceRanges().size(), 1u); // Verify we have reset the state on layer tree host. EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); // Verify that the primary and fallback SurfaceIds are pushed through. EXPECT_EQ(primary_id, layer_impl->range().end()); EXPECT_EQ(primary_id, layer_impl->range().start()); EXPECT_EQ(SK_ColorBLUE, layer_impl->background_color()); EXPECT_TRUE(layer_impl->stretch_content_to_fill_bounds()); EXPECT_EQ(2u, layer_impl->deadline_in_frames()); viz::SurfaceId fallback_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(2, base::UnguessableToken::Create())); layer->SetOldestAcceptableFallback(fallback_id); layer->SetSurfaceId(fallback_id, DeadlinePolicy::UseExistingDeadline()); layer->SetBackgroundColor(SK_ColorGREEN); layer->SetStretchContentToFillBounds(false); // Verify that fallback surface id is not recorded on the layer tree host as // surface synchronization is not enabled. EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u); SynchronizeTrees(); EXPECT_EQ(host_impl_.pending_tree()->SurfaceRanges().size(), 1u); // Verify that the primary viz::SurfaceId stays the same and the new // fallback viz::SurfaceId is pushed through. EXPECT_EQ(fallback_id, layer_impl->range().end()); EXPECT_EQ(fallback_id, layer_impl->range().start()); EXPECT_EQ(SK_ColorGREEN, layer_impl->background_color()); // The deadline resets back to 0 (no deadline) after the first commit. EXPECT_EQ(0u, layer_impl->deadline_in_frames()); EXPECT_FALSE(layer_impl->stretch_content_to_fill_bounds()); } // This test verifies the list of surface ids is correct when there are cloned // surface layers. This emulates the flow of maximize and minimize animations on // Chrome OS. TEST_F(SurfaceLayerTest, CheckSurfaceReferencesForClonedLayer) { const viz::SurfaceId old_surface_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); // This layer will always contain the old surface id and will be deleted when // animation is done. scoped_refptr layer1 = SurfaceLayer::Create(); layer1->SetLayerTreeHost(layer_tree_host_.get()); layer1->SetSurfaceId(old_surface_id, DeadlinePolicy::UseDefaultDeadline()); layer1->SetOldestAcceptableFallback(old_surface_id); // This layer will eventually be switched be switched to show the new surface // id and will be retained when animation is done. scoped_refptr layer2 = SurfaceLayer::Create(); layer2->SetLayerTreeHost(layer_tree_host_.get()); layer2->SetSurfaceId(old_surface_id, DeadlinePolicy::UseDefaultDeadline()); layer2->SetOldestAcceptableFallback(old_surface_id); std::unique_ptr layer_impl1 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer1->id()); std::unique_ptr layer_impl2 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer2->id()); SynchronizeTrees(); // Verify that only |old_surface_id| is going to be referenced. EXPECT_THAT(layer_tree_host_->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id))); const viz::SurfaceId new_surface_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(2, base::UnguessableToken::Create())); // Switch the new layer to use |new_surface_id|. layer2->SetSurfaceId(new_surface_id, DeadlinePolicy::UseDefaultDeadline()); layer2->SetOldestAcceptableFallback(new_surface_id); SynchronizeTrees(); // Verify that both surface ids are going to be referenced. EXPECT_THAT(layer_tree_host_->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id), viz::SurfaceRange(new_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id), viz::SurfaceRange(new_surface_id))); // Unparent the old layer like it's being destroyed at the end of animation. layer1->SetLayerTreeHost(nullptr); SynchronizeTrees(); // Verify that only |new_surface_id| is going to be referenced. EXPECT_THAT(layer_tree_host_->SurfaceRanges(), ElementsAre(viz::SurfaceRange(new_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(new_surface_id))); // Cleanup for destruction. layer2->SetLayerTreeHost(nullptr); } // This test verifies LayerTreeHost::needs_surface_ranges_sync() is correct when // there are cloned surface layers. TEST_F(SurfaceLayerTest, CheckNeedsSurfaceIdsSyncForClonedLayers) { const viz::SurfaceId surface_id( kArbitraryFrameSinkId, viz::LocalSurfaceId(1, base::UnguessableToken::Create())); scoped_refptr layer1 = SurfaceLayer::Create(); layer1->SetLayerTreeHost(layer_tree_host_.get()); layer1->SetSurfaceId(surface_id, DeadlinePolicy::UseDefaultDeadline()); layer1->SetOldestAcceptableFallback(surface_id); // Verify the surface id is in SurfaceLayerIds() and // needs_surface_ranges_sync() is true. EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1)); std::unique_ptr layer_impl1 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer1->id()); SynchronizeTrees(); // After syncchronizing trees verify needs_surface_ranges_sync() is false. EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); // Create the second layer that is a clone of the first. scoped_refptr layer2 = SurfaceLayer::Create(); layer2->SetLayerTreeHost(layer_tree_host_.get()); layer2->SetSurfaceId(surface_id, DeadlinePolicy::UseDefaultDeadline()); layer2->SetOldestAcceptableFallback(surface_id); // Verify that after creating the second layer with the same surface id that // needs_surface_ranges_sync() is still false. EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1)); std::unique_ptr layer_impl2 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer2->id()); SynchronizeTrees(); // Verify needs_surface_ranges_sync() is still false after synchronizing // trees. EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); // Destroy one of the layers, leaving one layer with the surface id. layer1->SetLayerTreeHost(nullptr); // Verify needs_surface_ranges_sync() is still false. EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); // Destroy the last layer, this should change the set of layer surface ids. layer2->SetLayerTreeHost(nullptr); // Verify SurfaceLayerIds() is empty and needs_surface_ranges_sync() is true. EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(0)); } } // namespace } // namespace cc