// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "gpu/command_buffer/client/client_shared_image.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2extchromium.h>

#include <optional>

#include "base/check_is_test.h"
#include "base/containers/contains.h"
#include "base/debug/crash_logging.h"
#include "base/notreached.h"
#include "base/task/bind_post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/process_memory_dump.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_capabilities.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "third_party/dawn/include/dawn/wire/client/webgpu_cpp.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/buffer_usage_util.h"

#if BUILDFLAG(IS_APPLE)
#include "gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h"
#endif

#if BUILDFLAG(IS_OZONE)
#include "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h"
#include "ui/ozone/public/client_native_pixmap_factory_ozone.h"
#include "ui/ozone/public/ozone_platform.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h"
#endif

namespace gpu {

namespace {

class ScopedMappingForTests : public ClientSharedImage::ScopedMapping {
 public:
  ScopedMappingForTests(const gfx::Size& size, gfx::BufferFormat format)
      : size_(size), format_(format) {
    int num_planes = gfx::NumberOfPlanesForLinearBufferFormat(format_);
    size_t allocation_size = 0;
    for (int plane_index = 0; plane_index < num_planes; plane_index++) {
      size_t height_in_pixels;
      CHECK(gfx::PlaneHeightForBufferFormatChecked(
          Size().height(), format_, plane_index, &height_in_pixels));
      allocation_size += Stride(plane_index) * height_in_pixels;
    }

    data_ = std::vector<uint8_t>(allocation_size);
  }

  ~ScopedMappingForTests() override = default;

  // ClientSharedImage::ScopedMapping:
  base::span<uint8_t> GetMemoryForPlane(const uint32_t plane_index) override {
    size_t height_in_pixels;
    size_t row_size_in_bytes;

    CHECK(gfx::PlaneHeightForBufferFormatChecked(
        Size().height(), format_, plane_index, &height_in_pixels));
    CHECK(gfx::RowSizeForBufferFormatChecked(Size().width(), format_,
                                             plane_index, &row_size_in_bytes));
    size_t span_length =
        Stride(plane_index) * (height_in_pixels - 1) + row_size_in_bytes;

    DCHECK_LT(plane_index, gfx::NumberOfPlanesForLinearBufferFormat(format_));
    auto* data_ptr = data_.data();
    data_ptr += gfx::BufferOffsetForBufferFormat(Size(), format_, plane_index);

    // SAFETY: `data_` has been allocated to have the necessary size.
    return UNSAFE_BUFFERS(
        base::span<uint8_t>(reinterpret_cast<uint8_t*>(data_ptr), span_length));
  }
  size_t Stride(const uint32_t plane_index) override {
    DCHECK_LT(plane_index, gfx::NumberOfPlanesForLinearBufferFormat(format_));
    return gfx::RowSizeForBufferFormat(Size().width(), format_, plane_index);
  }
  gfx::Size Size() override { return size_; }
  bool IsSharedMemory() override { return true; }

 private:
  gfx::Size size_;
  gfx::BufferFormat format_;
  std::vector<uint8_t> data_;
};

class ScopedMappingSharedMemoryMapping
    : public ClientSharedImage::ScopedMapping {
 public:
  ScopedMappingSharedMemoryMapping(SharedImageMetadata metadata,
                                   base::WritableSharedMemoryMapping* mapping)
      : metadata_(metadata), mapping_(mapping) {}
  ~ScopedMappingSharedMemoryMapping() override = default;

  // ClientSharedImage::ScopedMapping:
  base::span<uint8_t> GetMemoryForPlane(const uint32_t plane_index) override {
    CHECK(mapping_->IsValid());
    CHECK_LT(plane_index,
             gfx::NumberOfPlanesForLinearBufferFormat(BufferFormat()));

    size_t height_in_pixels;
    CHECK(gfx::PlaneHeightForBufferFormatChecked(
        Size().height(), BufferFormat(), plane_index, &height_in_pixels));
    size_t span_length = Stride(plane_index) * height_in_pixels;

    // SAFETY: The validity of the mapping combined with the construction of
    // that mapping guarantee that it contains at least `span_length` bytes
    // beyond the start of the plane.
    return UNSAFE_BUFFERS(
        base::span<uint8_t>(static_cast<uint8_t*>(mapping_->memory()) +
                                gfx::BufferOffsetForBufferFormat(
                                    Size(), BufferFormat(), plane_index),
                            span_length));
  }
  size_t Stride(const uint32_t plane_index) override {
    CHECK_LT(plane_index,
             gfx::NumberOfPlanesForLinearBufferFormat(BufferFormat()));
    return gfx::RowSizeForBufferFormat(Size().width(), BufferFormat(),
                                       plane_index);
  }
  gfx::Size Size() override { return metadata_.size; }
  bool IsSharedMemory() override { return true; }

 private:
  gfx::BufferFormat BufferFormat() {
    return viz::SinglePlaneSharedImageFormatToBufferFormat(metadata_.format);
  }

  SharedImageMetadata metadata_;
  raw_ptr<base::WritableSharedMemoryMapping> mapping_;
};

class ScopedMappingGpuMemoryBuffer : public ClientSharedImage::ScopedMapping {
 public:
  ScopedMappingGpuMemoryBuffer(const gfx::Size& size, gfx::BufferFormat format)
      : size_(size), format_(format) {}
  ~ScopedMappingGpuMemoryBuffer() override {
    if (buffer_) {
      buffer_->Unmap();
    }
  }

