blob: b195fce05a64d0245f068aa821a87d745453e14c [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.
#include "gpu/command_buffer/service/shared_image_backing_ozone.h"
#include <dawn/webgpu.h>
#include <vulkan/vulkan.h>
#include <memory>
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/command_buffer/service/shared_image_representation_gl_ozone.h"
#include "gpu/command_buffer/service/shared_image_representation_skia_gl.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/buildflags.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#if BUILDFLAG(USE_DAWN)
#include "gpu/command_buffer/service/shared_image_representation_dawn_ozone.h"
#endif // BUILDFLAG(USE_DAWN)
namespace gpu {
namespace {
size_t GetPixmapSizeInBytes(const gfx::NativePixmap& pixmap) {
return gfx::BufferSizeForBufferFormat(pixmap.GetBufferSize(),
pixmap.GetBufferFormat());
}
gfx::BufferUsage GetBufferUsage(uint32_t usage) {
if (usage & SHARED_IMAGE_USAGE_WEBGPU) {
// Just use SCANOUT for WebGPU since the memory doesn't need to be linear.
return gfx::BufferUsage::SCANOUT;
} else if (usage & SHARED_IMAGE_USAGE_SCANOUT) {
return gfx::BufferUsage::SCANOUT;
} else {
NOTREACHED() << "Unsupported usage flags.";
return gfx::BufferUsage::SCANOUT;
}
}
} // namespace
class SharedImageBackingOzone::SharedImageRepresentationVaapiOzone
: public SharedImageRepresentationVaapi {
public:
SharedImageRepresentationVaapiOzone(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
VaapiDependencies* vaapi_dependency)
: SharedImageRepresentationVaapi(manager,
backing,
tracker,
vaapi_dependency) {}
private:
SharedImageBackingOzone* ozone_backing() {
return static_cast<SharedImageBackingOzone*>(backing());
}
void EndAccess() override { ozone_backing()->has_pending_va_writes_ = true; }
void BeginAccess() override {
// TODO(andrescj): DCHECK that there are no fences to wait on (because the
// compositor should be completely done with a VideoFrame before returning
// it).
}
};
std::unique_ptr<SharedImageBackingOzone> SharedImageBackingOzone::Create(
scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs,
SharedContextState* context_state,
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
SurfaceHandle surface_handle) {
gfx::BufferFormat buffer_format = viz::BufferFormat(format);
gfx::BufferUsage buffer_usage = GetBufferUsage(usage);
VkDevice vk_device = VK_NULL_HANDLE;
DCHECK(context_state);
if (context_state->vk_context_provider()) {
vk_device = context_state->vk_context_provider()
->GetDeviceQueue()
->GetVulkanDevice();
}
ui::SurfaceFactoryOzone* surface_factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
scoped_refptr<gfx::NativePixmap> pixmap = surface_factory->CreateNativePixmap(
surface_handle, vk_device, size, buffer_format, buffer_usage);
if (!pixmap) {
return nullptr;
}
return base::WrapUnique(new SharedImageBackingOzone(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
context_state, std::move(pixmap), std::move(dawn_procs)));
}
SharedImageBackingOzone::~SharedImageBackingOzone() = default;
void SharedImageBackingOzone::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
NOTIMPLEMENTED_LOG_ONCE();
return;
}
bool SharedImageBackingOzone::ProduceLegacyMailbox(
MailboxManager* mailbox_manager) {
NOTREACHED();
return false;
}
std::unique_ptr<SharedImageRepresentationDawn>
SharedImageBackingOzone::ProduceDawn(SharedImageManager* manager,
MemoryTypeTracker* tracker,
WGPUDevice device) {
#if BUILDFLAG(USE_DAWN)
DCHECK(dawn_procs_);
WGPUTextureFormat webgpu_format = viz::ToWGPUFormat(format());
if (webgpu_format == WGPUTextureFormat_Undefined) {
return nullptr;
}
return std::make_unique<SharedImageRepresentationDawnOzone>(
manager, this, tracker, device, webgpu_format, pixmap_, dawn_procs_);
#else // !BUILDFLAG(USE_DAWN)
return nullptr;
#endif
}
std::unique_ptr<SharedImageRepresentationGLTexture>
SharedImageBackingOzone::ProduceGLTexture(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
return SharedImageRepresentationGLOzone::Create(manager, this, tracker,
pixmap_, format());
}
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
SharedImageBackingOzone::ProduceGLTexturePassthrough(
SharedImageManager* manager,
MemoryTypeTracker* tracker) {
NOTIMPLEMENTED_LOG_ONCE();
return nullptr;
}
std::unique_ptr<SharedImageRepresentationSkia>
SharedImageBackingOzone::ProduceSkia(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) {
if (context_state->GrContextIsGL()) {
auto gl_representation = ProduceGLTexture(manager, tracker);
if (!gl_representation) {
LOG(ERROR) << "SharedImageBackingOzone::ProduceSkia failed to create GL "
"representation";
return nullptr;
}
auto skia_representation = SharedImageRepresentationSkiaGL::Create(
std::move(gl_representation), std::move(context_state), manager, this,
tracker);
if (!skia_representation) {
LOG(ERROR) << "SharedImageBackingOzone::ProduceSkia failed to create "
"Skia representation";
return nullptr;
}
return skia_representation;
}
NOTIMPLEMENTED_LOG_ONCE();
return nullptr;
}
std::unique_ptr<SharedImageRepresentationOverlay>
SharedImageBackingOzone::ProduceOverlay(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
NOTIMPLEMENTED_LOG_ONCE();
return nullptr;
}
SharedImageBackingOzone::SharedImageBackingOzone(
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
SharedContextState* context_state,
scoped_refptr<gfx::NativePixmap> pixmap,
scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs)
: ClearTrackingSharedImageBacking(mailbox,
format,
size,
color_space,
surface_origin,
alpha_type,
usage,
GetPixmapSizeInBytes(*pixmap),
false),
pixmap_(std::move(pixmap)),
dawn_procs_(std::move(dawn_procs)) {}
std::unique_ptr<SharedImageRepresentationVaapi>
SharedImageBackingOzone::ProduceVASurface(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
VaapiDependenciesFactory* dep_factory) {
DCHECK(pixmap_);
if (!vaapi_deps_)
vaapi_deps_ = dep_factory->CreateVaapiDependencies(pixmap_);
if (!vaapi_deps_) {
LOG(ERROR) << "SharedImageBackingOzone::ProduceVASurface failed to create "
"VaapiDependencies";
return nullptr;
}
return std::make_unique<
SharedImageBackingOzone::SharedImageRepresentationVaapiOzone>(
manager, this, tracker, vaapi_deps_.get());
}
bool SharedImageBackingOzone::VaSync() {
if (has_pending_va_writes_)
has_pending_va_writes_ = !vaapi_deps_->SyncSurface();
return !has_pending_va_writes_;
}
} // namespace gpu