// 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 "cc/surfaces/surface.h" #include "base/memory/ptr_util.h" #include "cc/output/copy_output_result.h" #include "cc/surfaces/local_surface_id_allocator.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_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" namespace cc { namespace { static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1); class FakeSurfaceFactoryClient : public SurfaceFactoryClient { public: FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} void ReturnResources(const ReturnedResourceArray& resources) override {} void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override { begin_frame_source_ = begin_frame_source; } BeginFrameSource* begin_frame_source() { return begin_frame_source_; } private: BeginFrameSource* begin_frame_source_; }; TEST(SurfaceTest, SurfaceLifetime) { SurfaceManager manager; FakeSurfaceFactoryClient surface_factory_client; SurfaceFactory factory(kArbitraryFrameSinkId, &manager, &surface_factory_client); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); factory.SubmitCompositorFrame(local_surface_id, CompositorFrame(), SurfaceFactory::DrawCallback()); EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); factory.EvictSurface(); EXPECT_EQ(NULL, manager.GetSurfaceForId(surface_id)); } TEST(SurfaceTest, SurfaceIds) { for (size_t i = 0; i < 3; ++i) { LocalSurfaceIdAllocator allocator; LocalSurfaceId id1 = allocator.GenerateId(); LocalSurfaceId id2 = allocator.GenerateId(); EXPECT_NE(id1, id2); } } void TestCopyResultCallback(bool* called, std::unique_ptr result) { *called = true; } // Test that CopyOutputRequests can outlive the current frame and be // aggregated on the next frame. TEST(SurfaceTest, CopyRequestLifetime) { SurfaceManager manager; FakeSurfaceFactoryClient surface_factory_client; SurfaceFactory factory(kArbitraryFrameSinkId, &manager, &surface_factory_client); LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create()); SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id); CompositorFrame frame; frame.render_pass_list.push_back(RenderPass::Create()); factory.SubmitCompositorFrame(local_surface_id, std::move(frame), SurfaceFactory::DrawCallback()); Surface* surface = manager.GetSurfaceForId(surface_id); ASSERT_TRUE(!!surface); bool copy_called = false; factory.RequestCopyOfSurface(CopyOutputRequest::CreateRequest( base::Bind(&TestCopyResultCallback, ©_called))); EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); EXPECT_FALSE(copy_called); CompositorFrame frame2; frame2.render_pass_list.push_back(RenderPass::Create()); frame2.render_pass_list.back()->id = 1; frame2.render_pass_list.push_back(RenderPass::Create()); frame2.render_pass_list.back()->id = 2; factory.SubmitCompositorFrame(local_surface_id, std::move(frame2), SurfaceFactory::DrawCallback()); // The copy request should stay on the Surface after a new frame is created. EXPECT_FALSE(copy_called); EXPECT_EQ( 1u, surface->GetActiveFrame().render_pass_list.back()->copy_requests.size()); std::multimap> copy_requests; surface->TakeCopyOutputRequests(©_requests); EXPECT_EQ(1u, copy_requests.size()); // Last (root) pass should receive copy request. ASSERT_EQ(1u, copy_requests.count(2)); EXPECT_FALSE(copy_called); copy_requests.find(2)->second->SendEmptyResult(); EXPECT_TRUE(copy_called); factory.EvictSurface(); } } // namespace } // namespace cc