  // ClientSharedImage::ScopedMapping:
  base::span<uint8_t> GetMemoryForPlane(const uint32_t plane_index) override {
    CHECK(buffer_);

    size_t height_in_pixels;
    size_t row_size_in_bytes;

    CHECK(gfx::PlaneHeightForBufferFormatChecked(
        Size().height(), format_, plane_index, &height_in_pixels));
    CHECK(gfx::RowSizeForBufferFormatChecked(Size().width(), format_,
                                             plane_index, &row_size_in_bytes));

    // Note that the stride might be larger than the row size due to padding.
    // For all rows other than the last, this is legal data for the client to
    // access as it's part of the buffer.  However, the final row is not
    // guaranteed to have padding (it's a system-dependent internal detail).
    // Thus, the data that is legal for the client to access should *not*
    // include any bytes beyond the actual end of the final row.
    size_t span_length =
        Stride(plane_index) * (height_in_pixels - 1) + row_size_in_bytes;

    // SAFETY: The underlying platform-specific buffer generation mechanisms
    // guarantee that the buffer contains at least `span_length` bytes following
    // the start of the plane, as that region is by definition the memory
    // storing the data of the plane.
    return UNSAFE_BUFFERS(base::span<uint8_t>(
        reinterpret_cast<uint8_t*>(buffer_->memory(plane_index)), span_length));
  }
  size_t Stride(const uint32_t plane_index) override {
    CHECK(buffer_);
    return buffer_->stride(plane_index);
  }
  gfx::Size Size() override { return size_; }
  bool IsSharedMemory() override {
    CHECK(buffer_);
    return buffer_->GetType() == gfx::GpuMemoryBufferType::SHARED_MEMORY_BUFFER;
  }
  bool Init(GpuMemoryBufferImpl* gpu_memory_buffer, bool is_already_mapped) {
    if (!gpu_memory_buffer) {
      LOG(ERROR) << "No GpuMemoryBuffer.";
      return false;
    }

    if (!is_already_mapped && !gpu_memory_buffer->Map()) {
      LOG(ERROR) << "Failed to map the buffer.";
      return false;
    }
    buffer_ = gpu_memory_buffer;
    return true;
  }

 private:
  // ScopedMappingGpuMemoryBuffer is essentially a wrapper around
  // GpuMemoryBuffer for now for simplicity and will be removed later.
  // TODO(crbug.com/40279377): Refactor/Rename GpuMemoryBuffer and its
  // implementations  as the end goal after all clients using GMB are
  // converted to use the ScopedMapping and notion of GpuMemoryBuffer is being
  // removed.
  // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
  RAW_PTR_EXCLUSION GpuMemoryBufferImpl* buffer_ = nullptr;
  gfx::Size size_;
  gfx::BufferFormat format_;
};

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_OZONE)
bool GMBIsNative(gfx::GpuMemoryBufferType gmb_type) {
  return gmb_type != gfx::EMPTY_BUFFER && gmb_type != gfx::SHARED_MEMORY_BUFFER;
}
#endif

// Computes the texture target to use for a SharedImage that was created with
// `metadata` and the given type of GpuMemoryBuffer(Handle) supplied by the
// client (which will be gfx::EmptyBuffer if the client did not supply a
// GMB/GMBHandle). Conceptually:
// * On Mac the native buffer target is required if either (1) the client
//   gave a native buffer or (2) the usages require a native buffer. And this
//   matters only when running on ANGLE OpenGL/CGL - in all other cases we use
//   GL_TEXTURE_2D including with Graphite and on iOS (EAGL instead of CGL).
// * On Ozone the native buffer target is required iff external sampling is
//   being used, which is dictated by the format of the SharedImage. Note
//   * Fuchsia does not support import of external images to GL for usage with
//     external sampling.  The ClientSharedImage's texture target must be 0 in
//     the case where external sampling would be used to signal this lack of
//     support to the //media code, which detects the lack of support *based on*
//     on the texture target being 0.
// * On all other platforms GL_TEXTURE_2D is always used (external sampling is
//   supported in Chromium only on Ozone).
uint32_t ComputeTextureTargetForSharedImage(
    SharedImageMetadata metadata,
    gfx::GpuMemoryBufferType client_gmb_type,
    scoped_refptr<SharedImageInterface> sii) {
  CHECK(sii);
#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_OZONE)
  return GL_TEXTURE_2D;
#elif BUILDFLAG(IS_MAC)
  // Check for IOSurfaces being used. We infer IOSurface based on scanout or
  // WebGPU usage, but that's not strictly correct e.g. with Graphite, WebGL
  // canvas back buffers will also use IOSurfaces always regardless of scanout.
  // However, in those cases we would be using GL_TEXTURE_2D anyway due to ANGLE
  // Metal (or Swiftshader for tests) being used.
  // Note that iOS uses GL_TEXTURE_2D even though it uses IOSurfaces -
  // GL_TEXTURE_RECTANGLE_ARB is in CGL which is Mac only.
  constexpr gpu::SharedImageUsageSet kUsagesRequiringNativeBuffer =
      SHARED_IMAGE_USAGE_SCANOUT | SHARED_IMAGE_USAGE_WEBGPU_READ |
      SHARED_IMAGE_USAGE_WEBGPU_WRITE;
  const bool uses_native_buffer =
      GMBIsNative(client_gmb_type) ||
      metadata.usage.HasAny(kUsagesRequiringNativeBuffer);
  return uses_native_buffer
             ? sii->GetCapabilities().texture_target_for_io_surfaces
             : GL_TEXTURE_2D;
#else  // Ozone
  // Check for external sampling being used.
  if (!metadata.format.PrefersExternalSampler()) {
    return GL_TEXTURE_2D;
  }
  // The client should configure an SI to use external sampling only if they
  // have provided a native buffer to back that SI.
  CHECK(GMBIsNative(client_gmb_type));
  // See the note at the top of this function wrt Fuchsia.
#if BUILDFLAG(IS_FUCHSIA)
  return 0;
#else
  return GL_TEXTURE_EXTERNAL_OES;
#endif  // BUILDFLAG(IS_FUCHSIA)
#endif  // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_OZONE)
}

}  // namespace

