// Copyright 2020 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/client/client_shared_image_interface.h"

#include "build/build_config.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/common/shared_image_capabilities.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/client/shared_image_interface_proxy.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"

#if BUILDFLAG(IS_WIN)
#include "ui/gfx/win/d3d_shared_fence.h"
#endif

namespace gpu {

ClientSharedImageInterface::ClientSharedImageInterface(
    SharedImageInterfaceProxy* proxy,
    scoped_refptr<gpu::GpuChannelHost> channel)
    : gpu_channel_(std::move(channel)),
      proxy_(proxy),
      shared_memory_pool_(
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
          base::MakeRefCounted<base::UnsafeSharedMemoryPool>()
#else
          nullptr
#endif
      ) {
}

ClientSharedImageInterface::~ClientSharedImageInterface() {
  for (const auto& [mailbox, ref_count] : mailboxes_) {
    CHECK_GT(ref_count, 0);
    for (int i = 0; i < ref_count; i++) {
      proxy_->DestroySharedImage(std::vector<SyncToken>{}, mailbox);
    }
  }
}

void ClientSharedImageInterface::UpdateSharedImage(const SyncToken& sync_token,
                                                   const Mailbox& mailbox) {
  proxy_->UpdateSharedImage(sync_token, mailbox);
}

void ClientSharedImageInterface::UpdateSharedImage(
    const SyncToken& sync_token,
    std::unique_ptr<gfx::GpuFence> acquire_fence,
    const Mailbox& mailbox) {
  proxy_->UpdateSharedImage(sync_token, std::move(acquire_fence), mailbox);
}

#if BUILDFLAG(IS_FUCHSIA)
void ClientSharedImageInterface::RegisterSysmemBufferCollection(
    zx::eventpair service_handle,
    zx::channel sysmem_token,
    const viz::SharedImageFormat& format,
    gfx::BufferUsage usage,
    bool register_with_image_pipe) {
  proxy_->RegisterSysmemBufferCollection(std::move(service_handle),
                                         std::move(sysmem_token), format, usage,
                                         register_with_image_pipe);
}
#endif  // BUILDFLAG(IS_FUCHSIA)

SyncToken ClientSharedImageInterface::GenUnverifiedSyncToken() {
  return proxy_->GenUnverifiedSyncToken();
}

SyncToken ClientSharedImageInterface::GenVerifiedSyncToken() {
  return proxy_->GenVerifiedSyncToken();
}

void ClientSharedImageInterface::VerifySyncToken(gpu::SyncToken& sync_token) {
  proxy_->VerifySyncToken(sync_token);
}

bool ClientSharedImageInterface::CanVerifySyncToken(
    const gpu::SyncToken& sync_token) {
  return proxy_->CanVerifySyncToken(sync_token);
}

void ClientSharedImageInterface::VerifyFlush() {
  return proxy_->VerifyFlush();
}

void ClientSharedImageInterface::WaitSyncToken(
    const gpu::SyncToken& sync_token) {
  proxy_->WaitSyncToken(sync_token);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
    const SharedImageInfo& si_info,
    gpu::SurfaceHandle surface_handle,
    std::optional<SharedImagePoolId> pool_id) {
  DCHECK_EQ(surface_handle, kNullSurfaceHandle);
  DCHECK(gpu::IsValidClientUsage(si_info.usage))
      << static_cast<uint32_t>(si_info.usage);
  auto mailbox = proxy_->CreateSharedImage(si_info, std::move(pool_id));
  return base::MakeRefCounted<ClientSharedImage>(AddMailbox(mailbox), si_info,
                                                 GenUnverifiedSyncToken(),
                                                 holder_, gfx::EMPTY_BUFFER);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
    const SharedImageInfo& si_info,
    base::span<const uint8_t> pixel_data) {
  // Pixel upload path only supports single-planar formats.
  DCHECK(si_info.format.is_single_plane()) << si_info.format.ToString();
  DCHECK(gpu::IsValidClientUsage(si_info.usage))
      << static_cast<uint32_t>(si_info.usage);

  // EstimatedSizeInBytes() returns the minimum size in bytes needed to store
  // `format` at `size` so if span is smaller there is a problem.
  CHECK_GE(pixel_data.size(),
           si_info.format.EstimatedSizeInBytes(si_info.size));

  auto mailbox = proxy_->CreateSharedImage(si_info, pixel_data);
  if (mailbox.IsZero()) {
    return nullptr;
  }

  return base::MakeRefCounted<ClientSharedImage>(AddMailbox(mailbox), si_info,
                                                 GenUnverifiedSyncToken(),
                                                 holder_, gfx::EMPTY_BUFFER);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
    const SharedImageInfo& si_info,
    gpu::SurfaceHandle surface_handle,
    gfx::BufferUsage buffer_usage,
    std::optional<SharedImagePoolId> pool_id) {
  DCHECK_EQ(surface_handle, kNullSurfaceHandle);
  DCHECK(gpu::IsValidClientUsage(si_info.usage))
      << static_cast<uint32_t>(si_info.usage);
  gfx::GpuMemoryBufferHandle buffer_handle;

  // Copy which can be modified.
  SharedImageInfo si_info_copy = si_info;
  // Set CPU read/write usage based on buffer usage.
  si_info_copy.usage |= GetCpuSIUsage(buffer_usage);
  auto mailbox = proxy_->CreateSharedImage(si_info_copy, buffer_usage,
                                           std::move(pool_id), &buffer_handle);
  if (mailbox.IsZero()) {
    return nullptr;
  }

  CHECK(!buffer_handle.is_null());
  return base::MakeRefCounted<ClientSharedImage>(
      AddMailbox(mailbox), si_info_copy, GenUnverifiedSyncToken(),
      GpuMemoryBufferHandleInfo(std::move(buffer_handle), buffer_usage),
      holder_, shared_memory_pool_);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
    const SharedImageInfo& si_info,
    gpu::SurfaceHandle surface_handle,
    gfx::BufferUsage buffer_usage,
    gfx::GpuMemoryBufferHandle buffer_handle) {
  DCHECK(gpu::IsValidClientUsage(si_info.usage))
      << static_cast<uint32_t>(si_info.usage);
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
  CHECK(!si_info.format.PrefersExternalSampler()) << si_info.format.ToString();
#endif
  // Copy which can be modified.
  SharedImageInfo si_info_copy = si_info;
  // Set CPU read/write usage based on buffer usage.
  si_info_copy.usage |= GetCpuSIUsage(buffer_usage);
  auto client_buffer_handle = buffer_handle.Clone();
  auto mailbox =
      proxy_->CreateSharedImage(si_info_copy, std::move(buffer_handle));
  return base::MakeRefCounted<ClientSharedImage>(
      AddMailbox(mailbox), si_info_copy, GenUnverifiedSyncToken(),
      GpuMemoryBufferHandleInfo(std::move(client_buffer_handle), buffer_usage),
      holder_, shared_memory_pool_);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
    const SharedImageInfo& si_info,
    gfx::GpuMemoryBufferHandle buffer_handle) {
  DCHECK(gpu::IsValidClientUsage(si_info.usage))
      << static_cast<uint32_t>(si_info.usage);
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
  CHECK(!si_info.format.PrefersExternalSampler()) << si_info.format.ToString();
#endif
  auto buffer_handle_type = buffer_handle.type;
  auto mailbox = proxy_->CreateSharedImage(si_info, std::move(buffer_handle));
  return base::MakeRefCounted<ClientSharedImage>(AddMailbox(mailbox), si_info,
                                                 GenUnverifiedSyncToken(),
                                                 holder_, buffer_handle_type);
}

scoped_refptr<ClientSharedImage>
ClientSharedImageInterface::CreateSharedImageForMLTensor(
    std::string debug_label,
    viz::SharedImageFormat format,
    const gfx::Size& size,
    gpu::SharedImageUsageSet usage) {
  CHECK(gpu::IsValidClientUsage(usage)) << static_cast<uint32_t>(usage);
  CHECK(usage.Has(SHARED_IMAGE_USAGE_WEBNN_SHARED_TENSOR));

  const SharedImageInfo si_info = {format, std::move(size), gfx::ColorSpace(),
                                   usage, std::move(debug_label)};

  auto mailbox = proxy_->CreateSharedImage(si_info, std::nullopt);
  if (mailbox.IsZero()) {
    return nullptr;
  }

  return base::WrapRefCounted<ClientSharedImage>(new ClientSharedImage(
      AddMailbox(mailbox), si_info, GenUnverifiedSyncToken(), holder_,
      gfx::EMPTY_BUFFER));
}

scoped_refptr<ClientSharedImage>
ClientSharedImageInterface::CreateSharedImageForSoftwareCompositor(
    const SharedImageInfo& si_info) {
  base::WritableSharedMemoryMapping mapping;
  gfx::GpuMemoryBufferHandle handle;
  CreateSharedMemoryRegionFromSIInfo(si_info, mapping, handle);

  auto mailbox = proxy_->CreateSharedImage(si_info, std::move(handle));

  return base::MakeRefCounted<ClientSharedImage>(AddMailbox(mailbox), si_info,
                                                 GenUnverifiedSyncToken(),
                                                 holder_, std::move(mapping));
}

void ClientSharedImageInterface::CopyToGpuMemoryBuffer(
    const SyncToken& sync_token,
    const Mailbox& mailbox) {
  proxy_->CopyToGpuMemoryBuffer(sync_token, mailbox);
}

#if BUILDFLAG(IS_WIN)
void ClientSharedImageInterface::CopyToGpuMemoryBufferAsync(
    const SyncToken& sync_token,
    const Mailbox& mailbox,
    base::OnceCallback<void(bool)> callback) {
  proxy_->CopyToGpuMemoryBufferAsync(sync_token, mailbox, std::move(callback));
}

void ClientSharedImageInterface::UpdateSharedImage(
    const SyncToken& sync_token,
    scoped_refptr<gfx::D3DSharedFence> d3d_shared_fence,
    const Mailbox& mailbox) {
  proxy_->UpdateSharedImage(sync_token, std::move(d3d_shared_fence), mailbox);
}
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
void ClientSharedImageInterface::CopyNativeGmbToSharedMemoryAsync(
    gfx::GpuMemoryBufferHandle buffer_handle,
    base::UnsafeSharedMemoryRegion memory_region,
    base::OnceCallback<void(bool)> callback) {
#if BUILDFLAG(IS_WIN)
  CHECK_EQ(buffer_handle.type, gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE);
#elif BUILDFLAG(IS_ANDROID)
  CHECK_EQ(buffer_handle.type,
           gfx::GpuMemoryBufferType::ANDROID_HARDWARE_BUFFER);
#endif
  CHECK(memory_region.IsValid());
  proxy_->CopyNativeGmbToSharedMemoryAsync(
      std::move(buffer_handle), std::move(memory_region), std::move(callback));
}
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)

