blob: 7afb0b5147d25632dd995a6f08aacbe807a1f0c8 [file] [log] [blame]
// Copyright 2019 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.
#ifndef GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_
#define GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_
#include <memory>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/util/type_safety/pass_key.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_memory_region_wrapper.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/vulkan/semaphore_handle.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace gpu {
class VulkanCommandPool;
class VulkanImage;
struct VulkanImageUsageCache {
// Maximal usage flags for VK_IMAGE_TILING_OPTIMAL each ResourceFormat.
VkImageUsageFlags optimal_tiling_usage[viz::RESOURCE_FORMAT_MAX + 1];
};
class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking {
public:
static std::unique_ptr<ExternalVkImageBacking> Create(
SharedContextState* context_state,
VulkanCommandPool* command_pool,
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
const VulkanImageUsageCache* image_usage_cache,
base::span<const uint8_t> pixel_data,
bool using_gmb = false);
static std::unique_ptr<ExternalVkImageBacking> CreateFromGMB(
SharedContextState* context_state,
VulkanCommandPool* command_pool,
const Mailbox& mailbox,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat buffer_format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
const VulkanImageUsageCache* image_usage_cache);
ExternalVkImageBacking(util::PassKey<ExternalVkImageBacking>,
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
SharedContextState* context_state,
std::unique_ptr<VulkanImage> image,
VulkanCommandPool* command_pool);
~ExternalVkImageBacking() override;
SharedContextState* context_state() const { return context_state_; }
const GrBackendTexture& backend_texture() const { return backend_texture_; }
VulkanImage* image() const { return image_.get(); }
const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
const {
return texture_passthrough_;
}
VulkanImplementation* vulkan_implementation() const {
return context_state()->vk_context_provider()->GetVulkanImplementation();
}
VulkanFenceHelper* fence_helper() const {
return context_state()
->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper();
}
VkDevice device() const {
return context_state()
->vk_context_provider()
->GetDeviceQueue()
->GetVulkanDevice();
}
bool need_synchronization() const {
if (usage() & SHARED_IMAGE_USAGE_WEBGPU) {
return true;
}
if (usage() & SHARED_IMAGE_USAGE_GLES2) {
return !use_separate_gl_texture() && (texture_ || texture_passthrough_);
}
return false;
}
bool use_separate_gl_texture() const {
return !context_state()->support_vulkan_external_object();
}
uint32_t reads_in_progress() const { return reads_in_progress_; }
uint32_t gl_reads_in_progress() const { return gl_reads_in_progress_; }
// Notifies the backing that an access will start. Return false if there is
// currently any other conflict access in progress. Otherwise, returns true
// and semaphore handles which will be waited on before accessing.
bool BeginAccess(bool readonly,
std::vector<SemaphoreHandle>* semaphore_handles,
bool is_gl);
// Notifies the backing that an access has ended. The representation must
// provide a semaphore handle that has been signaled at the end of the write
// access.
void EndAccess(bool readonly, SemaphoreHandle semaphore_handle, bool is_gl);
// SharedImageBacking implementation.
void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
protected:
static std::unique_ptr<ExternalVkImageBacking> CreateInternal(
SharedContextState* context_state,
VulkanCommandPool* command_pool,
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
const VulkanImageUsageCache* image_usage_cache,
base::span<const uint8_t> pixel_data,
bool using_gmb);
void UpdateContent(uint32_t content_flags);
bool BeginAccessInternal(bool readonly,
std::vector<SemaphoreHandle>* semaphore_handles);
void EndAccessInternal(bool readonly, SemaphoreHandle semaphore_handle);
// SharedImageBacking implementation.
std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
WGPUDevice dawnDevice) override;
std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
ProduceGLTexturePassthrough(SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) override;
private:
#if defined(OS_LINUX) || defined(OS_ANDROID)
// Extract file descriptor from image
int GetMemoryFd(const GrVkImageInfo& image_info);
#endif
// Install a shared memory GMB to the backing.
void InstallSharedMemory(SharedMemoryRegionWrapper shared_memory_wrapper);
// Returns texture_service_id for ProduceGLTexture and GLTexturePassthrough.
GLuint ProduceGLTextureInternal();
using FillBufferCallback = base::OnceCallback<void(void* buffer)>;
// TODO(penghuang): Remove it when GrContext::updateBackendTexture() supports
// compressed texture and callback.
bool WritePixelsWithCallback(size_t data_size,
size_t stride,
FillBufferCallback callback);
bool WritePixelsWithData(base::span<const uint8_t> pixel_data, size_t stride);
bool WritePixels();
void CopyPixelsFromGLTextureToVkImage();
void CopyPixelsFromShmToGLTexture();
SharedContextState* const context_state_;
std::unique_ptr<VulkanImage> image_;
GrBackendTexture backend_texture_;
VulkanCommandPool* const command_pool_;
SemaphoreHandle write_semaphore_handle_;
std::vector<SemaphoreHandle> read_semaphore_handles_;
bool is_write_in_progress_ = false;
uint32_t reads_in_progress_ = 0;
uint32_t gl_reads_in_progress_ = 0;
gles2::Texture* texture_ = nullptr;
scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
// GMB related stuff.
SharedMemoryRegionWrapper shared_memory_wrapper_;
enum LatestContent {
kInVkImage = 1 << 0,
kInSharedMemory = 1 << 1,
kInGLTexture = 1 << 2,
};
uint32_t latest_content_ = 0;
DISALLOW_COPY_AND_ASSIGN(ExternalVkImageBacking);
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_EXTERNAL_VK_IMAGE_BACKING_H_