// static
std::unique_ptr<GpuMemoryBufferImpl>
ClientSharedImage::CreateGpuMemoryBufferImplFromHandle(
    gfx::GpuMemoryBufferHandle handle,
    const gfx::Size& size,
    gfx::BufferFormat format,
    gfx::BufferUsage usage,
    gpu::SharedImageUsageSet si_usage,
    GpuMemoryBufferImpl::CopyNativeBufferToShMemCallback
        copy_native_buffer_to_shmem_callback,
    scoped_refptr<base::UnsafeSharedMemoryPool> pool) {
  switch (handle.type) {
    case gfx::SHARED_MEMORY_BUFFER:
      return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
          std::move(handle), size, format, usage);
#if BUILDFLAG(IS_APPLE)
    case gfx::IO_SURFACE_BUFFER: {
      bool is_read_only_cpu_usage =
          si_usage.Has(SHARED_IMAGE_USAGE_CPU_READ) &&
          !si_usage.Has(SHARED_IMAGE_USAGE_CPU_WRITE_ONLY);
      return GpuMemoryBufferImplIOSurface::CreateFromHandle(
          std::move(handle), size, format, is_read_only_cpu_usage);
    }
#endif
#if BUILDFLAG(IS_OZONE)
    case gfx::NATIVE_PIXMAP: {
      // NOTE: This is not used beyond the lifetime of CreateFromHandle().
      auto client_native_pixmap_factory =
          ui::CreateClientNativePixmapFactoryOzone();
      return GpuMemoryBufferImplNativePixmap::CreateFromHandle(
          client_native_pixmap_factory.get(), std::move(handle), size, format,
          usage);
    }
#endif
#if BUILDFLAG(IS_WIN)
    case gfx::DXGI_SHARED_HANDLE:
      return GpuMemoryBufferImplDXGI::CreateFromHandle(
          std::move(handle), size, format,
          std::move(copy_native_buffer_to_shmem_callback), std::move(pool));
#endif
#if BUILDFLAG(IS_ANDROID)
    case gfx::ANDROID_HARDWARE_BUFFER:
      return nullptr;
#endif
    default:
      // TODO(dcheng): Remove default case (https://crbug.com/676224).
      NOTREACHED() << gfx::BufferFormatToString(format) << ", "
                   << gfx::BufferUsageToString(usage);
  }
}

// static
std::unique_ptr<ClientSharedImage::ScopedMapping>
ClientSharedImage::ScopedMapping::Create(
    SharedImageMetadata metadata,
    base::WritableSharedMemoryMapping* mapping) {
  return std::make_unique<ScopedMappingSharedMemoryMapping>(metadata, mapping);
}

// static
std::unique_ptr<ClientSharedImage::ScopedMapping>
ClientSharedImage::ScopedMapping::Create(SharedImageMetadata metadata,
                                         GpuMemoryBufferImpl* gpu_memory_buffer,
                                         bool is_already_mapped) {
  auto scoped_mapping = base::WrapUnique(new ScopedMappingGpuMemoryBuffer(
      metadata.size,
      viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
          metadata.format)));
  if (!scoped_mapping->Init(gpu_memory_buffer, is_already_mapped)) {
    LOG(ERROR) << "ScopedMapping init failed.";
    return nullptr;
  }
  return scoped_mapping;
}

// static
void ClientSharedImage::ScopedMapping::StartCreateAsync(
    SharedImageMetadata metadata,
    GpuMemoryBufferImpl* gpu_memory_buffer,
    base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb) {
  gpu_memory_buffer->MapAsync(
      base::BindOnce(&ClientSharedImage::ScopedMapping::FinishCreateAsync,
                     metadata, gpu_memory_buffer, std::move(result_cb)));
}

// static
void ClientSharedImage::ScopedMapping::FinishCreateAsync(
    SharedImageMetadata metadata,
    GpuMemoryBufferImpl* gpu_memory_buffer,
    base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb,
    bool success) {
  std::unique_ptr<ClientSharedImage::ScopedMapping> mapping;
  if (success) {
    mapping = ClientSharedImage::ScopedMapping::Create(
        metadata, gpu_memory_buffer, /*is_already_mapped=*/true);
  }
  std::move(result_cb).Run(std::move(mapping));
}

SkPixmap ClientSharedImage::ScopedMapping::GetSkPixmapForPlane(
    const uint32_t plane_index,
    SkImageInfo sk_image_info) {
  return SkPixmap(sk_image_info, GetMemoryForPlane(plane_index).data(),
                  Stride(plane_index));
}

ClientSharedImage::ClientSharedImage(
    const Mailbox& mailbox,
    const SharedImageInfo& info,
    const SyncToken& sync_token,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder,
    gfx::GpuMemoryBufferType gmb_type)
    : mailbox_(mailbox),
      metadata_(info.meta),
      debug_label_(info.debug_label),
      creation_sync_token_(sync_token),
      sii_holder_(std::move(sii_holder)) {
  CHECK(!mailbox.IsZero());
  CHECK(sii_holder_);
  texture_target_ = ComputeTextureTargetForSharedImage(metadata_, gmb_type,
                                                       sii_holder_->Get());
}

ClientSharedImage::ClientSharedImage(
    const Mailbox& mailbox,
    const SharedImageInfo& info,
    const SyncToken& sync_token,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder,
    base::WritableSharedMemoryMapping mapping)
    : ClientSharedImage(mailbox,
                        info,
                        sync_token,
                        sii_holder,
                        gfx::SHARED_MEMORY_BUFFER) {
  shared_memory_mapping_ = std::move(mapping);
  is_software_ = true;
}