void ClientSharedImageInterface::DestroySharedImage(
    std::vector<SyncToken> sync_tokens,
    const Mailbox& mailbox) {
  DCHECK(!mailbox.IsZero());

  {
    base::AutoLock lock(lock_);
    auto it = mailboxes_.find(mailbox);
    CHECK(it != mailboxes_.end());
    int& ref_count = it->second;
    CHECK_GT(ref_count, 0);
    if (--ref_count == 0) {
      mailboxes_.erase(it);
    }
  }
  proxy_->DestroySharedImage(std::move(sync_tokens), mailbox);
}

void ClientSharedImageInterface::DestroySharedImage(
    const SyncToken& sync_token,
    scoped_refptr<ClientSharedImage> client_shared_image) {
  CHECK(client_shared_image->HasOneRef());
  CHECK(client_shared_image->HasHolder());
  client_shared_image->UpdateDestructionSyncToken(sync_token);
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::ImportSharedImage(
    ExportedSharedImage exported_shared_image) {
  const auto& mailbox = exported_shared_image.mailbox_;
  const auto& sync_token = exported_shared_image.creation_sync_token_;

  DCHECK(!mailbox.IsZero());
  AddMailbox(mailbox);
  proxy_->AddReferenceToSharedImage(sync_token, mailbox);

  return base::WrapRefCounted<ClientSharedImage>(
      new ClientSharedImage(std::move(exported_shared_image), holder_));
}

scoped_refptr<ClientSharedImage> ClientSharedImageInterface::NotifyMailboxAdded(
    const Mailbox& mailbox,
    viz::SharedImageFormat format,
    const gfx::Size& size,
    const gfx::ColorSpace& color_space,
    GrSurfaceOrigin surface_origin,
    SkAlphaType alpha_type,
    gpu::SharedImageUsageSet usage,
    uint32_t texture_target,
    std::string_view debug_label) {
  AddMailbox(mailbox);
  proxy_->NotifyMailboxAdded(mailbox, usage);

  SharedImageMetadata metadata(format, size, color_space, surface_origin,
                               alpha_type, usage);
  SharedImageInfo info(metadata, debug_label);
  return base::WrapRefCounted<ClientSharedImage>(new ClientSharedImage(
      mailbox, info, GenUnverifiedSyncToken(), holder_, texture_target));
}

Mailbox ClientSharedImageInterface::AddMailbox(const gpu::Mailbox& mailbox) {
  if (mailbox.IsZero())
    return mailbox;

  base::AutoLock lock(lock_);
  CHECK_GE(mailboxes_[mailbox], 0);
  mailboxes_[mailbox]++;
  return mailbox;
}

bool ClientSharedImageInterface::IsLost() const {
  return gpu_channel_->IsLost();
}

bool ClientSharedImageInterface::AddGpuChannelLostObserver(
    GpuChannelLostObserver* observer) {
  return gpu_channel_->AddObserverIfNotAlreadyLost(observer);
}

void ClientSharedImageInterface::RemoveGpuChannelLostObserver(
    GpuChannelLostObserver* observer) {
  gpu_channel_->RemoveObserver(observer);
}

const SharedImageCapabilities& ClientSharedImageInterface::GetCapabilities() {
  return proxy_->GetCapabilities();
}

void ClientSharedImageInterface::CreateSharedImagePool(
    const SharedImagePoolId& pool_id,
    mojo::PendingRemote<mojom::SharedImagePoolClientInterface> client_remote) {
  proxy_->CreateSharedImagePool(pool_id, std::move(client_remote));
}

void ClientSharedImageInterface::DestroySharedImagePool(
    const SharedImagePoolId& pool_id) {
  proxy_->DestroySharedImagePool(pool_id);
}

void ClientSharedImageInterface::SignalSyncToken(
    std::vector<SyncToken> sync_tokens,
    base::OnceClosure callback) {
  proxy_->SignalSyncToken(std::move(sync_tokens), std::move(callback));
}

}  // namespace gpu
