1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_
6 #define GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/memory/scoped_refptr.h"
12 #include "base/util/type_safety/pass_key.h"
13 #include "components/viz/common/gpu/vulkan_context_provider.h"
14 #include "gpu/command_buffer/common/shared_image_usage.h"
15 #include "gpu/command_buffer/service/external_semaphore.h"
16 #include "gpu/command_buffer/service/external_semaphore_pool.h"
17 #include "gpu/command_buffer/service/shared_context_state.h"
18 #include "gpu/command_buffer/service/shared_image_backing.h"
19 #include "gpu/command_buffer/service/shared_memory_region_wrapper.h"
20 #include "gpu/command_buffer/service/texture_manager.h"
21 #include "gpu/vulkan/vulkan_device_queue.h"
22 #include "ui/gfx/gpu_memory_buffer.h"
23 
24 namespace gpu {
25 
26 class VulkanCommandPool;
27 class VulkanImage;
28 
29 struct VulkanImageUsageCache {
30   // Maximal usage flags for VK_IMAGE_TILING_OPTIMAL each ResourceFormat.
31   VkImageUsageFlags optimal_tiling_usage[viz::RESOURCE_FORMAT_MAX + 1];
32 };
33 
34 class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking {
35  public:
36   static std::unique_ptr<ExternalVkImageBacking> Create(
37       scoped_refptr<SharedContextState> context_state,
38       VulkanCommandPool* command_pool,
39       const Mailbox& mailbox,
40       viz::ResourceFormat format,
41       const gfx::Size& size,
42       const gfx::ColorSpace& color_space,
43       GrSurfaceOrigin surface_origin,
44       SkAlphaType alpha_type,
45       uint32_t usage,
46       const VulkanImageUsageCache* image_usage_cache,
47       base::span<const uint8_t> pixel_data,
48       bool using_gmb = false);
49 
50   static std::unique_ptr<ExternalVkImageBacking> CreateFromGMB(
51       scoped_refptr<SharedContextState> context_state,
52       VulkanCommandPool* command_pool,
53       const Mailbox& mailbox,
54       gfx::GpuMemoryBufferHandle handle,
55       gfx::BufferFormat buffer_format,
56       const gfx::Size& size,
57       const gfx::ColorSpace& color_space,
58       GrSurfaceOrigin surface_origin,
59       SkAlphaType alpha_type,
60       uint32_t usage,
61       const VulkanImageUsageCache* image_usage_cache);
62 
63   ExternalVkImageBacking(util::PassKey<ExternalVkImageBacking>,
64                          const Mailbox& mailbox,
65                          viz::ResourceFormat format,
66                          const gfx::Size& size,
67                          const gfx::ColorSpace& color_space,
68                          GrSurfaceOrigin surface_origin,
69                          SkAlphaType alpha_type,
70                          uint32_t usage,
71                          scoped_refptr<SharedContextState> context_state,
72                          std::unique_ptr<VulkanImage> image,
73                          VulkanCommandPool* command_pool,
74                          bool use_separate_gl_texture);
75 
76   ~ExternalVkImageBacking() override;
77 
context_state()78   SharedContextState* context_state() const { return context_state_.get(); }
backend_texture()79   const GrBackendTexture& backend_texture() const { return backend_texture_; }
image()80   VulkanImage* image() const { return image_.get(); }
GetTexturePassthrough()81   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
82       const {
83     return texture_passthrough_;
84   }
context_provider()85   viz::VulkanContextProvider* context_provider() const {
86     return context_state()->vk_context_provider();
87   }
vulkan_implementation()88   VulkanImplementation* vulkan_implementation() const {
89     return context_provider()->GetVulkanImplementation();
90   }
fence_helper()91   VulkanFenceHelper* fence_helper() const {
92     return context_provider()->GetDeviceQueue()->GetFenceHelper();
93   }
external_semaphore_pool()94   ExternalSemaphorePool* external_semaphore_pool() {
95     return context_state()->external_semaphore_pool();
96   }
use_separate_gl_texture()97   bool use_separate_gl_texture() const { return use_separate_gl_texture_; }
need_synchronization()98   bool need_synchronization() const {
99     if (usage() & SHARED_IMAGE_USAGE_WEBGPU) {
100       return true;
101     }
102 
103     if (usage() & SHARED_IMAGE_USAGE_GLES2) {
104       return !use_separate_gl_texture() && (texture_ || texture_passthrough_);
105     }
106 
107     if (usage() & SHARED_IMAGE_USAGE_SCANOUT) {
108       return true;
109     }
110 
111     return false;
112   }
reads_in_progress()113   uint32_t reads_in_progress() const { return reads_in_progress_; }
gl_reads_in_progress()114   uint32_t gl_reads_in_progress() const { return gl_reads_in_progress_; }
115 
116   // Notifies the backing that an access will start. Return false if there is
117   // currently any other conflict access in progress. Otherwise, returns true
118   // and semaphores which will be waited on before accessing.
119   bool BeginAccess(bool readonly,
120                    std::vector<ExternalSemaphore>* external_semaphores,
121                    bool is_gl);
122 
123   // Notifies the backing that an access has ended. The representation must
124   // provide a semaphore handle that has been signaled at the end of the write
125   // access.
126   void EndAccess(bool readonly,
127                  ExternalSemaphore external_semaphore,
128                  bool is_gl);
129 
130   // SharedImageBacking implementation.
131   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
132   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
133   scoped_refptr<gfx::NativePixmap> GetNativePixmap() override;
134 
135   // Add semaphores to a pending list for reusing or being released immediately.
136   void AddSemaphoresToPendingListOrRelease(
137       std::vector<ExternalSemaphore> semaphores);
138   // Return |pending_semaphores_| and passed in |semaphores| to
139   // ExternalSemaphorePool for reusing.
140   void ReturnPendingSemaphoresWithFenceHelper(
141       std::vector<ExternalSemaphore> semaphores);
142 
143  protected:
144   void UpdateContent(uint32_t content_flags);
145   bool BeginAccessInternal(bool readonly,
146                            std::vector<ExternalSemaphore>* external_semaphores);
147   void EndAccessInternal(bool readonly, ExternalSemaphore external_semaphore);
148 
149   // SharedImageBacking implementation.
150   std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
151       SharedImageManager* manager,
152       MemoryTypeTracker* tracker,
153       WGPUDevice dawnDevice) override;
154   std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
155       SharedImageManager* manager,
156       MemoryTypeTracker* tracker) override;
157   std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
158   ProduceGLTexturePassthrough(SharedImageManager* manager,
159                               MemoryTypeTracker* tracker) override;
160   std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
161       SharedImageManager* manager,
162       MemoryTypeTracker* tracker,
163       scoped_refptr<SharedContextState> context_state) override;
164   std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
165       SharedImageManager* manager,
166       MemoryTypeTracker* tracker) override;
167 
168  private:
169   // Install a shared memory GMB to the backing.
170   void InstallSharedMemory(SharedMemoryRegionWrapper shared_memory_wrapper);
171   // Returns texture_service_id for ProduceGLTexture and GLTexturePassthrough.
172   GLuint ProduceGLTextureInternal();
173 
174   using FillBufferCallback = base::OnceCallback<void(void* buffer)>;
175   // TODO(penghuang): Remove it when GrContext::updateBackendTexture() supports
176   // compressed texture and callback.
177   bool WritePixelsWithCallback(size_t data_size,
178                                size_t stride,
179                                FillBufferCallback callback);
180   bool WritePixelsWithData(base::span<const uint8_t> pixel_data, size_t stride);
181   bool WritePixels();
182   void CopyPixelsFromGLTextureToVkImage();
183   void CopyPixelsFromShmToGLTexture();
184 
185   scoped_refptr<SharedContextState> context_state_;
186   std::unique_ptr<VulkanImage> image_;
187   GrBackendTexture backend_texture_;
188   VulkanCommandPool* const command_pool_;
189   const bool use_separate_gl_texture_;
190 
191   ExternalSemaphore write_semaphore_;
192   std::vector<ExternalSemaphore> read_semaphores_;
193 
194   bool is_write_in_progress_ = false;
195   uint32_t reads_in_progress_ = 0;
196   uint32_t gl_reads_in_progress_ = 0;
197   gles2::Texture* texture_ = nullptr;
198   scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
199 
200   // GMB related stuff.
201   SharedMemoryRegionWrapper shared_memory_wrapper_;
202 
203   enum LatestContent {
204     kInVkImage = 1 << 0,
205     kInSharedMemory = 1 << 1,
206     kInGLTexture = 1 << 2,
207   };
208   uint32_t latest_content_ = 0;
209 
210   // Semaphores pending for returning to ExternalSemaphorePool.
211   // When the backing is accessed by the vulkan device for GrContext, they can
212   // be returned to ExternalSemaphorePool through VulkanFenceHelper.
213   std::vector<ExternalSemaphore> pending_semaphores_;
214 
215   DISALLOW_COPY_AND_ASSIGN(ExternalVkImageBacking);
216 };
217 
218 }  // namespace gpu
219 
220 #endif  // GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_
221