ClientSharedImage::ClientSharedImage(
    const Mailbox& mailbox,
    const SharedImageInfo& info,
    const SyncToken& sync_token,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder,
    uint32_t texture_target)
    : mailbox_(mailbox),
      metadata_(info.meta),
      debug_label_(info.debug_label),
      creation_sync_token_(sync_token),
      sii_holder_(std::move(sii_holder)),
      texture_target_(texture_target) {
  // TODO(crbug.com/391788839): Create GpuMemoryBuffer from handle.
  CHECK(!mailbox.IsZero());
  CHECK(sii_holder_);
#if !BUILDFLAG(IS_FUCHSIA)
  CHECK(texture_target);
#endif
}

ClientSharedImage::ClientSharedImage(
    ExportedSharedImage exported_si,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder)
    : mailbox_(exported_si.mailbox_),
      metadata_(exported_si.metadata_),
      debug_label_(exported_si.debug_label_),
      creation_sync_token_(exported_si.creation_sync_token_),
      buffer_usage_(exported_si.buffer_usage_),
      sii_holder_(std::move(sii_holder)),
      texture_target_(exported_si.texture_target_) {
  if (exported_si.buffer_handle_) {
    gpu_memory_buffer_ = CreateGpuMemoryBufferImplFromHandle(
        std::move(exported_si.buffer_handle_.value()), metadata_.size,
        viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
            metadata_.format),
        exported_si.buffer_usage_.value(), metadata_.usage,
        base::BindRepeating(
            &ClientSharedImage::CopyNativeGmbToSharedMemoryAsync,
            base::Unretained(this)));
  }
  CHECK(!mailbox_.IsZero());
  CHECK(sii_holder_);
#if !BUILDFLAG(IS_FUCHSIA)
  CHECK(texture_target_);
#endif
}

ClientSharedImage::ClientSharedImage(ExportedSharedImage exported_si)
    : mailbox_(exported_si.mailbox_),
      metadata_(exported_si.metadata_),
      debug_label_(exported_si.debug_label_),
      creation_sync_token_(exported_si.creation_sync_token_),
      buffer_usage_(exported_si.buffer_usage_),
      texture_target_(exported_si.texture_target_) {
  if (exported_si.buffer_handle_) {
    gpu_memory_buffer_ = CreateGpuMemoryBufferImplFromHandle(
        std::move(exported_si.buffer_handle_.value()), metadata_.size,
        viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
            metadata_.format),
        exported_si.buffer_usage_.value(), metadata_.usage,
        base::BindRepeating(
            &ClientSharedImage::CopyNativeGmbToSharedMemoryAsync,
            base::Unretained(this)));
  }
  CHECK(!mailbox_.IsZero());
#if !BUILDFLAG(IS_FUCHSIA)
  CHECK(texture_target_);
#endif
}

ClientSharedImage::ClientSharedImage(
    const Mailbox& mailbox,
    const SharedImageInfo& info,
    const SyncToken& sync_token,
    GpuMemoryBufferHandleInfo handle_info,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder,
    scoped_refptr<base::UnsafeSharedMemoryPool> shared_memory_pool)
    : mailbox_(mailbox),
      metadata_(info.meta),
      debug_label_(info.debug_label),
      creation_sync_token_(sync_token),
      gpu_memory_buffer_(CreateGpuMemoryBufferImplFromHandle(
          std::move(handle_info.handle),
          metadata_.size,
          viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
              metadata_.format),
          handle_info.buffer_usage,
          info.meta.usage,
          base::BindRepeating(
              &ClientSharedImage::CopyNativeGmbToSharedMemoryAsync,
              base::Unretained(this)),
          std::move(shared_memory_pool))),
      buffer_usage_(handle_info.buffer_usage),
      sii_holder_(std::move(sii_holder)) {
  CHECK(!mailbox.IsZero());
  CHECK(sii_holder_);
  CHECK(gpu_memory_buffer_);
  texture_target_ = ComputeTextureTargetForSharedImage(
      metadata_, gpu_memory_buffer_->GetType(), sii_holder_->Get());
}

ClientSharedImage::ClientSharedImage(const Mailbox& mailbox,
                                     const SharedImageInfo& info)
    : mailbox_(mailbox), metadata_(info.meta), debug_label_(info.debug_label) {
  CHECK(!mailbox.IsZero());
  texture_target_ = GL_TEXTURE_2D;
}

ClientSharedImage::~ClientSharedImage() {
  if (!HasHolder()) {
    return;
  }

  auto sii = sii_holder_->Get();
  if (sii) {
    sii->DestroySharedImage(destruction_sync_token_, mailbox_);
  }
}

size_t ClientSharedImage::GetStrideForVideoFrame(uint32_t plane_index) const {
  if (async_map_invoked_callback_for_testing_) {
    return gfx::RowSizeForBufferFormat(
        size().width(),
        viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
            format()),
        plane_index);
  }
  CHECK(gpu_memory_buffer_);
  return gpu_memory_buffer_->stride(plane_index);
}

// Returns whether the underlying resource is shared memory without needing to
// Map() the shared image. This method is supposed to be used by VideoFrame
// temporarily as mentioned above in ::GetStrideForVideoFrame().
bool ClientSharedImage::IsSharedMemoryForVideoFrame() const {
  if (async_map_invoked_callback_for_testing_) {
    return true;
  }
  CHECK(gpu_memory_buffer_);
  return gpu_memory_buffer_->GetType() ==
         gfx::GpuMemoryBufferType::SHARED_MEMORY_BUFFER;
}

bool ClientSharedImage::AsyncMappingIsNonBlocking() const {
  if (async_map_invoked_callback_for_testing_) {
    return true;
  }
  CHECK(gpu_memory_buffer_);
  return gpu_memory_buffer_->AsyncMappingIsNonBlocking();
}

std::unique_ptr<ClientSharedImage::ScopedMapping> ClientSharedImage::Map() {
  std::unique_ptr<ClientSharedImage::ScopedMapping> scoped_mapping;
  if (shared_memory_mapping_.IsValid()) {
    scoped_mapping = ScopedMapping::Create(metadata_, &shared_memory_mapping_);
  } else {
    scoped_mapping = ScopedMapping::Create(metadata_, gpu_memory_buffer_.get(),
                                           /*is_already_mapped=*/false);
  }

  if (!scoped_mapping) {
    LOG(ERROR) << "Unable to create ScopedMapping";
  }
  return scoped_mapping;
}

