910e62b5创建于 1月15日历史提交
// 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