| // Copyright 2022 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_SERVICE_SHARED_IMAGE_COMPOUND_IMAGE_BACKING_H_ |
| #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_COMPOUND_IMAGE_BACKING_H_ |
| |
| #include <vector> |
| |
| #include "base/containers/enum_set.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "gpu/command_buffer/common/mailbox.h" |
| #include "gpu/command_buffer/common/shared_image_usage.h" |
| #include "gpu/command_buffer/service/memory_tracking.h" |
| #include "gpu/command_buffer/service/shared_image/shared_image_backing.h" |
| #include "gpu/command_buffer/service/shared_image/shared_image_manager.h" |
| #include "gpu/command_buffer/service/shared_image/shared_image_representation.h" |
| #include "gpu/command_buffer/service/shared_image/shared_memory_image_backing.h" |
| #include "gpu/command_buffer/service/shared_memory_region_wrapper.h" |
| #include "gpu/gpu_gles2_export.h" |
| #include "gpu/ipc/common/surface_handle.h" |
| #include "ui/gfx/color_space.h" |
| #include "ui/gfx/geometry/size.h" |
| |
| namespace gpu { |
| |
| class D3DImageBackingFactoryTest; |
| class SharedImageBackingFactory; |
| class SharedImageCopyManager; |
| class SharedImageFactory; |
| |
| // TODO(kylechar): Merge with OzoneImageBacking::AccessStream enum. |
| enum class SharedImageAccessStream { |
| kSkia, |
| kOverlay, |
| kGL, |
| kDawn, |
| kMemory, |
| kVaapi |
| }; |
| |
| // Used to represent what access streams a backing can be used for. |
| using AccessStreamSet = base::EnumSet<SharedImageAccessStream, |
| SharedImageAccessStream::kSkia, |
| SharedImageAccessStream::kVaapi>; |
| |
| // A compound backing that combines a shared memory backing and real GPU |
| // backing. The real GPU backing must implement `UploadFromMemory()` and not |
| // have its own shared memory segment. |
| // TODO(crbug.com/40213543): Support multiple GPU backings. |
| class GPU_GLES2_EXPORT CompoundImageBacking : public SharedImageBacking { |
| public: |
| using CreateBackingCallback = |
| base::OnceCallback<void(std::unique_ptr<SharedImageBacking>&)>; |
| |
| static bool IsValidSharedMemoryBufferFormat(const gfx::Size& size, |
| viz::SharedImageFormat format); |
| |
| // Remove the SCANOUT flag if |kAllowShmOverlays|. |
| static SharedImageUsageSet GetGpuSharedImageUsage(SharedImageUsageSet usage); |
| |
| // Creates a backing that contains a shared memory backing and GPU backing |
| // provided by `shared_image_factory` based on `usage`. Eventually, instead of |
| // creating a shm+gpu backing, this method will have various strategy to |
| // allocate different combination of backings based on the `usage`. |
| static std::unique_ptr<SharedImageBacking> Create( |
| SharedImageFactory* shared_image_factory, |
| scoped_refptr<SharedImageCopyManager> copy_manager, |
| const Mailbox& mailbox, |
| gfx::GpuMemoryBufferHandle handle, |
| viz::SharedImageFormat format, |
| const gfx::Size& size, |
| const gfx::ColorSpace& color_space, |
| GrSurfaceOrigin surface_origin, |
| SkAlphaType alpha_type, |
| SharedImageUsageSet usage, |
| std::string debug_label); |
| |
| // Creates a backing that contains a shared memory backing and GPU backing |
| // provided by `shared_image_factory` based on `usage`. Eventually, instead of |
| // creating a shm+gpu backing, this method will have various strategy to |
| // allocate different combination of backings based on the `usage`. |
| // We additionally pass a |buffer_usage| parameter here in order to create a |
| // CPU mappable by creating a shared memory handle. |
| // TODO(crbug.com/40276878): Remove this method once we figure out the mapping |
| // between SharedImageUsage and BufferUsage and no longer need to use |
| // BufferUsage. |
| static std::unique_ptr<SharedImageBacking> Create( |
| SharedImageFactory* shared_image_factory, |
| scoped_refptr<SharedImageCopyManager> copy_manager, |
| const Mailbox& mailbox, |
| viz::SharedImageFormat format, |
| const gfx::Size& size, |
| const gfx::ColorSpace& color_space, |
| GrSurfaceOrigin surface_origin, |
| SkAlphaType alpha_type, |
| SharedImageUsageSet usage, |
| std::string debug_label, |
| gfx::BufferUsage buffer_usage); |
| |
| ~CompoundImageBacking() override; |
| |
| // Called by wrapped representations before access. This will update |
| // the backing that is going to be accessed if most recent pixels are in |
| // a different backing. |
| void NotifyBeginAccess(SharedImageBacking* backing, |
| RepresentationAccessMode mode); |
| |
| // SharedImageBacking implementation. |
| SharedImageBackingType GetType() const override; |
| void Update(std::unique_ptr<gfx::GpuFence> in_fence) override; |
| bool CopyToGpuMemoryBuffer() override; |
| void CopyToGpuMemoryBufferAsync( |
| base::OnceCallback<void(bool)> callback) override; |
| gfx::Rect ClearedRect() const override; |
| void SetClearedRect(const gfx::Rect& cleared_rect) override; |
| void OnAddSecondaryReference() override; |
| |
| // CompoundImageBacking is registered as the primary backing while creating a |
| // SharedImageRepresentationFactoryRef whereas the underlying |
| // elements/backings it holds are not. Since the MarkForDestruction() method |
| // in SharedImageRepresentationFactoryRef only runs for primary backing, |
| // CompoundImageBacking needs to propagate this call to all its elements. |
| void MarkForDestruction() override; |
| gfx::GpuMemoryBufferHandle GetGpuMemoryBufferHandle() override; |
| |
| protected: |
| // SharedImageBacking implementation. |
| std::unique_ptr<DawnImageRepresentation> ProduceDawn( |
| SharedImageManager* manager, |
| MemoryTypeTracker* tracker, |
| const wgpu::Device& device, |
| wgpu::BackendType backend_type, |
| std::vector<wgpu::TextureFormat> view_formats, |
| scoped_refptr<SharedContextState> context_state) override; |
| std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture( |
| SharedImageManager* manager, |
| MemoryTypeTracker* tracker) override; |
| std::unique_ptr<GLTexturePassthroughImageRepresentation> |
| ProduceGLTexturePassthrough(SharedImageManager* manager, |
| MemoryTypeTracker* tracker) override; |
| std::unique_ptr<SkiaGaneshImageRepresentation> ProduceSkiaGanesh( |
| SharedImageManager* manager, |
| MemoryTypeTracker* tracker, |
| scoped_refptr<SharedContextState> context_state) override; |
| std::unique_ptr<SkiaGraphiteImageRepresentation> ProduceSkiaGraphite( |
| SharedImageManager* manager, |
| MemoryTypeTracker* tracker, |
| scoped_refptr<SharedContextState> context_state) override; |
| std::unique_ptr<OverlayImageRepresentation> ProduceOverlay( |
| SharedImageManager* manager, |
| MemoryTypeTracker* tracker) override; |
| |
| private: |
| friend class CompoundImageBackingTest; |
| friend class D3DImageBackingFactoryTest; |
| |
| // Holds one element, aka SharedImageBacking and related information, that |
| // makes up the compound. |
| struct ElementHolder { |
| public: |
| ElementHolder(); |
| ElementHolder(const ElementHolder& other) = delete; |
| ElementHolder& operator=(const ElementHolder& other) = delete; |
| ElementHolder(ElementHolder&& other); |
| ElementHolder& operator=(ElementHolder&& other); |
| ~ElementHolder(); |
| |
| // Will invoke `create_callback` to create backing if |
| // required. |
| void CreateBackingIfNecessary(); |
| |
| // Returns the backing. Will call `CreateBackingIfNecessary()`. |
| SharedImageBacking* GetBacking(); |
| |
| AccessStreamSet access_streams; |
| uint32_t content_id_ = 0; |
| |
| CreateBackingCallback create_callback; |
| std::unique_ptr<SharedImageBacking> backing; |
| }; |
| |
| // Creates a backing that contains a shared memory backing and GPU backing |
| // provided by `gpu_backing_factory`. |
| static std::unique_ptr<SharedImageBacking> CreateSharedMemoryForTesting( |
| SharedImageBackingFactory* gpu_backing_factory, |
| scoped_refptr<SharedImageCopyManager> copy_manager, |
| const Mailbox& mailbox, |
| gfx::GpuMemoryBufferHandle handle, |
| viz::SharedImageFormat format, |
| const gfx::Size& size, |
| const gfx::ColorSpace& color_space, |
| GrSurfaceOrigin surface_origin, |
| SkAlphaType alpha_type, |
| SharedImageUsageSet usage, |
| std::string debug_label); |
| |
| // Creates a backing that contains a shared memory backing and GPU backing |
| // provided by `gpu_backing_factory`. We additionally pass a |buffer_usage| |
| // parameter here in order to create a CPU mappable by creating a shared |
| // memory handle. |
| // TODO(crbug.com/40276878): Remove this method once we figure out the mapping |
| // between SharedImageUsage and BufferUsage and no longer need to use |
| // BufferUsage. |
| static std::unique_ptr<SharedImageBacking> CreateSharedMemoryForTesting( |
| SharedImageBackingFactory* gpu_backing_factory, |
| scoped_refptr<SharedImageCopyManager> copy_manager, |
| const Mailbox& mailbox, |
| viz::SharedImageFormat format, |
| const gfx::Size& size, |
| const gfx::ColorSpace& color_space, |
| GrSurfaceOrigin surface_origin, |
| SkAlphaType alpha_type, |
| SharedImageUsageSet usage, |
| std::string debug_label, |
| gfx::BufferUsage buffer_usage); |
| |
| CompoundImageBacking( |
| const Mailbox& mailbox, |
| viz::SharedImageFormat format, |
| const gfx::Size& size, |
| const gfx::ColorSpace& color_space, |
| GrSurfaceOrigin surface_origin, |
| SkAlphaType alpha_type, |
| SharedImageUsageSet usage, |
| std::string debug_label, |
| std::unique_ptr<SharedImageBacking> shm_backing, |
| base::WeakPtr<SharedImageFactory> shared_image_factory, |
| base::WeakPtr<SharedImageBackingFactory> gpu_backing_factory, |
| scoped_refptr<SharedImageCopyManager> copy_manager, |
| std::optional<gfx::BufferUsage> buffer_usage = std::nullopt); |
| |
| base::trace_event::MemoryAllocatorDump* OnMemoryDump( |
| const std::string& dump_name, |
| base::trace_event::MemoryAllocatorDumpGuid client_guid, |
| base::trace_event::ProcessMemoryDump* pmd, |
| uint64_t client_tracing_id) override; |
| |
| // Returns a SkPixmap for shared memory backing. |
| const std::vector<SkPixmap>& GetSharedMemoryPixmaps(); |
| |
| // Returns the shared memory element used for access stream |
| // SharedImageAccessStream::kMemory. There can be only 1 shared memory element |
| // at most. |
| ElementHolder& GetShmElement(); |
| |
| // Gets the element corresponding to the backing. |
| ElementHolder* GetElement(const SharedImageBacking* backing); |
| |
| // Finds the element which has the most recent data/content irrespective of |
| // the stream. There could be multiple elements which has the most recent |
| // data. This method finds the first element which has most recent data. |
| ElementHolder* GetElementWithLatestContent(); |
| |
| // Gets or allocates a backing for a given |stream|. |
| // If a backing with a given |stream| is present, it will either return the |
| // backing with the latest content OR will return any supported backing (the |
| // first one it finds). |
| // If no backing is found, then it will allocate an appropriate backing which |
| // can support the |stream|. |
| SharedImageBacking* GetOrAllocateBacking(SharedImageAccessStream stream); |
| |
| // Returns the gpu backing from the list of |element_| which has a shm and a |
| // gpu backing. |
| SharedImageBacking* GetGpuBacking(); |
| |
| bool HasLatestContent(ElementHolder& element); |
| |
| // Sets the element used for `stream` as having the latest content. If |
| // `write_access` is true then only that element has the latest content. |
| void SetLatestContent(SharedImageAccessStream stream, bool write_access); |
| |
| // Runs CreateSharedImage() on `factory` and stores the result in `backing`. |
| // If successful this will update the estimated size of compound backing. |
| void CreateBackingFromBackingFactory( |
| base::WeakPtr<SharedImageBackingFactory> factory, |
| std::string debug_label, |
| std::unique_ptr<SharedImageBacking>& backing); |
| |
| void OnCopyToGpuMemoryBufferComplete(bool success); |
| |
| // This is required for CompoundImageBacking to be able to query an |
| // appropriate SharedImageBackingFactory dynamically based on clients |
| // required usage(Produce*) which typically happens after the backing |
| // creation time. WeakPtr since backings can outlive SharedImageFactory. |
| // Note that CompoundImageBacking is not thread-safe at this moment and |
| // we would need to switch WeakPtr to something else if we make it |
| // thread-safe. |
| base::WeakPtr<SharedImageFactory> shared_image_factory_; |
| |
| uint32_t latest_content_id_ = 1; |
| |
| // Holds all of the "element" backings that make up this compound backing. For |
| // each there is a backing, set of streams and tracking for latest content. |
| // |
| // It's expected that for each access stream there is exactly one element used |
| // to access it. Note that it's possible the backing for a given access stream |
| // can't actually support that type of usage, in which case the backing will |
| // be null or the ProduceX() call will just fail. |
| // As of now, CompoundImageBacking only has 2 backings,i.e., 1 shm and 1 gpu |
| // backing. In future, it will evolve into a dynamic CompoundImageBacking |
| // where it can have any number of gpu backings and at most 1 cpu backing. |
| std::vector<ElementHolder> elements_; |
| |
| base::OnceCallback<void(bool)> pending_copy_to_gmb_callback_; |
| |
| scoped_refptr<SharedImageCopyManager> copy_manager_; |
| }; |
| |
| } // namespace gpu |
| |
| #endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_COMPOUND_IMAGE_BACKING_H_ |