void ClientSharedImage::FinishMapAsyncForTests(
    base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb,
    bool success) {
  std::unique_ptr<ScopedMapping> mapping;
  if (success) {
    mapping = std::make_unique<ScopedMappingForTests>(
        size(),
        viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
            format()));
  }
  std::move(result_cb).Run(std::move(mapping));
}

void ClientSharedImage::MapAsync(
    base::OnceCallback<void(std::unique_ptr<ScopedMapping>)> result_cb) {
  if (async_map_invoked_callback_for_testing_) {
    if (premapped_for_testing_) {
      FinishMapAsyncForTests(std::move(result_cb), true);
    } else {
      async_map_invoked_callback_for_testing_.Run(
          base::BindOnce(&ClientSharedImage::FinishMapAsyncForTests,
                         base::Unretained(this), std::move(result_cb)));
    }
    return;
  }

  ScopedMapping::StartCreateAsync(metadata_, gpu_memory_buffer_.get(),
                                  std::move(result_cb));
}

gfx::GpuMemoryBufferHandle ClientSharedImage::CloneGpuMemoryBufferHandle()
    const {
  CHECK(gpu_memory_buffer_);
  return gpu_memory_buffer_->CloneHandle();
}

uint32_t ClientSharedImage::GetTextureTarget() {
#if !BUILDFLAG(IS_FUCHSIA)
  // Check that `texture_target_` has been initialized (note that on Fuchsia it
  // is possible for `texture_target_` to be initialized to 0: Fuchsia does not
  // support import of external images to GL for usage with external sampling.
  // SetTextureTarget() sets the texture target to 0 in the case where external
  // sampling would be used to signal this lack of support to the //media code,
  // which detects the lack of support *based on* on the texture target being
  // 0).
  CHECK(texture_target_);
#endif
  return texture_target_;
}

scoped_refptr<ClientSharedImage> ClientSharedImage::MakeUnowned() {
  return ClientSharedImage::ImportUnowned(Export());
}

ExportedSharedImage ClientSharedImage::Export(bool with_buffer_handle) {
  if (creation_sync_token_.HasData() &&
      !creation_sync_token_.verified_flush()) {
    sii_holder_->Get()->VerifySyncToken(creation_sync_token_);
  }
  std::optional<gfx::GpuMemoryBufferHandle> buffer_handle;
  std::optional<gfx::BufferUsage> buffer_usage;
  if (with_buffer_handle && gpu_memory_buffer_) {
    buffer_handle = gpu_memory_buffer_->CloneHandle();
    buffer_usage = buffer_usage_.value();
  }
  return ExportedSharedImage(mailbox_, metadata_, creation_sync_token_,
                             debug_label_, std::move(buffer_handle),
                             buffer_usage, texture_target_);
}

scoped_refptr<ClientSharedImage> ClientSharedImage::ImportUnowned(
    ExportedSharedImage exported_shared_image) {
  return base::WrapRefCounted<ClientSharedImage>(
      new ClientSharedImage(std::move(exported_shared_image)));
}

gpu::SyncToken ClientSharedImage::BackingWasExternallyUpdated(
    const gpu::SyncToken& sync_token) {
  CHECK(sii_holder_);
  auto sii = sii_holder_->Get();
  if (!sii) {
    return gpu::SyncToken();
  }

  sii->UpdateSharedImage(sync_token, mailbox());
  return sii->GenUnverifiedSyncToken();
}

void ClientSharedImage::OnMemoryDump(
    base::trace_event::ProcessMemoryDump* pmd,
    const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
    int importance) {
  auto tracing_guid = GetGUIDForTracing();
  pmd->CreateSharedGlobalAllocatorDump(tracing_guid);
  pmd->AddOwnershipEdge(buffer_dump_guid, tracing_guid, importance);
}

void ClientSharedImage::BeginAccess(bool readonly) {
  base::AutoLock lock(lock_);
  if (readonly) {
    CHECK(!has_writer_ ||
          usage().Has(SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE));
    num_readers_++;
  } else {
    CHECK(!has_writer_);
    CHECK(num_readers_ == 0 ||
          usage().Has(SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE));
    has_writer_ = true;
  }
}

void ClientSharedImage::EndAccess(bool readonly) {
  base::AutoLock lock(lock_);
  if (readonly) {
    CHECK(num_readers_ > 0);
    num_readers_--;
  } else {
    CHECK(has_writer_);
    has_writer_ = false;
  }
}

std::unique_ptr<SharedImageTexture> ClientSharedImage::CreateGLTexture(
    gles2::GLES2Interface* gl) {
  SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel", debug_label_);
  SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage", metadata_.usage);
  DUMP_WILL_BE_CHECK(metadata_.usage.Has(SHARED_IMAGE_USAGE_GLES2_READ) ||
                     metadata_.usage.Has(SHARED_IMAGE_USAGE_GLES2_WRITE));
  return base::WrapUnique(new SharedImageTexture(gl, this));
}

std::unique_ptr<RasterScopedAccess> ClientSharedImage::BeginRasterAccess(
    InterfaceBase* raster_interface,
    const SyncToken& sync_token,
    bool readonly) {
  bool has_raster_usage =
      metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_READ) ||
      metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_WRITE) ||
      metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_COPY_SOURCE);
  if (!has_raster_usage) {
    SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel", debug_label_);
    SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage", metadata_.usage);
    DUMP_WILL_BE_CHECK(has_raster_usage);
  }
  return base::WrapUnique(
      new RasterScopedAccess(raster_interface, this, sync_token, readonly));
}

