| // Copyright 2023 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_CLIENT_SHARED_IMAGE_H_ | |
| #define GPU_COMMAND_BUFFER_CLIENT_CLIENT_SHARED_IMAGE_H_ | |
| #include <optional> | |
| #include "base/byte_size.h" | |
| #include "base/containers/flat_map.h" | |
| #include "base/containers/span.h" | |
| #include "base/gtest_prod_util.h" | |
| #include "base/memory/raw_ptr.h" | |
| #include "base/memory/ref_counted.h" | |
| #include "base/memory/scoped_refptr.h" | |
| #include "base/memory/unsafe_shared_memory_pool.h" | |
| #include "gpu/command_buffer/client/gpu_command_buffer_client_export.h" | |
| #include "gpu/command_buffer/client/internal/mappable_buffer.h" | |
| #include "gpu/command_buffer/common/mailbox.h" | |
| #include "gpu/command_buffer/common/shared_image_info.h" | |
| #include "gpu/command_buffer/common/shared_image_trace_utils.h" | |
| #include "gpu/command_buffer/common/shared_image_usage.h" | |
| #include "gpu/command_buffer/common/sync_token.h" | |
| #include "gpu/ipc/common/exported_shared_image.mojom-forward.h" | |
| #include "gpu/ipc/common/gpu_memory_buffer_handle_info.h" | |
| #include "third_party/skia/include/core/SkImageInfo.h" | |
| #include "third_party/skia/include/core/SkPixmap.h" | |
| #include "third_party/skia/include/gpu/ganesh/GrTypes.h" | |
| #include "ui/gfx/color_space.h" | |
| #include "ui/gfx/gpu_memory_buffer_handle.h" | |
| namespace base { | |
| class SingleThreadTaskRunner; | |
| } // namespace base | |
| namespace base::trace_event { | |
| class ProcessMemoryDump; | |
| class MemoryAllocatorDumpGuid; | |
| } // namespace base::trace_event | |
| namespace gfx { | |
| class GpuFence; | |
| } // namespace gfx | |
| namespace media { | |
| class VideoFrame; | |
| } // namespace media | |
| namespace viz { | |
| class CopyOutputSharedImageResult; | |
| struct ReturnedResource; | |
| struct ReturnedResourceViz; | |
| } // namespace viz | |
| namespace wgpu::dawn::wire::client { | |
| class Device; | |
| class Texture; | |
| class Buffer; | |
| struct TextureDescriptor; | |
| struct BufferDescriptor; | |
| } // namespace wgpu::dawn::wire::client | |
| namespace gpu { | |
| class ContextSupport; | |
| namespace gles2 { | |
| class GLES2Interface; | |
| } // namespace gles2 | |
| namespace webgpu { | |
| class WebGPUInterface; | |
| enum MailboxFlags : uint32_t; | |
| } // namespace webgpu | |
| class SharedImageInterface; | |
| class ClientSharedImageInterface; | |
| class GpuChannelSharedImageInterface; | |
| class MappableBuffer; | |
| class InterfaceBase; | |
| class RasterScopedAccess; | |
| struct SharedImageInfo; | |
| class SharedImageInterfaceHolder; | |
| class SharedImageTexture; | |
| class TestSharedImageInterface; | |
| class WebGPUTextureScopedAccess; | |
| class WebGPUBufferScopedAccess; | |
| struct ExportedSharedImage; | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT SharedImageExportResult { | |
| public: | |
| SharedImageExportResult(); | |
| ~SharedImageExportResult(); | |
| SharedImageExportResult(SharedImageExportResult&&); | |
| SharedImageExportResult& operator=(SharedImageExportResult&&); | |
| SharedImageExportResult(const SharedImageExportResult&) = delete; | |
| SharedImageExportResult& operator=(const SharedImageExportResult&) = delete; | |
| // Used in FrameSinkResourceManager to facilitate creating a dummy | |
| // ReturnedResource for callback clearing. | |
| static SharedImageExportResult CreateEmptyResult() { | |
| return SharedImageExportResult(SyncToken()); | |
| } | |
| static SharedImageExportResult CreateForTesting(const SyncToken& sync_token) { | |
| return SharedImageExportResult(sync_token); | |
| } | |
| static SharedImageExportResult CreateForTesting( | |
| std::vector<SyncToken> sync_tokens) { | |
| return SharedImageExportResult(std::move(sync_tokens)); | |
| } | |
| // The two IsEqualForTesting methods allow easy SyncToken comparison without | |
| // unpacking SharedImageExportResult. | |
| bool IsEqualForTesting(const SyncToken& sync_token) const { | |
| return sync_tokens_.size() == 1 && sync_tokens_[0] == sync_token; | |
| } | |
| bool IsEqualForTesting(const SharedImageExportResult& other_result) const { | |
| return sync_tokens_ == other_result.sync_tokens_; | |
| } | |
| bool HasData() const; | |
| std::string ToDebugString() const; | |
| private: | |
| friend class ClientSharedImage; | |
| // Allows ReturnedResourceViz to convert SyncToken to SharedImageExportResult. | |
| friend struct viz::ReturnedResourceViz; | |
| friend struct mojo::StructTraits<gpu::mojom::SharedImageExportResultDataView, | |
| SharedImageExportResult>; | |
| explicit SharedImageExportResult(const SyncToken& sync_token); | |
| explicit SharedImageExportResult(std::vector<SyncToken> sync_tokens); | |
| std::vector<SyncToken> sync_tokens_; | |
| }; | |
| // Wrapper around Mailbox and metadata for efficient sharing between threads | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT ClientSharedImage | |
| : public base::RefCountedThreadSafe<ClientSharedImage> { | |
| public: | |
| // Provides access to the CPU visible memory for the SharedImage if it is | |
| // being used for CPU READ/WRITE and underlying resource(native buffers/shared | |
| // memory) is CPU mappable. Memory and strides can be requested for each | |
| // plane. | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT ScopedMapping { | |
| public: | |
| ScopedMapping(const gfx::Size& size, viz::SharedImageFormat format); | |
| ~ScopedMapping(); | |
| base::span<uint8_t> GetMemoryForPlane(const uint32_t plane_index); | |
| SkPixmap GetSkPixmapForPlane(const uint32_t plane_index, | |
| SkImageInfo sk_image_info); | |
| // Returns plane stride. | |
| size_t Stride(const uint32_t plane_index); | |
| // Returns the size of the buffer. | |
| gfx::Size Size(); | |
| // Returns whether the underlying resource is shared memory. | |
| bool IsSharedMemory(); | |
| private: | |
| friend class ClientSharedImage; | |
| static std::unique_ptr<ScopedMapping> Create( | |
| SharedImageMetadata metadata_, | |
| MappableBuffer* mappable_buffer, | |
| bool is_already_mapped); | |
| static void StartCreateAsync( | |
| SharedImageMetadata metadata_, | |
| MappableBuffer* mappable_buffer, | |
| base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb); | |
| static void FinishCreateAsync( | |
| SharedImageMetadata metadata_, | |
| MappableBuffer* mappable_buffer, | |
| base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb, | |
| bool success); | |
| bool Init(MappableBuffer* mappable_buffer, bool is_already_mapped); | |
| // Uses UnprotectedInRelease for performance reasons (based on analysis of | |
| // MotionMark). | |
| raw_ptr<MappableBuffer, UnprotectedInRelease> buffer_ = nullptr; | |
| gfx::Size size_; | |
| viz::SharedImageFormat format_; | |
| }; | |
| // `sii_holder` must not be null. | |
| ClientSharedImage(const Mailbox& mailbox, | |
| const SharedImageInfo& info, | |
| const SyncToken& sync_token, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder, | |
| gfx::GpuMemoryBufferType gmb_type); | |
| // `sii_holder` must not be null. | |
| ClientSharedImage(const Mailbox& mailbox, | |
| const SharedImageInfo& info, | |
| const SyncToken& sync_token, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder, | |
| base::WritableSharedMemoryMapping mapping); | |
| // `sii_holder` must not be null. |shared_memory_pool| can be null and is only | |
| // used on windows platform. | |
| ClientSharedImage( | |
| const Mailbox& mailbox, | |
| const SharedImageInfo& info, | |
| const SyncToken& sync_token, | |
| GpuMemoryBufferHandleInfo handle_info, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder, | |
| scoped_refptr<base::UnsafeSharedMemoryPool> shared_memory_pool = nullptr); | |
| const Mailbox& mailbox() const { return mailbox_; } | |
| viz::SharedImageFormat format() const { return metadata_.format; } | |
| base::ByteSize EstimatedSizeInBytes() const { | |
| return base::ByteSize(format().EstimatedSizeInBytes(size()) * | |
| metadata_.array_layers); | |
| } | |
| gfx::Size size() const { return metadata_.size; } | |
| uint32_t array_layers() const { return metadata_.array_layers; } | |
| const gfx::ColorSpace& color_space() const { return metadata_.color_space; } | |
| GrSurfaceOrigin surface_origin() const { return metadata_.surface_origin; } | |
| SkAlphaType alpha_type() const { return metadata_.alpha_type; } | |
| SharedImageUsageSet usage() const { return metadata_.usage; } | |
| std::optional<gfx::BufferUsage> buffer_usage() const { return buffer_usage_; } | |
| std::string debug_label() const { return debug_label_; } | |
| bool is_software() const { return is_software_; } | |
| bool HasHolder() { return sii_holder_ != nullptr; } | |
| // The type of the underlying GpuMemoryBuffer backing this ClientSI. | |
| gfx::GpuMemoryBufferType GetGpuMemoryBufferType() const; | |
| // Whether the underlying buffer supports zero-copy import into WebGPU. | |
| bool SupportsZeroCopyWebGPUImport() const; | |
| // Returns a clone of the GpuMemoryBufferHandle associated with this ClientSI. | |
| // Valid to call only if this instance was created with a non-null | |
| // GpuMemoryBuffer. | |
| gfx::GpuMemoryBufferHandle CloneGpuMemoryBufferHandle() const; | |
| // Returns the GL texture target to use for this SharedImage. | |
| uint32_t GetTextureTarget(); | |
| base::trace_event::MemoryAllocatorDumpGuid GetGUIDForTracing() { | |
| return gpu::GetSharedImageGUIDForTracing(mailbox_); | |
| } | |
| // Maps |mailbox| into CPU visible memory and returns a ScopedMapping object | |
| // which can be used to read/write to the CPU mapped memory. The SharedImage | |
| // backing this ClientSI must have been created with CPU_READ/CPU_WRITE usage. | |
| std::unique_ptr<ScopedMapping> Map(); | |
| // Maps |mailbox| into CPU visible memory and returns a ScopedMapping object | |
| // which can be used to read/write to the CPU mapped memory. The SharedImage | |
| // backing this ClientSI must have been created with CPU_READ/CPU_WRITE usage. | |
| // Default implementation is blocking. However, on some platforms, where | |
| // possible, the implementation is non-blocking and may execute the callback | |
| // on the GpuMemoryThread. But if no GPU work is necessary, it still may | |
| // execute the callback immediately in the current sequence. Note: `this` must | |
| // be kept alive until the result callback is executed. | |
| void MapAsync( | |
| base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb); | |
| // Returns an unowned copy of the current ClientSharedImage. This function | |
| // is a temporary workaround for the situation where a ClientSharedImage may | |
| // have more than one reference when being destroyed. | |
| // TODO(crbug.com/40286368): Remove this function once ClientSharedImage | |
| // can properly handle shared image destruction internally. | |
| scoped_refptr<ClientSharedImage> MakeUnowned(); | |
| ExportedSharedImage Export(bool with_buffer_handle = false); | |
| // Returns an unowned reference for the underlying shared image backing. The | |
| // caller should ensure that the original shared image backing created in | |
| // client process outlives this reference. Note that it is preferable to use | |
| // SharedImageInterface::ImportSharedImage() instead, which returns an owning | |
| // reference, where the underlying shared image backing stays alive in gpu | |
| // process even if original ClientSharedImage goes away. | |
| static scoped_refptr<ClientSharedImage> ImportUnowned( | |
| ExportedSharedImage exported_shared_image); | |
| static void CreateGpuFenceForSyncTokens( | |
| std::vector<scoped_refptr<ClientSharedImage>> shared_images, | |
| std::vector<SyncToken> sync_tokens, | |
| gles2::GLES2Interface* gl, | |
| ContextSupport* context_support, | |
| base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback); | |
| static uint64_t SignalLatestSyncToken( | |
| std::vector<scoped_refptr<ClientSharedImage>> shared_images, | |
| std::vector<SyncToken> sync_tokens, | |
| base::OnceClosure callback, | |
| SharedImageInterface* sii, | |
| ContextSupport* context_support, | |
| uint64_t pending_callback_id); | |
| static void SignalLatestSyncToken( | |
| std::vector<scoped_refptr<ClientSharedImage>> shared_images, | |
| std::vector<SyncToken> sync_tokens, | |
| base::OnceClosure callback, | |
| SharedImageInterface* sii); | |
| // When the UseAutomaticSyncTokenManagement feature is enabled, this function | |
| // checks if all tracked SyncTokens (excluding the creation SyncToken) have | |
| // been signaled according to ContextSupport, ignoring `resource_sync_token`. | |
| // When the feature is disabled, this function only checks | |
| // `resource_sync_token` instead, ignoring the internal SyncToken map. | |
| bool IsSyncTokenSignaled(ContextSupport* context_support, | |
| const SyncToken& resource_sync_token); | |
| // When the UseAutomaticSyncTokenManagement feature is enabled, this function | |
| // returns all tracked SyncTokens for this SharedImage. When the feature is | |
| // disabled, this function returns a 1-element vector containing the input | |
| // SyncToken (if the input SyncToken is valid), or an empty vector (if the | |
| // input SyncToken is empty). Note that all SyncTokens in the returned vector | |
| // are non-empty, regardless of whether UseAutomaticSyncTokenManagement is | |
| // enabled. | |
| std::vector<SyncToken> GetSyncTokensForDisplayCompositor( | |
| const SyncToken& sync_token); | |
| // In automatic SyncToken management mode, stores the SyncToken generated by | |
| // the display compositor when it finishes accessing this SharedImage. | |
| void EndDisplayCompositorAccess(const SyncToken& sync_token); | |
| void UpdateDestructionSyncToken(const gpu::SyncToken& sync_token) { | |
| destruction_sync_token_ = sync_token; | |
| } | |
| // Signals the service-side that the backing of this SharedImage was modified | |
| // on the CPU or through external devices. `sync_token` can be passed to order | |
| // the processing of the signal. Returns a SyncToken that the caller can use | |
| // to ensure that any future service-side accesses to this SharedImage are | |
| // sequenced with respect to this call being processed. | |
| gpu::SyncToken BackingWasExternallyUpdated(const gpu::SyncToken& sync_token); | |
| // Similar to the function above, except that this overloaded version accepts | |
| // GpuFence. This version is used in ArImageTransport. | |
| gpu::SyncToken BackingWasExternallyUpdated( | |
| std::unique_ptr<gfx::GpuFence> fence); | |
| // Creates a ClientSharedImage that is not associated with any | |
| // SharedImageInterface for testing. | |
| static scoped_refptr<ClientSharedImage> CreateForTesting(); | |
| static scoped_refptr<ClientSharedImage> CreateSoftwareForTesting(); | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| viz::SharedImageFormat format, | |
| uint32_t texture_target); | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| const gfx::ColorSpace& color_space); | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| SharedImageUsageSet usage); | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| const SharedImageMetadata& metadata); | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| const SharedImageMetadata& metadata, | |
| uint32_t texture_target); | |
| using AsyncMapCompletionCallback = base::OnceCallback<void(bool)>; | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| const Mailbox& mailbox, | |
| const SharedImageMetadata& metadata, | |
| const SyncToken& sync_token, | |
| uint32_t texture_target, | |
| bool is_software = false); | |
| // Used to control execution of `MapAsync()` completion callbacks. On a | |
| // `MapAsync()` invocation the completion callback will be passed to this | |
| // callback, which can execute it as the test requires. | |
| using AsyncMapInvokedCallback = | |
| base::RepeatingCallback<void(AsyncMapCompletionCallback)>; | |
| static scoped_refptr<ClientSharedImage> CreateForTesting( | |
| const Mailbox& mailbox, | |
| const SharedImageMetadata& metadata, | |
| const SyncToken& sync_token, | |
| bool premapped, | |
| const AsyncMapInvokedCallback& callback, | |
| gfx::BufferUsage buffer_usage, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder); | |
| const SyncToken& creation_sync_token() const { return creation_sync_token_; } | |
| void OnMemoryDump( | |
| base::trace_event::ProcessMemoryDump* pmd, | |
| const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, | |
| int importance); | |
| // Creates a GL Texture from the current SharedImage for the provided | |
| // GLES2Interface. | |
| std::unique_ptr<SharedImageTexture> CreateGLTexture( | |
| gles2::GLES2Interface* gl); | |
| // Creates a RasterScopedAccess object from the current SharedImage for the | |
| // provided raster interface. | |
| std::unique_ptr<RasterScopedAccess> BeginRasterAccess( | |
| InterfaceBase* raster_interface, | |
| const SyncToken& sync_token, | |
| bool readonly); | |
| // This is used for CopySharedImageToTextureINTERNAL, where we need GL access | |
| // but do not create a GL texture. | |
| std::unique_ptr<RasterScopedAccess> BeginGLAccessForCopySharedImage( | |
| InterfaceBase* gl_interface, | |
| const SyncToken& sync_token, | |
| bool readonly); | |
| std::unique_ptr<WebGPUTextureScopedAccess> BeginWebGPUTextureAccess( | |
| webgpu::WebGPUInterface* webgpu, | |
| const SyncToken& sync_token, | |
| const wgpu::dawn::wire::client::Device& device, | |
| const wgpu::dawn::wire::client::TextureDescriptor& desc, | |
| uint64_t usage, | |
| webgpu::MailboxFlags mailbox_flags); | |
| std::unique_ptr<WebGPUBufferScopedAccess> BeginWebGPUBufferAccess( | |
| webgpu::WebGPUInterface* webgpu, | |
| const SyncToken& sync_token, | |
| const wgpu::dawn::wire::client::Device& device, | |
| const wgpu::dawn::wire::client::BufferDescriptor& desc, | |
| uint64_t usage, | |
| webgpu::MailboxFlags mailbox_flags); | |
| // Pack the SharedImageExportResult. | |
| SharedImageExportResult EndImport(const SyncToken& sync_token); | |
| SharedImageExportResult EndImport(const std::vector<SyncToken>& sync_tokens); | |
| // Unpack the SharedImageExportResult. | |
| // This version expects an empty or a single-SyncToken export result. | |
| SyncToken EndExport(SharedImageExportResult&& result); | |
| std::vector<SyncToken> EndExportAsVector(SharedImageExportResult&& result); | |
| #if BUILDFLAG(IS_WIN) | |
| // Allows client to indicate the |gpu_memory_buffer_| to pre map its shared | |
| // memory region internally for performance optimization purposes. It is only | |
| // used on windows. | |
| void SetUsePreMappedMemory(bool use_premapped_memory); | |
| #endif | |
| private: | |
| friend class base::RefCountedThreadSafe<ClientSharedImage>; | |
| friend class SharedImageTexture; | |
| ~ClientSharedImage(); | |
| std::unique_ptr<MappableBuffer> CreateMappableBufferFromHandle( | |
| gfx::GpuMemoryBufferHandle handle, | |
| const gfx::Size& size, | |
| viz::SharedImageFormat format, | |
| gfx::BufferUsage usage, | |
| gpu::SharedImageUsageSet si_usage, | |
| scoped_refptr<base::UnsafeSharedMemoryPool> pool = nullptr); | |
| // This constructor is used only when importing an owned ClientSharedImage, | |
| // which should only be done via implementations of | |
| // SharedImageInterface::ImportSharedImage(). | |
| // `sii_holder` must not be null. | |
| friend class ClientSharedImageInterface; | |
| friend class GpuChannelSharedImageInterface; | |
| friend class RasterScopedAccess; | |
| friend class TestSharedImageInterface; | |
| friend class media::VideoFrame; | |
| friend class WebGPUTextureScopedAccess; | |
| friend class WebGPUBufferScopedAccess; | |
| ClientSharedImage(const Mailbox& mailbox, | |
| const SharedImageInfo& info, | |
| const SyncToken& sync_token, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder, | |
| uint32_t texture_target); | |
| ClientSharedImage(ExportedSharedImage exported_si, | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder); | |
| // This constructor is used only when importing an unowned ClientSharedImage, | |
| // in which case this ClientSharedImage is not associated with a | |
| // SharedImageInterface. | |
| explicit ClientSharedImage(ExportedSharedImage exported_si); | |
| friend class ::viz::CopyOutputSharedImageResult; | |
| // Creates unowned (no `sii_holder`) `ClientSharedImage` | |
| explicit ClientSharedImage(const Mailbox& mailbox, | |
| const SharedImageInfo& info); | |
| // VideoFrame needs this info currently for MappableSI. | |
| // TODO(crbug.com/40263579): Once MappableSI is fully launched for VideoFrame, | |
| // VF can be refactored to behave like OPAQUE storage which does not need | |
| // layout info and hence stride. This method will then no longer needed and | |
| // can be removed. | |
| size_t GetStrideForVideoFrame(uint32_t plane_index) const; | |
| // Returns whether the underlying resource is shared memory without needing to | |
| // Map() the shared image. This method is supposed to be used by VideoFrame | |
| // temporarily as mentioned above in ::GetStrideForVideoFrame(). | |
| bool IsSharedMemoryForVideoFrame() const; | |
| bool AsyncMappingIsNonBlocking() const; | |
| void CopyNativeGmbToSharedMemoryAsync( | |
| gfx::GpuMemoryBufferHandle buffer_handle, | |
| base::UnsafeSharedMemoryRegion memory_region, | |
| base::OnceCallback<void(bool)> callback); | |
| // Collect all SyncTokens stored in the internal map. | |
| std::vector<SyncToken> CollectSyncTokensLocked() | |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); | |
| std::vector<SyncToken> CollectSyncTokens(); | |
| void WaitSyncTokenInternal(InterfaceBase* ib, const SyncToken& sync_token); | |
| // Helper function for `StoreSyncTokenInternal` and | |
| // `StoreSyncTokenVectorInternal`; Must be called while holding `lock_`. | |
| void StoreSyncTokenLocked(const SyncToken& sync_token) | |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); | |
| SyncToken StoreSyncTokenInternal(const SyncToken& sync_token); | |
| std::vector<SyncToken> StoreSyncTokenVectorInternal( | |
| const std::vector<SyncToken>& sync_tokens); | |
| SyncToken GenSyncTokenInternal(InterfaceBase* ib); | |
| // Verify SyncTokens in-place in `sync_token_map_` and collect them. | |
| std::vector<SyncToken> VerifyAndCollectSyncTokens(); | |
| void RunOnTaskRunner(MappableBuffer::CopyNativeBufferToShMemCallback callback, | |
| gfx::GpuMemoryBufferHandle buffer_handle, | |
| base::UnsafeSharedMemoryRegion memory_region, | |
| base::OnceCallback<void(bool)> result_cb); | |
| // This pair of functions are used by SharedImageTexture to notify | |
| // ClientSharedImage of the beginning and the end of a scoped access. | |
| void BeginAccess(bool readonly); | |
| void EndAccess(bool readonly); | |
| void FinishMapAsyncForTests( | |
| base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb, | |
| bool success); | |
| scoped_refptr<SharedImageInterface> GetSharedImageInterface(); | |
| const Mailbox mailbox_; | |
| const SharedImageMetadata metadata_; | |
| const std::string debug_label_; | |
| SyncToken creation_sync_token_; | |
| SyncToken destruction_sync_token_; | |
| // Every SyncToken stored in this map is guaranteed to be non-empty, as | |
| // enforced by StoreSyncTokenLocked(). | |
| base::flat_map<SyncPointClientId, SyncToken> sync_token_map_; | |
| std::unique_ptr<MappableBuffer> mappable_buffer_; | |
| std::optional<gfx::BufferUsage> buffer_usage_; | |
| scoped_refptr<SharedImageInterfaceHolder> sii_holder_; | |
| scoped_refptr<SharedImageInterface> sii_; | |
| // CopyNativeGmbToSharedMemoryAsync uses this task runner for | |
| // operations to prevent deadlocks. | |
| // | |
| // Deadlock Scenario: | |
| // 1. Client thread calls CopyGpuMemoryBufferAsync() with a completion | |
| // callback. | |
| // 2. Client thread blocks, waiting for an event which is often signaled by | |
| // the callback. | |
| // 3. If the copy ran on the client thread, the callback would also need to | |
| // run on the *same*, now-blocked thread. | |
| // 4. The callback can't run, the event isn't signaled, and a deadlock | |
| // occurs. | |
| // | |
| // Solution: | |
| // This dedicated task runner ensures the copy and callback execute | |
| // independently of the client thread, allowing the callback to signal the | |
| // event and prevent the deadlock. | |
| scoped_refptr<base::SingleThreadTaskRunner> | |
| copy_native_buffer_to_shmem_task_runner_; | |
| // The texture target returned by `GetTextureTarget()`. | |
| uint32_t texture_target_ = 0; | |
| bool is_software_ = false; | |
| AsyncMapInvokedCallback async_map_invoked_callback_for_testing_; | |
| bool premapped_for_testing_; | |
| // The number of active scoped read accesses. | |
| unsigned int num_readers_ GUARDED_BY(lock_) = 0; | |
| // Whether there exists an active scoped write access. | |
| bool has_writer_ GUARDED_BY(lock_) = false; | |
| base::Lock lock_; | |
| }; | |
| struct GPU_COMMAND_BUFFER_CLIENT_EXPORT ExportedSharedImage { | |
| public: | |
| ExportedSharedImage(); | |
| ~ExportedSharedImage(); | |
| ExportedSharedImage(const ExportedSharedImage& other) = delete; | |
| ExportedSharedImage& operator=(const ExportedSharedImage& other) = delete; | |
| ExportedSharedImage(ExportedSharedImage&& other); | |
| ExportedSharedImage& operator=(ExportedSharedImage&& other); | |
| ExportedSharedImage Clone() const; | |
| private: | |
| friend class ClientSharedImage; | |
| friend class SharedImageInterface; | |
| friend class ClientSharedImageInterface; | |
| friend class TestSharedImageInterface; | |
| friend struct mojo::StructTraits<gpu::mojom::ExportedSharedImageDataView, | |
| ExportedSharedImage>; | |
| FRIEND_TEST_ALL_PREFIXES(ClientSharedImageTest, ImportUnowned); | |
| FRIEND_TEST_ALL_PREFIXES( | |
| ClientSharedImageTest, | |
| ExportedSharedImageMojoDeserialization_TextureTargetZero); | |
| FRIEND_TEST_ALL_PREFIXES(ClientSharedImageTest, | |
| ExportedSharedImageMojoDeserialization_EmptyBuffer); | |
| FRIEND_TEST_ALL_PREFIXES(ClientSharedImageTest, | |
| ExportedSharedImageMojoDeserialization_ZeroMailbox); | |
| FRIEND_TEST_ALL_PREFIXES( | |
| ClientSharedImageTest, | |
| ExportedSharedImageMojoDeserialization_DuplicateManagedSyncTokens); | |
| FRIEND_TEST_ALL_PREFIXES( | |
| ClientSharedImageTest, | |
| ExportedSharedImageMojoDeserialization_ValidManagedSyncTokens); | |
| ExportedSharedImage(const Mailbox& mailbox, | |
| const SharedImageMetadata& metadata, | |
| const SyncToken& creation_sync_token, | |
| const std::vector<SyncToken>& managed_sync_tokens, | |
| std::string debug_label, | |
| std::optional<gfx::GpuMemoryBufferHandle> buffer_handle, | |
| std::optional<gfx::BufferUsage> buffer_usage, | |
| uint32_t texture_target, | |
| bool is_software); | |
| Mailbox mailbox_; | |
| SharedImageMetadata metadata_; | |
| SyncToken creation_sync_token_; | |
| std::vector<SyncToken> managed_sync_tokens_; | |
| std::string debug_label_; | |
| std::optional<gfx::GpuMemoryBufferHandle> buffer_handle_; | |
| std::optional<gfx::BufferUsage> buffer_usage_; | |
| uint32_t texture_target_ = 0; | |
| bool is_software_ = false; | |
| }; | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT SharedImageTexture { | |
| public: | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT ScopedAccess { | |
| public: | |
| ScopedAccess(const ScopedAccess&) = delete; | |
| ScopedAccess& operator=(const ScopedAccess&) = delete; | |
| ScopedAccess(ScopedAccess&&) = delete; | |
| ScopedAccess& operator=(ScopedAccess&&) = delete; | |
| ~ScopedAccess(); | |
| unsigned int texture_id() { return texture_->id(); } | |
| static SyncToken EndAccess( | |
| std::unique_ptr<ScopedAccess> scoped_shared_image); | |
| private: | |
| friend class SharedImageTexture; | |
| ScopedAccess(SharedImageTexture* texture, | |
| const SyncToken& sync_token, | |
| bool readonly); | |
| void DidEndAccess(); | |
| const raw_ptr<SharedImageTexture> texture_; | |
| const bool readonly_; | |
| bool is_access_ended_ = false; | |
| }; | |
| SharedImageTexture(const SharedImageTexture&) = delete; | |
| SharedImageTexture& operator=(const SharedImageTexture&) = delete; | |
| SharedImageTexture(SharedImageTexture&&) = delete; | |
| SharedImageTexture& operator=(SharedImageTexture&&) = delete; | |
| ~SharedImageTexture(); | |
| std::unique_ptr<ScopedAccess> BeginAccess(const SyncToken& sync_token, | |
| bool readonly); | |
| void DidEndAccess(bool readonly); | |
| unsigned int id() { return id_; } | |
| private: | |
| friend class ClientSharedImage; | |
| SharedImageTexture(gles2::GLES2Interface* gl, | |
| ClientSharedImage* shared_image); | |
| const raw_ptr<gles2::GLES2Interface> gl_; | |
| const raw_ptr<gpu::ClientSharedImage> shared_image_; | |
| unsigned int id_ = 0; | |
| bool has_active_access_ = false; | |
| }; | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT RasterScopedAccess { | |
| public: | |
| RasterScopedAccess(const RasterScopedAccess&) = delete; | |
| RasterScopedAccess& operator=(const RasterScopedAccess&) = delete; | |
| RasterScopedAccess(RasterScopedAccess&&) = delete; | |
| RasterScopedAccess& operator=(RasterScopedAccess&&) = delete; | |
| ~RasterScopedAccess() = default; | |
| static SyncToken EndAccess( | |
| std::unique_ptr<RasterScopedAccess> scoped_shared_image); | |
| private: | |
| friend class ClientSharedImage; | |
| RasterScopedAccess(InterfaceBase* raster_interface, | |
| ClientSharedImage* shared_image, | |
| const SyncToken& sync_token, | |
| bool readonly); | |
| const raw_ptr<InterfaceBase> raster_interface_; | |
| const raw_ptr<ClientSharedImage> shared_image_; | |
| bool readonly_; | |
| }; | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT WebGPUTextureScopedAccess { | |
| public: | |
| WebGPUTextureScopedAccess(const WebGPUTextureScopedAccess&) = delete; | |
| WebGPUTextureScopedAccess& operator=(const WebGPUTextureScopedAccess&) = | |
| delete; | |
| WebGPUTextureScopedAccess(WebGPUTextureScopedAccess&&) = delete; | |
| WebGPUTextureScopedAccess& operator=(WebGPUTextureScopedAccess&&) = delete; | |
| ~WebGPUTextureScopedAccess(); | |
| static SyncToken EndAccess( | |
| std::unique_ptr<WebGPUTextureScopedAccess> scoped_access); | |
| void SetNeedsPresent(bool needs_present); | |
| const wgpu::dawn::wire::client::Texture& texture(); | |
| // This method is used to clear the context before the object is destroyed. | |
| // This is necessary to avoid a dangling pointer crash when the context is | |
| // lost. | |
| void ClearContext(); | |
| private: | |
| friend class ClientSharedImage; | |
| WebGPUTextureScopedAccess( | |
| webgpu::WebGPUInterface* webgpu, | |
| ClientSharedImage* shared_image, | |
| const SyncToken& sync_token, | |
| const wgpu::dawn::wire::client::Device& device, | |
| const wgpu::dawn::wire::client::TextureDescriptor& desc, | |
| uint64_t usage, | |
| webgpu::MailboxFlags mailbox_flags); | |
| raw_ptr<webgpu::WebGPUInterface> webgpu_; | |
| std::unique_ptr<wgpu::dawn::wire::client::Texture> texture_; | |
| raw_ptr<gpu::ClientSharedImage> shared_image_; | |
| uint32_t device_id_ = 0; | |
| uint32_t device_generation_ = 0; | |
| uint32_t texture_id_ = 0; | |
| uint32_t texture_generation_ = 0; | |
| bool needs_present_ = false; | |
| bool readonly_; | |
| }; | |
| class GPU_COMMAND_BUFFER_CLIENT_EXPORT WebGPUBufferScopedAccess { | |
| public: | |
| WebGPUBufferScopedAccess(const WebGPUBufferScopedAccess&) = delete; | |
| WebGPUBufferScopedAccess& operator=(const WebGPUBufferScopedAccess&) = delete; | |
| WebGPUBufferScopedAccess(WebGPUBufferScopedAccess&&) = delete; | |
| WebGPUBufferScopedAccess& operator=(WebGPUBufferScopedAccess&&) = delete; | |
| ~WebGPUBufferScopedAccess(); | |
| static SyncToken EndAccess( | |
| std::unique_ptr<WebGPUBufferScopedAccess> scoped_access); | |
| const wgpu::dawn::wire::client::Buffer& buffer(); | |
| private: | |
| friend class ClientSharedImage; | |
| WebGPUBufferScopedAccess( | |
| webgpu::WebGPUInterface* webgpu, | |
| ClientSharedImage* shared_image, | |
| const SyncToken& sync_token, | |
| const wgpu::dawn::wire::client::Device& device, | |
| const wgpu::dawn::wire::client::BufferDescriptor& desc, | |
| uint64_t usage, | |
| webgpu::MailboxFlags mailbox_flags); | |
| const raw_ptr<webgpu::WebGPUInterface> webgpu_; | |
| std::unique_ptr<wgpu::dawn::wire::client::Buffer> buffer_; | |
| raw_ptr<gpu::ClientSharedImage> shared_image_; | |
| uint32_t buffer_id_ = 0; | |
| uint32_t buffer_generation_ = 0; | |
| }; | |
| } // namespace gpu | |
| #endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_SHARED_IMAGE_H_ |