blob: d9b239e1378db201bdcf3a8d7ef61ec00338ca08 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/ipc/service/arc_shared_image_interface.h"
#include "base/notimplemented.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/experiences/arc/arc_features.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/ipc/service/gpu_channel_manager.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gl/gl_context.h"
namespace gpu {
namespace {
bool MakeContextCurrentOnGpuThread(SharedContextState* context_state,
bool needs_gl /*=false*/) {
if (!context_state) {
return false;
}
if (context_state->context_lost()) {
return false;
}
// |shared_image_factory_| never writes to the surface, so pass nullptr to
// improve performance. https://crbug.com/457431
auto* context = context_state->real_context();
if (context->IsCurrent(nullptr)) {
return !context_state->CheckResetStatus(needs_gl);
}
return context_state->MakeCurrent(/*surface=*/nullptr, needs_gl);
}
} // namespace
// static
scoped_refptr<ArcSharedImageInterface> ArcSharedImageInterface::Create(
GpuChannelManager* gpu_channel_manager,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner) {
if (!base::FeatureList::IsEnabled(arc::kVideoEncodeUseMappableSI)) {
return nullptr;
}
CHECK(gpu_task_runner->BelongsToCurrentThread());
gpu::ContextResult result;
scoped_refptr<SharedContextState> context_state =
gpu_channel_manager->GetSharedContextState(&result);
// Some of the backings require a current GL context to be created.
if (!::gpu::MakeContextCurrentOnGpuThread(context_state.get(),
/*needs_gl=*/true)) {
return nullptr;
}
return base::MakeRefCounted<ArcSharedImageInterface>(
std::make_unique<gpu::SharedImageFactory>(
gpu_channel_manager->gpu_preferences(),
gpu_channel_manager->gpu_driver_bug_workarounds(),
gpu_channel_manager->gpu_feature_info(), context_state.get(),
gpu_channel_manager->shared_image_manager(),
context_state->memory_tracker(),
/*is_for_display_compositor=*/false),
std::move(gpu_task_runner));
}
ArcSharedImageInterface::ArcSharedImageInterface(
std::unique_ptr<SharedImageFactory> shared_image_factory,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner)
: shared_image_factory_(std::move(shared_image_factory)),
gpu_task_runner_(std::move(gpu_task_runner)) {}
ArcSharedImageInterface::~ArcSharedImageInterface() {
CHECK(gpu_task_runner_->BelongsToCurrentThread());
if (shared_image_factory_->HasImages()) {
// Some of the backings might require a current GL context to be destroyed.
bool have_context = MakeContextCurrentOnGpuThread(/*needs_gl=*/true);
shared_image_factory_->DestroyAllSharedImages(have_context);
}
shared_image_factory_.reset();
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage(
const SharedImageInfo& si_info,
gpu::SurfaceHandle surface_handle,
gfx::BufferUsage buffer_usage,
gfx::GpuMemoryBufferHandle buffer_handle) {
if (encountered_error_.load(std::memory_order_relaxed)) {
return nullptr;
}
auto client_buffer_handle = buffer_handle.Clone();
auto mailbox = Mailbox::Generate();
// Copy which can be modified.
SharedImageInfo si_info_copy = si_info;
// Set CPU read/write usage based on buffer usage.
si_info_copy.meta.usage |= GetCpuSIUsage(buffer_usage);
gpu_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ArcSharedImageInterface::CreateSharedImageOnGpuThread,
base::Unretained(this), mailbox, si_info_copy,
buffer_usage, std::move(buffer_handle)));
return base::MakeRefCounted<ClientSharedImage>(
mailbox, si_info_copy, gpu::SyncToken(),
GpuMemoryBufferHandleInfo(std::move(client_buffer_handle), buffer_usage),
holder_);
}
void ArcSharedImageInterface::CreateSharedImageOnGpuThread(
const Mailbox& mailbox,
const SharedImageInfo& si_info,
gfx::BufferUsage buffer_usage,
gfx::GpuMemoryBufferHandle buffer_handle) {
if (!MakeContextCurrentOnGpuThread()) {
encountered_error_.store(true, std::memory_order_relaxed);
return;
}
if (!shared_image_factory_->CreateSharedImage(
mailbox, si_info.meta.format, si_info.meta.size,
si_info.meta.color_space, si_info.meta.surface_origin,
si_info.meta.alpha_type, si_info.meta.usage,
std::move(si_info.debug_label), std::move(buffer_handle))) {
shared_image_factory_->shared_context_state()->MarkContextLost();
encountered_error_.store(true, std::memory_order_relaxed);
return;
}
}
void ArcSharedImageInterface::DestroySharedImage(
const SyncToken& sync_token,
scoped_refptr<ClientSharedImage> client_shared_image) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage(
const SharedImageInfo& si_info,
gpu::SurfaceHandle surface_handle,
std::optional<SharedImagePoolId> pool_id /*=std::nullopt*/) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage(
const SharedImageInfo& si_info,
base::span<const uint8_t> pixel_data) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage(
const SharedImageInfo& si_info,
SurfaceHandle surface_handle,
gfx::BufferUsage buffer_usage,
std::optional<SharedImagePoolId> pool_id /*=std::nullopt*/) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::CreateSharedImage(
const SharedImageInfo& si_info,
gfx::GpuMemoryBufferHandle buffer_handle) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage>
ArcSharedImageInterface::CreateSharedImageForMLTensor(
std::string debug_label,
viz::SharedImageFormat format,
const gfx::Size& size,
gpu::SharedImageUsageSet usage) {
NOTREACHED();
}
scoped_refptr<ClientSharedImage>
ArcSharedImageInterface::CreateSharedImageForSoftwareCompositor(
const SharedImageInfo& si_info) {
NOTREACHED();
}
void ArcSharedImageInterface::UpdateSharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) {
NOTREACHED();
}
void ArcSharedImageInterface::UpdateSharedImage(
const SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence,
const Mailbox& mailbox) {
NOTREACHED();
}
void ArcSharedImageInterface::DestroySharedImage(const SyncToken& sync_token,
const Mailbox& mailbox) {
gpu_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ArcSharedImageInterface::DestroySharedImageOnGpuThread,
base::Unretained(this), mailbox));
}
void ArcSharedImageInterface::DestroySharedImageOnGpuThread(
const Mailbox& mailbox) {
if (!MakeContextCurrentOnGpuThread()) {
return;
}
if (!shared_image_factory_->DestroySharedImage(mailbox)) {
shared_image_factory_->shared_context_state()->MarkContextLost();
}
}
scoped_refptr<ClientSharedImage> ArcSharedImageInterface::ImportSharedImage(
ExportedSharedImage exported_shared_image) {
NOTREACHED();
}
SyncToken ArcSharedImageInterface::GenUnverifiedSyncToken() {
NOTREACHED();
}
SyncToken ArcSharedImageInterface::GenVerifiedSyncToken() {
NOTREACHED();
}
void ArcSharedImageInterface::VerifySyncToken(SyncToken& sync_token) {
NOTREACHED();
}
void ArcSharedImageInterface::WaitSyncToken(const SyncToken& sync_token) {
NOTREACHED();
}
bool ArcSharedImageInterface::CanVerifySyncToken(const SyncToken& sync_token) {
NOTREACHED();
}
void ArcSharedImageInterface::VerifyFlush() {
NOTREACHED();
}
const SharedImageCapabilities& ArcSharedImageInterface::GetCapabilities() {
NOTREACHED();
}
bool ArcSharedImageInterface::MakeContextCurrentOnGpuThread(
bool needs_gl /*=false*/) {
return ::gpu::MakeContextCurrentOnGpuThread(
shared_image_factory_->shared_context_state(), needs_gl);
}
} // namespace gpu