std::unique_ptr<RasterScopedAccess>
ClientSharedImage::BeginGLAccessForCopySharedImage(InterfaceBase* gl_interface,
                                                   const SyncToken& sync_token,
                                                   bool readonly) {
  return BeginRasterAccess(gl_interface, sync_token, readonly);
}

#if BUILDFLAG(IS_WIN)
void ClientSharedImage::SetUsePreMappedMemory(bool use_premapped_memory) {
  CHECK(gpu_memory_buffer_);
  gpu_memory_buffer_->SetUsePreMappedMemory(use_premapped_memory);
}
#endif

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting() {
  return CreateForTesting(viz::SinglePlaneFormat::kRGBA_8888, GL_TEXTURE_2D);
}

scoped_refptr<ClientSharedImage> ClientSharedImage::CreateSoftwareForTesting() {
  auto shared_image = CreateForTesting();  // IN-TEST
  shared_image->is_software_ = true;
  return shared_image;
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    const SharedImageMetadata& metadata) {
  return CreateForTesting(metadata, GL_TEXTURE_2D);  // IN-TEST
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    viz::SharedImageFormat format,
    uint32_t texture_target) {
  SharedImageMetadata metadata;
  metadata.format = format;
  metadata.size = gfx::Size(64, 64);
  metadata.color_space = gfx::ColorSpace::CreateSRGB();
  metadata.surface_origin = kTopLeft_GrSurfaceOrigin;
  metadata.alpha_type = kOpaque_SkAlphaType;
  metadata.usage = gpu::SharedImageUsageSet();

  return CreateForTesting(metadata, texture_target);
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    SharedImageUsageSet usage) {
  SharedImageMetadata metadata;
  metadata.format = viz::SinglePlaneFormat::kRGBA_8888;
  metadata.size = gfx::Size(64, 64);
  metadata.color_space = gfx::ColorSpace::CreateSRGB();
  metadata.surface_origin = kTopLeft_GrSurfaceOrigin;
  metadata.alpha_type = kOpaque_SkAlphaType;
  metadata.usage = usage;

  return CreateForTesting(metadata, GL_TEXTURE_2D);
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    const SharedImageMetadata& metadata,
    uint32_t texture_target) {
  return ImportUnowned(ExportedSharedImage(
      Mailbox::Generate(), metadata, SyncToken(), "CSICreateForTesting",
      std::nullopt, std::nullopt, texture_target));
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    const Mailbox& mailbox,
    const SharedImageMetadata& metadata,
    const SyncToken& sync_token,
    gfx::BufferUsage buffer_usage,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder) {
  SharedImageInfo info(metadata, "CSICreateForTesting");

  auto gpu_memory_buffer = GpuMemoryBufferImplSharedMemory::CreateForTesting(
      info.meta.size,
      viz::SharedImageFormatToBufferFormatRestrictedUtils::ToBufferFormat(
          info.meta.format),
      buffer_usage);

  // Since the |gpu_memory_buffer| here is always a shared memory, clear the
  // external sampler prefs if it is already set by client.
  // https://issues.chromium.org/339546249.
  if (info.meta.format.PrefersExternalSampler()) {
    info.meta.format.ClearPrefersExternalSampler();
  }

  auto client_si = base::MakeRefCounted<ClientSharedImage>(
      mailbox, info, sync_token, sii_holder, gfx::SHARED_MEMORY_BUFFER);
  client_si->gpu_memory_buffer_ = std::move(gpu_memory_buffer);
  client_si->buffer_usage_ = buffer_usage;
  return client_si;
}

// static
scoped_refptr<ClientSharedImage> ClientSharedImage::CreateForTesting(
    const Mailbox& mailbox,
    const SharedImageMetadata& metadata,
    const SyncToken& sync_token,
    bool premapped,
    const AsyncMapInvokedCallback& callback,
    gfx::BufferUsage buffer_usage,
    scoped_refptr<SharedImageInterfaceHolder> sii_holder) {
  SharedImageInfo info(metadata, "CSICreateForTesting");

  auto client_si = base::MakeRefCounted<ClientSharedImage>(
      mailbox, info, sync_token, sii_holder, gfx::SHARED_MEMORY_BUFFER);
  client_si->async_map_invoked_callback_for_testing_ = callback;
  client_si->premapped_for_testing_ = premapped;
  client_si->buffer_usage_ = buffer_usage;
  return client_si;
}

void ClientSharedImage::CopyNativeGmbToSharedMemoryAsync(
    gfx::GpuMemoryBufferHandle buffer_handle,
    base::UnsafeSharedMemoryRegion memory_region,
    base::OnceCallback<void(bool)> callback) {
  // Lazily create the |task_runner_|.
  if (!copy_native_buffer_to_shmem_task_runner_) {
    copy_native_buffer_to_shmem_task_runner_ =
        base::ThreadPool::CreateSingleThreadTaskRunner({base::MayBlock()});
    CHECK(copy_native_buffer_to_shmem_task_runner_);
  }

  if (!copy_native_buffer_to_shmem_task_runner_->BelongsToCurrentThread()) {
    copy_native_buffer_to_shmem_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&ClientSharedImage::CopyNativeGmbToSharedMemoryAsync,
                       base::Unretained(this), std::move(buffer_handle),
                       std::move(memory_region), std::move(callback)));
    return;
  }

  auto sii = sii_holder_->Get();
  if (!sii) {
    DLOG(WARNING) << "No SharedImageInterface.";
    std::move(callback).Run(false);
    return;
  }
  sii->CopyNativeGmbToSharedMemoryAsync(
      std::move(buffer_handle), std::move(memory_region),
      mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback),
                                                  /*result=*/false));
}

