| // Copyright 2024 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef GPU_COMMAND_BUFFER_CLIENT_TEST_SHARED_IMAGE_INTERFACE_H_ | |
| #define GPU_COMMAND_BUFFER_CLIENT_TEST_SHARED_IMAGE_INTERFACE_H_ | |
| #include <memory> | |
| #include "base/synchronization/lock.h" | |
| #include "build/build_config.h" | |
| #include "gpu/command_buffer/client/client_shared_image.h" | |
| #include "gpu/command_buffer/client/shared_image_interface.h" | |
| #include "gpu/command_buffer/common/shared_image_capabilities.h" | |
| #include "gpu/command_buffer/common/shared_image_usage.h" | |
| #include "gpu/ipc/client/shared_image_interface_proxy.h" | |
| #include "gpu/ipc/common/shared_image_pool_client_interface.mojom.h" | |
| #include "mojo/public/cpp/bindings/remote.h" | |
| #include "testing/gmock/include/gmock/gmock.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" | |
| #include "third_party/abseil-cpp/absl/container/flat_hash_set.h" | |
| #include "ui/gfx/buffer_types.h" | |
| #include "ui/gfx/gpu_memory_buffer_handle.h" | |
| namespace gpu { | |
| class TestBufferCollection; | |
| class TestSharedImageInterfaceClient { | |
| public: | |
| virtual ~TestSharedImageInterfaceClient() {} | |
| virtual void DidDestroySharedImage() = 0; | |
| }; | |
| class TestSharedImageInterface : public SharedImageInterface { | |
| public: | |
| TestSharedImageInterface(); | |
| // Creates a shared memory region and returns a handle to it. | |
| static gfx::GpuMemoryBufferHandle CreateGMBHandle( | |
| const viz::SharedImageFormat& format, | |
| const gfx::Size& size); | |
| // for default-args overloads | |
| using SharedImageInterface::CreateSharedImage; | |
| scoped_refptr<ClientSharedImage> CreateSharedImage( | |
| const SharedImageInfo& si_info, | |
| SurfaceHandle surface_handle, | |
| std::optional<SharedImagePoolId> pool_id) override; | |
| scoped_refptr<ClientSharedImage> CreateSharedImage( | |
| const SharedImageInfo& si_info, | |
| base::span<const uint8_t> pixel_data) override; | |
| scoped_refptr<ClientSharedImage> CreateSharedImage( | |
| const SharedImageInfo& si_info, | |
| SurfaceHandle surface_handle, | |
| gfx::BufferUsage buffer_usage, | |
| std::optional<SharedImagePoolId> pool_id) override; | |
| MOCK_METHOD4(DoCreateSharedImage, | |
| void(const gfx::Size& size, | |
| const viz::SharedImageFormat& format, | |
| gpu::SurfaceHandle surface_handle, | |
| gfx::BufferUsage buffer_usage)); | |
| scoped_refptr<ClientSharedImage> CreateSharedImage( | |
| const SharedImageInfo& si_info, | |
| SurfaceHandle surface_handle, | |
| gfx::BufferUsage buffer_usage, | |
| gfx::GpuMemoryBufferHandle buffer_handle) override; | |
| scoped_refptr<ClientSharedImage> CreateSharedImage( | |
| const SharedImageInfo& si_info, | |
| gfx::GpuMemoryBufferHandle buffer_handle) override; | |
| scoped_refptr<ClientSharedImage> CreateSharedImageForMLTensor( | |
| std::string debug_label, | |
| viz::SharedImageFormat format, | |
| const gfx::Size& size, | |
| gpu::SharedImageUsageSet usage) override; | |
| scoped_refptr<ClientSharedImage> CreateSharedImageForSoftwareCompositor( | |
| const SharedImageInfo& si_info) override; | |
| void UpdateSharedImage(const SyncToken& sync_token, | |
| const Mailbox& mailbox) override; | |
| void UpdateSharedImage(const SyncToken& sync_token, | |
| std::unique_ptr<gfx::GpuFence> acquire_fence, | |
| const Mailbox& mailbox) override; | |
| scoped_refptr<ClientSharedImage> ImportSharedImage( | |
| ExportedSharedImage exported_shared_image) override; | |
| void DestroySharedImage(std::vector<SyncToken> sync_tokens, | |
| const Mailbox& mailbox) override; | |
| void DestroySharedImage( | |
| const SyncToken& sync_token, | |
| scoped_refptr<ClientSharedImage> client_shared_image) override; | |
| bool IsLost() const override { return false; } | |
| bool AddGpuChannelLostObserver(GpuChannelLostObserver* observer) override { | |
| return true; | |
| } | |
| void RemoveGpuChannelLostObserver(GpuChannelLostObserver* observer) override { | |
| } | |
| #if BUILDFLAG(IS_FUCHSIA) | |
| void RegisterSysmemBufferCollection(zx::eventpair service_handle, | |
| zx::channel sysmem_token, | |
| const viz::SharedImageFormat& format, | |
| gfx::BufferUsage usage, | |
| bool register_with_image_pipe) override; | |
| #endif // BUILDFLAG(IS_FUCHSIA) | |
| SyncToken GenVerifiedSyncToken() override; | |
| SyncToken GenUnverifiedSyncToken() override; | |
| void VerifySyncToken(SyncToken& sync_token) override; | |
| void WaitSyncToken(const SyncToken& sync_token) override; | |
| void SignalSyncToken(std::vector<SyncToken> sync_tokens, | |
| base::OnceClosure callback) override; | |
| bool CanVerifySyncToken(const gpu::SyncToken& sync_token) override; | |
| void VerifyFlush() override; | |
| // This is used only on windows for webrtc tests where test wants the | |
| // production code to trigger ClientSharedImage::MapAsync() but wants | |
| // to control when the callback runs from inside the test. This is achieved by | |
| // using a custom ClientSharedImage::MapCallbackControllerForTesting. The | |
| // callback execution is deferred by registering the callback with the | |
| // provided |controller|. The test manually triggers the mapping completion by | |
| // invoking the |controller| later, simulating a delayed (asynchronous) | |
| // mapping. This is required to test delayed mapping behavior. | |
| scoped_refptr<ClientSharedImage> CreateSharedImageWithAsyncMapControl( | |
| const SharedImageInfo& si_info, | |
| gfx::BufferUsage buffer_usage, | |
| bool premapped, | |
| const ClientSharedImage::AsyncMapInvokedCallback& callback); | |
| #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) | |
| // Creates a mappable SI backed by a NativePixmapHandle. | |
| scoped_refptr<ClientSharedImage> CreateNativePixmapBackedSharedImage( | |
| const SharedImageInfo& si_info, | |
| SurfaceHandle surface_handle, | |
| gfx::BufferUsage buffer_usage); | |
| #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) | |
| void CreateSharedImagePool( | |
| const SharedImagePoolId& pool_id, | |
| mojo::PendingRemote<mojom::SharedImagePoolClientInterface> client_remote) | |
| override { | |
| auto it = remote_map_.find(pool_id); | |
| CHECK(it == remote_map_.end()); | |
| mojo::Remote<mojom::SharedImagePoolClientInterface> remote; | |
| remote.Bind(std::move(client_remote)); | |
| remote_map_.emplace(pool_id, std::move(remote)); | |
| } | |
| void DestroySharedImagePool(const SharedImagePoolId& pool_id) override { | |
| auto it = remote_map_.find(pool_id); | |
| if (it != remote_map_.end()) { | |
| // Disconnect the remote and remove the entry. | |
| it->second.reset(); | |
| remote_map_.erase(it); | |
| } | |
| } | |
| void SetClient(TestSharedImageInterfaceClient* client) { | |
| test_client_ = client; | |
| } | |
| size_t shared_image_count() const { return shared_images_.size(); } | |
| size_t num_update_shared_image_no_fence_calls() const { | |
| return num_update_shared_image_no_fence_calls_; | |
| } | |
| const gfx::Size& MostRecentSize() const { return most_recent_size_; } | |
| const SyncToken& MostRecentGeneratedToken() const { | |
| return most_recent_generated_token_; | |
| } | |
| const std::vector<SyncToken>& MostRecentDestroyTokens() const { | |
| return most_recent_destroy_tokens_; | |
| } | |
| ClientSharedImage* MostRecentMappableSharedImage() const { | |
| return most_recent_mappable_shared_image_; | |
| } | |
| bool CheckSharedImageExists(const Mailbox& mailbox) const; | |
| const SharedImageCapabilities& GetCapabilities() override; | |
| void SetCapabilities(const SharedImageCapabilities& caps); | |
| void SetFailSharedImageCreationWithBufferUsage(bool value) { | |
| fail_shared_image_creation_with_buffer_usage_ = value; | |
| } | |
| void emulate_client_provided_native_buffer() { | |
| emulate_client_provided_native_buffer_ = true; | |
| } | |
| protected: | |
| ~TestSharedImageInterface() override; | |
| private: | |
| mutable base::Lock lock_; | |
| raw_ptr<TestSharedImageInterfaceClient> test_client_ = nullptr; | |
| uint64_t release_id_ = 0; | |
| size_t num_update_shared_image_no_fence_calls_ = 0; | |
| gfx::Size most_recent_size_; | |
| SyncToken most_recent_generated_token_; | |
| std::vector<SyncToken> most_recent_destroy_tokens_; | |
| raw_ptr<ClientSharedImage> most_recent_mappable_shared_image_; | |
| absl::flat_hash_set<Mailbox> shared_images_; | |
| bool emulate_client_provided_native_buffer_ = false; | |
| #if BUILDFLAG(IS_FUCHSIA) | |
| absl::flat_hash_map<zx_koid_t, std::unique_ptr<TestBufferCollection>> | |
| sysmem_buffer_collections_; | |
| #endif | |
| SharedImageCapabilities shared_image_capabilities_; | |
| bool fail_shared_image_creation_with_buffer_usage_ = false; | |
| // This is used to simply keep the SharedImagePoolClientInterface alive for | |
| // the duration of the SharedImagePool. Not keeping it alive and bound | |
| // triggers diconnect_handlers causing unexpected behaviour in the test. | |
| absl::flat_hash_map<SharedImagePoolId, | |
| mojo::Remote<mojom::SharedImagePoolClientInterface>> | |
| remote_map_; | |
| }; | |
| } // namespace gpu | |
| #endif // GPU_COMMAND_BUFFER_CLIENT_TEST_SHARED_IMAGE_INTERFACE_H_ |