Chromium Code Reviews| Index: cc/surfaces/surface_unittest.cc |
| diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc |
| index dc6dc2dee90556bd39d69f88154bc70219bf6558..9a9f508659c63e9edb38322a0c096dbd0f49dd99 100644 |
| --- a/cc/surfaces/surface_unittest.cc |
| +++ b/cc/surfaces/surface_unittest.cc |
| @@ -3,10 +3,14 @@ |
| // found in the LICENSE file. |
| #include "cc/surfaces/surface.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "cc/surfaces/surface_dependency_tracker.h" |
| #include "cc/surfaces/surface_factory.h" |
| #include "cc/surfaces/surface_factory_client.h" |
| #include "cc/surfaces/surface_id_allocator.h" |
| #include "cc/surfaces/surface_manager.h" |
| +#include "cc/test/begin_frame_args_test.h" |
| +#include "cc/test/fake_external_begin_frame_source.h" |
| #include "cc/test/scheduler_test_common.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/geometry/size.h" |
| @@ -16,6 +20,14 @@ namespace { |
| static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); |
| +CompositorFrame MakeCompositorFrame( |
| + std::vector<SurfaceId> referenced_surfaces) { |
| + CompositorFrame compositor_frame; |
| + compositor_frame.metadata.referenced_surfaces = |
| + std::move(referenced_surfaces); |
| + return compositor_frame; |
| +} |
| + |
| class FakeSurfaceFactoryClient : public SurfaceFactoryClient { |
| public: |
| FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} |
| @@ -32,6 +44,329 @@ class FakeSurfaceFactoryClient : public SurfaceFactoryClient { |
| BeginFrameSource* begin_frame_source_; |
| }; |
| +// Surface 1 is blocked on Surface 2 and Surface 3. |
| +TEST(SurfaceTest, DisplayCompositorLocking1) { |
| + SurfaceManager manager; |
| + std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source( |
| + new FakeExternalBeginFrameSource(0.f, false)); |
| + |
| + std::unique_ptr<SurfaceDependencyTracker> dependency_tracker( |
| + new SurfaceDependencyTracker(&manager, begin_frame_source.get())); |
| + manager.SetDependencyTracker(std::move(dependency_tracker)); |
| + |
| + LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create()); |
| + SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1); |
| + |
| + LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create()); |
| + SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2); |
| + |
| + LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create()); |
| + SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client1; |
| + SurfaceFactory factory1(FrameSinkId(1, 1), &manager, |
| + &surface_factory_client1); |
| + factory1.SubmitCompositorFrame( |
| + local_surface_id1, MakeCompositorFrame({surface_id2, surface_id3}), |
| + SurfaceFactory::DrawCallback()); |
| + EXPECT_TRUE(manager.dependency_tracker()->has_deadline()); |
| + |
| + // |factory1| is blocked on |surface_id2| and |surface_id3|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client2; |
| + SurfaceFactory factory2(FrameSinkId(2, 2), &manager, |
| + &surface_factory_client2); |
| + factory2.SubmitCompositorFrame(local_surface_id2, |
| + MakeCompositorFrame(std::vector<SurfaceId>()), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + EXPECT_TRUE(manager.dependency_tracker()->has_deadline()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory1| is blocked on just |surface_id3|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client3; |
| + SurfaceFactory factory3(FrameSinkId(3, 3), &manager, |
| + &surface_factory_client3); |
| + factory3.SubmitCompositorFrame(local_surface_id3, |
| + MakeCompositorFrame(std::vector<SurfaceId>()), |
| + SurfaceFactory::DrawCallback()); |
| + EXPECT_FALSE(manager.dependency_tracker()->has_deadline()); |
| + |
| + // |factory1|'s Frame is now active. |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + factory1.EvictSurface(); |
| + factory2.EvictSurface(); |
| + factory3.EvictSurface(); |
| + |
| + // Destroy the SurfaceDependencyTracker before we destroy the |
| + // BeginFrameSource. |
| + manager.SetDependencyTracker(nullptr); |
| +} |
| + |
| +// Surface 1 is blocked on Surface 2 which is blocked on Surface 3. |
| +TEST(SurfaceTest, DisplayCompositorLocking2) { |
|
vmpstr
2017/02/08 19:25:40
Can you name the tests something more descriptive?
Fady Samuel
2017/02/08 23:39:58
Done.
|
| + SurfaceManager manager; |
| + std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source( |
| + new FakeExternalBeginFrameSource(0.f, false)); |
| + |
| + std::unique_ptr<SurfaceDependencyTracker> dependency_tracker( |
| + new SurfaceDependencyTracker(&manager, begin_frame_source.get())); |
| + manager.SetDependencyTracker(std::move(dependency_tracker)); |
| + |
| + LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create()); |
| + SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1); |
| + |
| + LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create()); |
| + SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2); |
| + |
| + LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create()); |
| + SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client1; |
| + SurfaceFactory factory1(FrameSinkId(1, 1), &manager, |
| + &surface_factory_client1); |
| + factory1.SubmitCompositorFrame(local_surface_id1, |
| + MakeCompositorFrame({surface_id2}), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory1| is blocked on |surface_id2|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client2; |
| + SurfaceFactory factory2(FrameSinkId(2, 2), &manager, |
| + &surface_factory_client2); |
| + factory2.SubmitCompositorFrame(local_surface_id2, |
| + MakeCompositorFrame({surface_id3}), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory2| is blocked on |surface_id3|. |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory1| is still blocked on just |surface_id2|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client3; |
| + SurfaceFactory factory3(FrameSinkId(3, 3), &manager, |
| + &surface_factory_client3); |
| + CompositorFrame frame3; |
| + factory3.SubmitCompositorFrame(local_surface_id3, |
| + MakeCompositorFrame(std::vector<SurfaceId>()), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory1|'s Frame is now active. |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory2|'s Frame is now active. |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + factory1.EvictSurface(); |
| + factory2.EvictSurface(); |
| + factory3.EvictSurface(); |
| + |
| + // Destroy the SurfaceDependencyTracker before we destroy the |
| + // BeginFrameSource. |
| + manager.SetDependencyTracker(nullptr); |
| +} |
| + |
| +// Surface 1 and Surface 2 are blocked on Surface 3. |
| +TEST(SurfaceTest, DisplayCompositorLocking3) { |
|
vmpstr
2017/02/08 19:25:40
DisplayCompositorLockingTwoBlockedOnOne
Fady Samuel
2017/02/08 23:39:58
Done.
|
| + SurfaceManager manager; |
| + std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source( |
| + new FakeExternalBeginFrameSource(0.f, false)); |
| + |
| + std::unique_ptr<SurfaceDependencyTracker> dependency_tracker( |
| + new SurfaceDependencyTracker(&manager, begin_frame_source.get())); |
| + manager.SetDependencyTracker(std::move(dependency_tracker)); |
| + |
| + LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create()); |
| + SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1); |
| + |
| + LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create()); |
| + SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2); |
| + |
| + LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create()); |
| + SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client1; |
| + SurfaceFactory factory1(FrameSinkId(1, 1), &manager, |
| + &surface_factory_client1); |
| + factory1.SubmitCompositorFrame(local_surface_id1, |
| + MakeCompositorFrame({surface_id3}), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory1| is blocked on |surface_id3|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client2; |
| + SurfaceFactory factory2(FrameSinkId(2, 2), &manager, |
| + &surface_factory_client2); |
| + factory2.SubmitCompositorFrame(local_surface_id2, |
| + MakeCompositorFrame({surface_id3}), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory2| is blocked on |surface_id3|. |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory1| is still blocked on |surface_id3|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client3; |
| + SurfaceFactory factory3(FrameSinkId(3, 3), &manager, |
| + &surface_factory_client3); |
| + factory3.SubmitCompositorFrame(local_surface_id3, |
| + MakeCompositorFrame(std::vector<SurfaceId>()), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory1|'s Frame is now active. |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory2|'s Frame is now active. |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + factory1.EvictSurface(); |
| + factory2.EvictSurface(); |
| + factory3.EvictSurface(); |
| + |
| + // Destroy the SurfaceDependencyTracker before we destroy the |
| + // BeginFrameSource. |
| + manager.SetDependencyTracker(nullptr); |
| +} |
| + |
| +// |factory1| is blocked on |surface_id2| but the deadline hits. |
| +TEST(SurfaceTest, DisplayCompositorLocking4) { |
|
vmpstr
2017/02/08 19:25:40
DisplayCompositorLockingDeadlineHits
Fady Samuel
2017/02/08 23:39:58
Done.
|
| + SurfaceManager manager; |
| + std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source( |
| + new FakeExternalBeginFrameSource(0.f, false)); |
| + |
| + std::unique_ptr<SurfaceDependencyTracker> dependency_tracker( |
| + new SurfaceDependencyTracker(&manager, begin_frame_source.get())); |
| + manager.SetDependencyTracker(std::move(dependency_tracker)); |
| + |
| + LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create()); |
| + SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1); |
| + |
| + LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create()); |
| + SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2); |
| + |
| + LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create()); |
| + SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client1; |
| + SurfaceFactory factory1(FrameSinkId(1, 1), &manager, |
| + &surface_factory_client1); |
| + CompositorFrame frame; |
| + factory1.SubmitCompositorFrame(local_surface_id1, |
| + MakeCompositorFrame({surface_id2}), |
| + SurfaceFactory::DrawCallback()); |
| + EXPECT_TRUE(manager.dependency_tracker()->has_deadline()); |
| + |
| + // |factory1| is blocked on |surface_id2|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client2; |
| + SurfaceFactory factory2(FrameSinkId(2, 2), &manager, |
| + &surface_factory_client2); |
| + factory2.SubmitCompositorFrame(local_surface_id2, |
| + MakeCompositorFrame({surface_id3}), |
| + SurfaceFactory::DrawCallback()); |
| + EXPECT_TRUE(manager.dependency_tracker()->has_deadline()); |
| + |
| + // |factory2| is blocked on |surface_id3|. |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + BeginFrameArgs args = |
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); |
| + begin_frame_source->TestOnBeginFrame(args); |
| + |
| + // |factory1| is still blocked on |surface_id2|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + // |factory2| is still blcoked on |surface_id3|. |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + |
| + begin_frame_source->TestOnBeginFrame(args); |
|
vmpstr
2017/02/08 19:25:40
Can you make this into a for loop that checks the
Fady Samuel
2017/02/08 23:39:58
Done.
|
| + begin_frame_source->TestOnBeginFrame(args); |
| + begin_frame_source->TestOnBeginFrame(args); |
| + |
| + // |factory1| and |factory2| are no longer blocked. |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame()); |
| + EXPECT_FALSE(manager.dependency_tracker()->has_deadline()); |
| + |
| + factory1.EvictSurface(); |
| + factory2.EvictSurface(); |
| + |
| + // Destroy the SurfaceDependencyTracker before we destroy the |
| + // BeginFrameSource. |
| + manager.SetDependencyTracker(nullptr); |
| +} |
| + |
| +// Frame activates once a new frame is submitted. |
| +TEST(SurfaceTest, DisplayCompositorLocking5) { |
| + SurfaceManager manager; |
| + std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source( |
| + new FakeExternalBeginFrameSource(0.f, false)); |
| + |
| + manager.SetDependencyTracker(base::MakeUnique<SurfaceDependencyTracker>( |
| + &manager, begin_frame_source.get())); |
| + |
| + LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create()); |
| + SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1); |
| + |
| + LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create()); |
| + SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2); |
| + |
| + FakeSurfaceFactoryClient surface_factory_client1; |
| + SurfaceFactory factory1(FrameSinkId(1, 1), &manager, |
| + &surface_factory_client1); |
| + factory1.SubmitCompositorFrame(local_surface_id1, |
| + MakeCompositorFrame({surface_id2}), |
| + SurfaceFactory::DrawCallback()); |
| + |
| + // |factory1|'s Frame is blocked on |surface_id2|. |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + EXPECT_TRUE(manager.dependency_tracker()->has_deadline()); |
| + |
| + // Another frame is submitted to |factory1| that has no dependencies. |
| + factory1.SubmitCompositorFrame(local_surface_id1, |
| + MakeCompositorFrame(std::vector<SurfaceId>()), |
| + SurfaceFactory::DrawCallback()); |
| + EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame()); |
| + EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame()); |
| + EXPECT_FALSE(manager.dependency_tracker()->has_deadline()); |
| + |
| + factory1.EvictSurface(); |
| + |
| + // Destroy the SurfaceDependencyTracker before we destroy the |
| + // BeginFrameSource. |
| + manager.SetDependencyTracker(nullptr); |
| +} |
| + |
| TEST(SurfaceTest, SurfaceLifetime) { |
| SurfaceManager manager; |
| FakeSurfaceFactoryClient surface_factory_client; |