std::unique_ptr<WebGPUTextureScopedAccess>
ClientSharedImage::BeginWebGPUTextureAccess(
    webgpu::WebGPUInterface* webgpu,
    const SyncToken& sync_token,
    const wgpu::dawn::wire::client::Device& device,
    const wgpu::dawn::wire::client::TextureDescriptor& desc,
    uint64_t usage,
    webgpu::MailboxFlags mailbox_flags) {
  return base::WrapUnique(new WebGPUTextureScopedAccess(
      webgpu, this, sync_token, device, desc, usage, mailbox_flags));
}

ExportedSharedImage::ExportedSharedImage() = default;
ExportedSharedImage::~ExportedSharedImage() = default;

ExportedSharedImage::ExportedSharedImage(ExportedSharedImage&& other) = default;
ExportedSharedImage& ExportedSharedImage::operator=(
    ExportedSharedImage&& other) = default;

ExportedSharedImage::ExportedSharedImage(
    const Mailbox& mailbox,
    const SharedImageMetadata& metadata,
    const SyncToken& sync_token,
    std::string debug_label,
    std::optional<gfx::GpuMemoryBufferHandle> buffer_handle,
    std::optional<gfx::BufferUsage> buffer_usage,
    uint32_t texture_target)
    : mailbox_(mailbox),
      metadata_(metadata),
      creation_sync_token_(sync_token),
      debug_label_(debug_label),
      buffer_handle_(std::move(buffer_handle)),
      buffer_usage_(buffer_usage),
      texture_target_(texture_target) {}

ExportedSharedImage ExportedSharedImage::Clone() const {
  std::optional<gfx::GpuMemoryBufferHandle> handle = std::nullopt;
  if (buffer_handle_.has_value()) {
    handle = buffer_handle_->Clone();
  }
  return ExportedSharedImage(mailbox_, metadata_, creation_sync_token_,
                             debug_label_, std::move(handle), buffer_usage_,
                             texture_target_);
}

SharedImageTexture::ScopedAccess::ScopedAccess(SharedImageTexture* texture,
                                               const SyncToken& sync_token,
                                               bool readonly)
    : texture_(texture), readonly_(readonly) {
  texture_->gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  texture_->gl_->BeginSharedImageAccessDirectCHROMIUM(
      texture->id(), (readonly_)
                         ? GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM
                         : GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
}

SharedImageTexture::ScopedAccess::~ScopedAccess() {
  CHECK(is_access_ended_);
}

void SharedImageTexture::ScopedAccess::DidEndAccess() {
  is_access_ended_ = true;
  texture_->DidEndAccess(readonly_);
}

// static
SyncToken SharedImageTexture::ScopedAccess::EndAccess(
    std::unique_ptr<SharedImageTexture::ScopedAccess> scoped_shared_image) {
  gles2::GLES2Interface* gl = scoped_shared_image->texture_->gl_;
  gl->EndSharedImageAccessDirectCHROMIUM(scoped_shared_image->texture_->id());
  scoped_shared_image->DidEndAccess();
  SyncToken sync_token;
  gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
  return sync_token;
}

SharedImageTexture::SharedImageTexture(gles2::GLES2Interface* gl,
                                       ClientSharedImage* shared_image)
    : gl_(gl), shared_image_(shared_image) {
  CHECK(gl_);
  CHECK(shared_image_);
  gl_->WaitSyncTokenCHROMIUM(
      shared_image_->creation_sync_token().GetConstData());
  id_ = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(
      shared_image_->mailbox().name);
}

SharedImageTexture::~SharedImageTexture() {
  CHECK(!has_active_access_);
  gl_->DeleteTextures(1, &id_);
}

std::unique_ptr<SharedImageTexture::ScopedAccess>
SharedImageTexture::BeginAccess(const SyncToken& sync_token, bool readonly) {
  CHECK(!has_active_access_);
  SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel",
                            shared_image_->debug_label());
  SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage", shared_image_->usage());
  if (readonly) {
    DUMP_WILL_BE_CHECK(
        shared_image_->usage().Has(SHARED_IMAGE_USAGE_GLES2_READ));
  } else {
    DUMP_WILL_BE_CHECK(
        shared_image_->usage().Has(SHARED_IMAGE_USAGE_GLES2_WRITE));
  }
  has_active_access_ = true;
  shared_image_->BeginAccess(readonly);
  return base::WrapUnique(
      new SharedImageTexture::ScopedAccess(this, sync_token, readonly));
}

void SharedImageTexture::DidEndAccess(bool readonly) {
  has_active_access_ = false;
  shared_image_->EndAccess(readonly);
}

RasterScopedAccess::RasterScopedAccess(InterfaceBase* raster_interface,
                                       ClientSharedImage* shared_image,
                                       const SyncToken& sync_token,
                                       bool readonly)
    : raster_interface_(raster_interface),
      shared_image_(shared_image),
      readonly_(readonly) {
  CHECK(raster_interface_);
  shared_image_->BeginAccess(readonly);
  raster_interface_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  bool has_read_usage =
      shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_READ) ||
      shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_COPY_SOURCE);
  bool has_write_usage =
      shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_WRITE);
  if (readonly && !has_read_usage) {
    SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel",
                              shared_image_->debug_label());
    SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage",
                            shared_image_->usage());
    DUMP_WILL_BE_CHECK(has_read_usage);
  } else if (!readonly && !has_write_usage) {
    SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel",
                              shared_image_->debug_label());
    SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage",
                            shared_image_->usage());
    DUMP_WILL_BE_CHECK(has_write_usage);
  }
}

// static
SyncToken RasterScopedAccess::EndAccess(
    std::unique_ptr<RasterScopedAccess> scoped_access) {
  InterfaceBase* raster_interface = scoped_access->raster_interface_;
  SyncToken sync_token;
  scoped_access->shared_image_->EndAccess(scoped_access->readonly_);
  raster_interface->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
  return sync_token;
}

WebGPUTextureScopedAccess::WebGPUTextureScopedAccess(
    webgpu::WebGPUInterface* webgpu,
    ClientSharedImage* shared_image,
    const SyncToken& sync_token,
    const wgpu::dawn::wire::client::Device& device,
    const wgpu::dawn::wire::client::TextureDescriptor& desc,
    uint64_t usage,
    webgpu::MailboxFlags mailbox_flags)
    : webgpu_(webgpu), shared_image_(shared_image) {
  // Wait on any work using the image.
  webgpu_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());

  // Produce and inject image to WebGPU texture
  webgpu::ReservedTexture reservation = webgpu_->ReserveTexture(
      device.Get(), &static_cast<const WGPUTextureDescriptor&>(desc));
  DCHECK(reservation.texture);

  // If either |desc.usage| or |usage| contains the following flags, the access
  // is not read-only.
  const wgpu::TextureUsage write_flags = wgpu::TextureUsage::CopyDst |
                                         wgpu::TextureUsage::RenderAttachment |
                                         wgpu::TextureUsage::StorageBinding;
  readonly_ = !((desc.usage | wgpu::TextureUsage{usage}) & write_flags);
  shared_image_->BeginAccess(readonly_);
  texture_ = base::WrapUnique(
      new wgpu::Texture(wgpu::Texture::Acquire(reservation.texture)));
  device_id_ = reservation.deviceId;
  device_generation_ = reservation.deviceGeneration;
  texture_id_ = reservation.id;
  texture_generation_ = reservation.generation;

  // This may fail because gl_backing resource cannot produce dawn
  // representation.
  webgpu_->AssociateMailbox(
      device_id_, device_generation_, texture_id_, texture_generation_,
      static_cast<uint64_t>(desc.usage), static_cast<uint64_t>(usage),
      reinterpret_cast<const WGPUTextureFormat*>(desc.viewFormats),
      base::checked_cast<GLuint>(desc.viewFormatCount), mailbox_flags,
      shared_image->mailbox());
}

WebGPUTextureScopedAccess::~WebGPUTextureScopedAccess() = default;

SyncToken WebGPUTextureScopedAccess::EndAccess(
    std::unique_ptr<WebGPUTextureScopedAccess> scoped_access) {
  webgpu::WebGPUInterface* webgpu = scoped_access->webgpu_;
  SyncToken finished_access_token;
  if (scoped_access->needs_present_) {
    webgpu->DissociateMailboxForPresent(
        scoped_access->device_id_, scoped_access->device_generation_,
        scoped_access->texture_id_, scoped_access->texture_generation_);
  } else {
    webgpu->DissociateMailbox(scoped_access->texture_id_,
                              scoped_access->texture_generation_);
  }

  scoped_access->shared_image_->EndAccess(scoped_access->readonly_);
  webgpu->GenUnverifiedSyncTokenCHROMIUM(finished_access_token.GetData());
  return finished_access_token;
}

const wgpu::dawn::wire::client::Texture& WebGPUTextureScopedAccess::texture() {
  return *texture_.get();
}

void WebGPUTextureScopedAccess::SetNeedsPresent(bool needs_present) {
  needs_present_ = needs_present;
}

std::unique_ptr<WebGPUBufferScopedAccess>
ClientSharedImage::BeginWebGPUBufferAccess(
    webgpu::WebGPUInterface* webgpu,
    const SyncToken& sync_token,
    const wgpu::dawn::wire::client::Device& device,
    const wgpu::dawn::wire::client::BufferDescriptor& desc,
    uint64_t usage,
    webgpu::MailboxFlags mailbox_flags) {
  return base::WrapUnique(new WebGPUBufferScopedAccess(
      webgpu, this, sync_token, device, desc, usage, mailbox_flags));
}

WebGPUBufferScopedAccess::WebGPUBufferScopedAccess(
    webgpu::WebGPUInterface* webgpu,
    ClientSharedImage* shared_image,
    const SyncToken& sync_token,
    const wgpu::dawn::wire::client::Device& device,
    const wgpu::dawn::wire::client::BufferDescriptor& desc,
    uint64_t usage,
    webgpu::MailboxFlags mailbox_flags)
    : webgpu_(webgpu), shared_image_(shared_image) {
  // Wait on any work using the buffer.
  webgpu_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());

  webgpu::ReservedBuffer reservation = webgpu_->ReserveBuffer(
      device.Get(), &static_cast<const WGPUBufferDescriptor&>(desc));
  DCHECK(reservation.buffer);

  wire_buffer_id_ = reservation.id;
  wire_buffer_generation_ = reservation.id;

  // We currently only use storage buffers. Which are always read-write.
  shared_image_->BeginAccess(false);

  buffer_ = base::WrapUnique(
      new wgpu::Buffer(wgpu::Buffer::Acquire(reservation.buffer)));

  webgpu_->AssociateMailboxForBuffer(
      reservation.deviceId, reservation.deviceGeneration, wire_buffer_id_,
      wire_buffer_generation_, static_cast<uint64_t>(desc.usage),
      shared_image_->mailbox());
}

WebGPUBufferScopedAccess::~WebGPUBufferScopedAccess() = default;

SyncToken WebGPUBufferScopedAccess::EndAccess(
    std::unique_ptr<WebGPUBufferScopedAccess> scoped_access) {
  webgpu::WebGPUInterface* webgpu = scoped_access->webgpu_;
  SyncToken finished_access_token;
  webgpu->DissociateMailboxForBuffer(scoped_access->wire_buffer_id_,
                                     scoped_access->wire_buffer_generation_);
  scoped_access->shared_image_->EndAccess(false);

  // SyncToken must be verified to allow use from another pipe.
  webgpu->GenSyncTokenCHROMIUM(finished_access_token.GetData());
  return finished_access_token;
}

const wgpu::Buffer& WebGPUBufferScopedAccess::buffer() {
  return *buffer_.get();
}

}  // namespace gpu
