// Copyright 2019 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 "build/build_config.h"
#include "components/viz/test/test_gpu_service_holder.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/client/webgpu_implementation.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/webgpu_decoder.h"
#include "gpu/command_buffer/tests/webgpu_test.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_test_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/init/gl_factory.h"

#define SKIP_TEST_IF(condition) \
  if (condition)                \
  GTEST_SKIP() << #condition

namespace gpu {
namespace {

class MockBufferMapCallback {
 public:
  MOCK_METHOD(void,
              Call,
              (wgpu::MapAsyncStatus status, wgpu::StringView message));
};
std::unique_ptr<testing::StrictMock<MockBufferMapCallback>>
    mock_buffer_map_callback;

void ToMockBufferMapCallback(wgpu::MapAsyncStatus status,
                             wgpu::StringView message) {
  mock_buffer_map_callback->Call(status, message);
}

struct WebGPUMailboxTextureTestParams : WebGPUTest::Options {
  viz::SharedImageFormat format;
};

std::ostream& operator<<(std::ostream& os,
                         const WebGPUMailboxTextureTestParams& options) {
  DCHECK(options.format == viz::SinglePlaneFormat::kRGBA_8888 ||
         options.format == viz::SinglePlaneFormat::kBGRA_8888 ||
         options.format == viz::SinglePlaneFormat::kRGBA_F16);
  os << options.format.ToTestParamString();

  if (options.use_skia_graphite) {
    os << "_SkiaGraphite";
  }
  if (options.enable_unsafe_webgpu) {
    os << "_UnsafeWebGPU";
  }
  if (options.force_fallback_adapter) {
    os << "_FallbackAdapter";
  }

  return os;
}

uint32_t BytesPerTexel(viz::SharedImageFormat format) {
  if ((format == viz::SinglePlaneFormat::kRGBA_8888) ||
      (format == viz::SinglePlaneFormat::kBGRA_8888)) {
    return 4;
  }

  if (format == viz::SinglePlaneFormat::kRGBA_F16) {
    return 8;
  }

  NOTREACHED();
}

wgpu::TextureFormat VizToWGPUFormat(const viz::SharedImageFormat& format) {
  // This function provides the inverse mapping of `WGPUFormatToViz` (located in
  // webgpu_swap_buffer_provider.cc).
  if (format == viz::SinglePlaneFormat::kBGRA_8888) {
    return wgpu::TextureFormat::BGRA8Unorm;
  }
  if (format == viz::SinglePlaneFormat::kRGBA_8888) {
    return wgpu::TextureFormat::RGBA8Unorm;
  }
  if (format == viz::SinglePlaneFormat::kRGBA_F16) {
    return wgpu::TextureFormat::RGBA16Float;
  }
  NOTREACHED() << "Unsupported format: " << format.ToString();
}

}  // namespace

class WebGPUMailboxTestBase : public WebGPUTest {
 protected:
  template <typename T>
  static error::Error ExecuteCmd(webgpu::WebGPUDecoder* decoder, const T& cmd) {
    static_assert(T::kArgFlags == cmd::kFixed,
                  "T::kArgFlags should equal cmd::kFixed");
    int entries_processed = 0;
    return decoder->DoCommands(1, (const void*)&cmd,
                               ComputeNumEntries(sizeof(cmd)),
                               &entries_processed);
  }

  template <typename T>
  static error::Error ExecuteImmediateCmd(webgpu::WebGPUDecoder* decoder,
                                          const T& cmd,
                                          size_t data_size) {
    static_assert(T::kArgFlags == cmd::kAtLeastN,
                  "T::kArgFlags should equal cmd::kAtLeastN");
    int entries_processed = 0;
    return decoder->DoCommands(1, (const void*)&cmd,
                               ComputeNumEntries(sizeof(cmd) + data_size),
                               &entries_processed);
  }
};

class WebGPUMailboxTextureTest
    : public WebGPUMailboxTestBase,
      public testing::WithParamInterface<WebGPUMailboxTextureTestParams> {
 public:
  static std::vector<WebGPUMailboxTextureTestParams> TestParams() {
    WebGPUMailboxTextureTestParams options = {};

    WebGPUMailboxTextureTestParams fallback_options = {};
    fallback_options.force_fallback_adapter = true;
    // Unsafe WebGPU currently required for SwiftShader fallback.
    fallback_options.enable_unsafe_webgpu = true;

    std::vector<WebGPUMailboxTextureTestParams> params;

    for (viz::SharedImageFormat format : {
// TODO(crbug.com/40823053): Support "rgba8unorm" canvas context format on Mac
#if !BUILDFLAG(IS_MAC)
           viz::SinglePlaneFormat::kRGBA_8888,
#endif  // !BUILDFLAG(IS_MAC)
               viz::SinglePlaneFormat::kBGRA_8888,
               viz::SinglePlaneFormat::kRGBA_F16,
         }) {
      WebGPUMailboxTextureTestParams o = options;
      o.format = format;
#if BUILDFLAG(IS_LINUX)
      // Linux does not support creation of RGBA_F16 GpuMemoryBuffers, which
      // causes SharedImage creation in these tests to fail.
      if (o.format != viz::SinglePlaneFormat::kRGBA_F16) {
        params.push_back(o);
      }
#else
      params.push_back(o);
#endif

      // Test SwiftShader fallback both with and without SkiaGraphite
      o = fallback_options;
      o.format = format;

      o.use_skia_graphite = false;
      params.push_back(o);

      // Note: Only windows & Mac have Graphite supported for now.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
      o.use_skia_graphite = true;
      params.push_back(o);
#endif
    }
    return params;
  }

 protected:
  void SetUp() override {
    SKIP_TEST_IF(!WebGPUSupported());
    SKIP_TEST_IF(!WebGPUSharedImageSupported());
    WebGPUTest::SetUp();
    Initialize(GetParam());

    device_ = GetNewDevice();

    mock_buffer_map_callback =
        std::make_unique<testing::StrictMock<MockBufferMapCallback>>();
  }

  void TearDown() override {
    mock_buffer_map_callback = nullptr;
    // Wait for all operations to catch any validation or device lost errors.
    PollUntilIdle();
    device_ = nullptr;
    WebGPUTest::TearDown();
  }

  struct AssociateMailboxCmdStorage {
    webgpu::cmds::AssociateMailboxImmediate cmd;

    // Immediate data is copied into the space immediately following `cmd`.
    // Allocate space to hold up to 1 mailbox and 2 view formats.
    GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
    std::array<WGPUTextureFormat, 2u> view_formats;
  };

  enum class AccessType { Read, Write, ReadWrite };

  SharedImageUsageSet GetSharedImageUsage(AccessType access_type) {
    SharedImageUsageSet webgpu_usage;

    // With the fallback adapter, reading/writing from the SharedImage will
    // occur via Skia.
    SharedImageUsageSet fallback_usage;

    switch (access_type) {
      case AccessType::Read:
        webgpu_usage = SHARED_IMAGE_USAGE_WEBGPU_READ;
        fallback_usage = SHARED_IMAGE_USAGE_RASTER_READ;
        break;
      case AccessType::Write:
        webgpu_usage = SHARED_IMAGE_USAGE_WEBGPU_WRITE;
        fallback_usage = SHARED_IMAGE_USAGE_RASTER_WRITE;
        break;
      case AccessType::ReadWrite:
        webgpu_usage =
            SHARED_IMAGE_USAGE_WEBGPU_READ | SHARED_IMAGE_USAGE_WEBGPU_WRITE;
        fallback_usage =
            SHARED_IMAGE_USAGE_RASTER_READ | SHARED_IMAGE_USAGE_RASTER_WRITE;
        break;
    }

    auto si_usage = webgpu_usage;
    if (IsUsingFallbackAdapter()) {
      si_usage |= fallback_usage;
    }

    return si_usage;
  }

  void InitializeTextureColor(
      wgpu::Device device,
      scoped_refptr<gpu::ClientSharedImage> shared_image,
      wgpu::Color clearValue) {
    wgpu::TextureDescriptor desc = {
        .usage = wgpu::TextureUsage::RenderAttachment,
    };

    std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
        shared_image->BeginWebGPUTextureAccess(
            webgpu(), GetSharedImageInterface()->GenVerifiedSyncToken(), device,
            desc, /*usage=*/0, webgpu::WEBGPU_MAILBOX_NONE);

    // Clear the texture using a render pass.
    wgpu::RenderPassColorAttachment color_desc = {};
    color_desc.view = webgpu_scoped_access->texture().CreateView();
    color_desc.loadOp = wgpu::LoadOp::Clear;
    color_desc.storeOp = wgpu::StoreOp::Store;
    color_desc.clearValue = clearValue;

    wgpu::RenderPassDescriptor render_pass_desc = {};
    render_pass_desc.colorAttachmentCount = 1;
    render_pass_desc.colorAttachments = &color_desc;

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&render_pass_desc);
    pass.End();
    wgpu::CommandBuffer commands = encoder.Finish();

    wgpu::Queue queue = device.GetQueue();
    queue.Submit(1, &commands);

    WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
  }

  void UninitializeTexture(wgpu::Device device, wgpu::Texture texture) {
    wgpu::RenderPassColorAttachment color_desc = {};
    color_desc.view = texture.CreateView();
    color_desc.loadOp = wgpu::LoadOp::Load;
    color_desc.storeOp = wgpu::StoreOp::Discard;

    wgpu::RenderPassDescriptor render_pass_desc = {};
    render_pass_desc.colorAttachmentCount = 1;
    render_pass_desc.colorAttachments = &color_desc;

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&render_pass_desc);
    pass.End();
    wgpu::CommandBuffer commands = encoder.Finish();

    wgpu::Queue queue = device.GetQueue();
    queue.Submit(1, &commands);
  }

  wgpu::Device device_;
};

TEST_P(WebGPUMailboxTextureTest, AssociateMailboxCmd) {
  // Create the shared image
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  webgpu::ReservedTexture reservation = webgpu()->ReserveTexture(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedTexture reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        const gpu::Mailbox& mailbox = shared_image->mailbox();

        // Error case: device client id doesn't exist.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId + 1, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: device generation is invalid.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration + 1,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: texture ID invalid for the wire server.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id + 1, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: invalid texture usage.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       UINT64_MAX, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: invalid internal texture usage.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding,
                       UINT64_MAX, webgpu::WEBGPU_MAILBOX_NONE,
                       0u, ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Prep packed data for packing view formats and the mailbox.
        std::vector<GLuint> packed_data;
        packed_data.resize(sizeof(mailbox.name) / sizeof(uint32_t));
        memcpy(reinterpret_cast<char*>(packed_data.data()), &mailbox.name,
               sizeof(mailbox.name));

        uint32_t view_format_count = 0u;
        if (GetParam().format == viz::SinglePlaneFormat::kRGBA_F16) {
        } else if (GetParam().format == viz::SinglePlaneFormat::kRGBA_8888) {
          view_format_count = 1u;
          packed_data.push_back(
              static_cast<uint32_t>(WGPUTextureFormat_RGBA8UnormSrgb));
        } else if (GetParam().format == viz::SinglePlaneFormat::kBGRA_8888) {
          view_format_count = 2u;
          packed_data.push_back(
              static_cast<uint32_t>(WGPUTextureFormat_BGRA8UnormSrgb));
          packed_data.push_back(
              static_cast<uint32_t>(WGPUTextureFormat_BGRA8Unorm));
        } else {
          NOTREACHED();
        }

        // Error case: packed data empty.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation, UINT64_MAX, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u, 0u, packed_data.data());
          EXPECT_EQ(error::kOutOfBounds,
                    ExecuteImmediateCmd(decoder, cmd.cmd, 0u));
        }

        // Error case: packed data smaller than mailbox.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation, UINT64_MAX, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, view_format_count,
                       ComputeNumEntries(sizeof(mailbox.name)) - 1u,
                       packed_data.data());
          EXPECT_EQ(error::kOutOfBounds,
                    ExecuteImmediateCmd(decoder, cmd.cmd,
                                        sizeof(uint32_t) * packed_data.size()));
        }

        // Error case: packed data size incorrect.
        for (int adjustment : {-1, -2}) {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, view_format_count,
                       packed_data.size() + adjustment, packed_data.data());
          EXPECT_EQ(error::kOutOfBounds,
                    ExecuteImmediateCmd(decoder, cmd.cmd,
                                        sizeof(uint32_t) * packed_data.size()));
        }

        // Error case: view_format_count incorrect.
        for (int adjustment : {-1, 1}) {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE,
                       view_format_count + adjustment, packed_data.size(),
                       packed_data.data());
          EXPECT_EQ(error::kOutOfBounds,
                    ExecuteImmediateCmd(decoder, cmd.cmd,
                                        sizeof(uint32_t) * packed_data.size()));
        }

        // Control case: test a successful call to AssociateMailbox.
        // The control case is not put first because it modifies the internal
        // state of the Dawn wire server and would make calls with the same
        // texture ID and generation invalid.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, view_format_count,
                       packed_data.size(), packed_data.data());
          EXPECT_EQ(error::kNoError,
                    ExecuteImmediateCmd(decoder, cmd.cmd,
                                        sizeof(uint32_t) * packed_data.size()));
        }

        // Error case: associated to an already associated texture.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Dissociate the image from the control case to remove its reference.
        {
          webgpu::cmds::DissociateMailbox cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kNoError, ExecuteCmd(decoder, cmd));
        }
      },
      GetDecoder(), reservation, std::move(shared_image)));

  GetGpuServiceHolder()
      ->gpu_main_thread_task_runner()
      ->RunsTasksInCurrentSequence();
}

// Test that AssociateMailbox with a bad mailbox produces an error texture.
TEST_P(WebGPUMailboxTextureTest,
       AssociateMailboxCmdBadMailboxMakesErrorTexture) {
  // Create the shared image
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  webgpu::ReservedTexture reservation = webgpu()->ReserveTexture(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedTexture reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        // Error case: invalid mailbox
        {
          gpu::Mailbox bad_mailbox;
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(bad_mailbox.name)),
                       reinterpret_cast<const GLuint*>(&bad_mailbox.name));
          EXPECT_EQ(
              error::kNoError,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(bad_mailbox.name)));
        }
      },
      GetDecoder(), reservation, std::move(shared_image)));

  wgpu::Texture texture = wgpu::Texture::Acquire(reservation.texture);

  // Expect an error when creating a view since the texture is an error.
  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation,
                      texture.CreateView());
}

TEST_P(WebGPUMailboxTextureTest, DissociateMailboxCmd) {
  // Create the shared image
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  webgpu::ReservedTexture reservation = webgpu()->ReserveTexture(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedTexture reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        const gpu::Mailbox& mailbox = shared_image->mailbox();

        // Associate a mailbox so we can later dissociate it.
        {
          AssociateMailboxCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUTextureUsage_TextureBinding, 0u,
                       webgpu::WEBGPU_MAILBOX_NONE, 0u,
                       ComputeNumEntries(sizeof(mailbox.name)),
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(decoder, cmd.cmd,
                                                         sizeof(mailbox.name)));
        }

        // Error case: wrong texture ID
        {
          webgpu::cmds::DissociateMailbox cmd;
          cmd.Init(reservation.id + 1, reservation.generation);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }

        // Error case: wrong texture generation
        {
          webgpu::cmds::DissociateMailbox cmd;
          cmd.Init(reservation.id, reservation.generation + 1);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }

        // Success case
        {
          webgpu::cmds::DissociateMailbox cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kNoError, ExecuteCmd(decoder, cmd));
        }

        // Error case: dissociate an already dissociated mailbox
        {
          webgpu::cmds::DissociateMailbox cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }
      },
      GetDecoder(), reservation, std::move(shared_image)));

  GetGpuServiceHolder()
      ->gpu_main_thread_task_runner()
      ->RunsTasksInCurrentSequence();
}

// Tests using Associate/DissociateMailbox to share an image with Dawn.
// For simplicity of the test the image is shared between a Dawn device and
// itself: we render to it using the Dawn device, then re-associate it to a
// Dawn texture and read back the values that were written.
TEST_P(WebGPUMailboxTextureTest, WriteToMailboxThenReadFromIt) {
  SKIP_TEST_IF(GetParam().format == viz::SinglePlaneFormat::kRGBA_F16);

  // Create the shared image
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Part 1: Write to the texture using Dawn
  InitializeTextureColor(device_, shared_image, {0.0, 0.0, 1.0, 1.0});

  // Part 2: Read back the texture using Dawn
  {
    // Register the shared image as a Dawn texture in the wire.
    wgpu::TextureDescriptor desc = {
        .usage = wgpu::TextureUsage::CopySrc,
    };
    std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
        shared_image->BeginWebGPUTextureAccess(webgpu(), gpu::SyncToken(),
                                               device_, desc, /*usage=*/0,
                                               webgpu::WEBGPU_MAILBOX_NONE);

    // Copy the texture in a mappable buffer.
    wgpu::BufferDescriptor buffer_desc;
    buffer_desc.size = 4;
    buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
    wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

    wgpu::TexelCopyTextureInfo copy_src = {};
    copy_src.texture = webgpu_scoped_access->texture();
    copy_src.mipLevel = 0;
    copy_src.origin = {0, 0, 0};

    wgpu::TexelCopyBufferInfo copy_dst = {};
    copy_dst.buffer = readback_buffer;
    copy_dst.layout.offset = 0;
    copy_dst.layout.bytesPerRow = 256;

    wgpu::Extent3D copy_size = {1, 1, 1};

    wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
    encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
    wgpu::CommandBuffer commands = encoder.Finish();

    wgpu::Queue queue = device_.GetQueue();
    queue.Submit(1, &commands);

    WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

    // Map the buffer and assert the pixel is the correct value.
    readback_buffer.MapAsync(wgpu::MapMode::Read, 0, 4,
                             wgpu::CallbackMode::AllowSpontaneous,
                             ToMockBufferMapCallback);
    EXPECT_CALL(*mock_buffer_map_callback,
                Call(wgpu::MapAsyncStatus::Success, testing::_))
        .Times(1);

    WaitForCompletion(device_);

    const void* data = readback_buffer.GetConstMappedRange();
    if (GetParam().format == viz::SinglePlaneFormat::kRGBA_8888) {
      EXPECT_EQ(0xFFFF0000u, *static_cast<const uint32_t*>(data));
    } else if (GetParam().format == viz::SinglePlaneFormat::kBGRA_8888) {
      EXPECT_EQ(0xFF0000FFu, *static_cast<const uint32_t*>(data));
    } else {
      NOTREACHED();
    }
  }
}

// Test that passing write usages when associating a mailbox fails if
// the SharedImage associated with the mailbox doesn't have WEBGPU_WRITE access.
TEST_P(WebGPUMailboxTextureTest,
       PassWriteUsagesWhenAssociatingReadOnlyMailbox) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);

  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation, encoder.Finish());

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
  WaitForCompletion(device_);
}

// Test that passing internal write usages when associating a mailbox fails if
// the SharedImage associated with the mailbox doesn't have WEBGPU_WRITE access.
TEST_P(WebGPUMailboxTextureTest,
       PassInternalWriteUsagesWhenAssociatingReadOnlyMailbox) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);
  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc,
          WGPUTextureUsage_CopyDst, webgpu::WEBGPU_MAILBOX_NONE);

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);

  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation, encoder.Finish());

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
  WaitForCompletion(device_);
}

// Test that passing WEBGPU_MAILBOX_DISCARD when associating a mailbox fails if
// the SharedImage associated with the mailbox doesn't have WEBGPU_WRITE access.
TEST_P(WebGPUMailboxTextureTest, PassDiscardWhenAssociatingReadOnlyMailbox) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_DISCARD);

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);

  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation, encoder.Finish());

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
  WaitForCompletion(device_);
}

// Test that passing WEBGPU_MAILBOX_DISCARD when associating a mailbox fails if
// the client doesn't pass a usage supporting lazy clearing.
TEST_P(WebGPUMailboxTextureTest,
       PassDiscardWhenAssociatingMailboxWithoutUsageSupportingClearing) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_DISCARD);

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);

  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation, encoder.Finish());

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
  WaitForCompletion(device_);
}

// Test that an uninitialized writable shared image is lazily cleared by Dawn
// when it is accessed with an internal write usage supporting lazy clearing.
TEST_P(WebGPUMailboxTextureTest,
       ReadWritableUninitializedSharedImageWhenAccessedWithInternalWriteUsage) {
  // Create the shared image. Note that it is uncleared by default.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc,
          WGPUTextureUsage_RenderAttachment, webgpu::WEBGPU_MAILBOX_NONE);

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
  wgpu::CommandBuffer commands = encoder.Finish();

  wgpu::Queue queue = device_.GetQueue();
  queue.Submit(1, &commands);

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  // Map the buffer and assert the pixel is the correct value.
  readback_buffer.MapAsync(wgpu::MapMode::Read, 0, buffer_desc.size,
                           wgpu::CallbackMode::AllowSpontaneous,
                           ToMockBufferMapCallback);
  EXPECT_CALL(*mock_buffer_map_callback,
              Call(wgpu::MapAsyncStatus::Success, testing::_))
      .Times(1);

  WaitForCompletion(device_);

  const uint8_t* data = static_cast<const uint8_t*>(
      readback_buffer.GetConstMappedRange(0, buffer_desc.size));
  // Contents should be black because the texture was lazily cleared.
  for (uint32_t i = 0; i < buffer_desc.size; ++i) {
    EXPECT_EQ(data[i], uint8_t(0));
  }

  // Associate the SharedImage with a new Dawn texture in a read-only access.
  // The SharedImage should have been cleared at the end of the previous access,
  // and hence this read access should succeed.
  EXPECT_EQ(webgpu_scoped_access, nullptr);

  webgpu_scoped_access = shared_image->BeginWebGPUTextureAccess(
      webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
      webgpu::WEBGPU_MAILBOX_NONE);

  copy_src.texture = webgpu_scoped_access->texture();
  wgpu::Buffer readback_buffer2 = device_.CreateBuffer(&buffer_desc);
  copy_dst.buffer = readback_buffer2;
  wgpu::CommandEncoder encoder2 = device_.CreateCommandEncoder();
  encoder2.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
  commands = encoder2.Finish();

  queue.Submit(1, &commands);

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  // Map the buffer.
  readback_buffer2.MapAsync(wgpu::MapMode::Read, 0, buffer_desc.size,
                            wgpu::CallbackMode::AllowSpontaneous,
                            ToMockBufferMapCallback);
  EXPECT_CALL(*mock_buffer_map_callback,
              Call(wgpu::MapAsyncStatus::Success, testing::_))
      .Times(1);

  WaitForCompletion(device_);
}

// Test that an uninitialized writable shared image is lazily cleared by Dawn
// when it is read if a usage supporting lazy clearing is passed.
TEST_P(WebGPUMailboxTextureTest,
       ReadWritableUninitializedSharedImageWithUsageSupportingLazyClearing) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Set the texture contents to non-zero so we can test a lazy clear occurs.
  InitializeTextureColor(device_, shared_image, {1.0, 0, 0, 1.0});

  // Register the shared image as a Dawn texture in the wire.
  wgpu::TextureDescriptor desc = {
      .usage =
          wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment,
  };
  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(webgpu(), gpu::SyncToken(),
                                             device_, desc, /*usage=*/0,
                                             webgpu::WEBGPU_MAILBOX_DISCARD);

  // Read the texture using a render pass. Load+Store the contents.
  // Uninitialized contents should not be loaded.
  wgpu::RenderPassColorAttachment color_desc = {};
  color_desc.view = webgpu_scoped_access->texture().CreateView();
  color_desc.loadOp = wgpu::LoadOp::Load;
  color_desc.storeOp = wgpu::StoreOp::Store;

  wgpu::RenderPassDescriptor render_pass_desc = {};
  render_pass_desc.colorAttachmentCount = 1;
  render_pass_desc.colorAttachments = &color_desc;

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&render_pass_desc);
  pass.End();

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
  wgpu::CommandBuffer commands = encoder.Finish();

  wgpu::Queue queue = device_.GetQueue();
  queue.Submit(1, &commands);

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  // Map the buffer and assert the pixel is the correct value.
  readback_buffer.MapAsync(wgpu::MapMode::Read, 0, buffer_desc.size,
                           wgpu::CallbackMode::AllowSpontaneous,
                           ToMockBufferMapCallback);
  EXPECT_CALL(*mock_buffer_map_callback,
              Call(wgpu::MapAsyncStatus::Success, testing::_))
      .Times(1);

  WaitForCompletion(device_);

  const uint8_t* data = static_cast<const uint8_t*>(
      readback_buffer.GetConstMappedRange(0, buffer_desc.size));
  // Contents should be black because the texture was lazily cleared.
  for (uint32_t i = 0; i < buffer_desc.size; ++i) {
    EXPECT_EQ(data[i], uint8_t(0));
  }
}

// Test that an uninitialized writable shared image is lazily cleared by Dawn
// when it is read if an internal usage supporting lazy clearing is passed.
TEST_P(
    WebGPUMailboxTextureTest,
    ReadWritableUninitializedSharedImageWithInternalUsageSupportingLazyClearing) {
  // Create the shared image.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Set the texture contents to non-zero so we can test a lazy clear occurs.
  InitializeTextureColor(device_, shared_image, {1.0, 0, 0, 1.0});

  // Register the shared image as a Dawn texture in the wire.
  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::CopySrc,
  };
  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), gpu::SyncToken(), device_, desc,
          WGPUTextureUsage_RenderAttachment, webgpu::WEBGPU_MAILBOX_DISCARD);

  // Copy the texture in a mappable buffer.
  wgpu::BufferDescriptor buffer_desc;
  buffer_desc.size = BytesPerTexel(GetParam().format);
  buffer_desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&buffer_desc);

  wgpu::TexelCopyTextureInfo copy_src = {};
  copy_src.texture = webgpu_scoped_access->texture();
  copy_src.mipLevel = 0;
  copy_src.origin = {0, 0, 0};

  wgpu::TexelCopyBufferInfo copy_dst = {};
  copy_dst.buffer = readback_buffer;
  copy_dst.layout.offset = 0;
  copy_dst.layout.bytesPerRow = 256;

  wgpu::Extent3D copy_size = {1, 1, 1};

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToBuffer(&copy_src, &copy_dst, &copy_size);
  wgpu::CommandBuffer commands = encoder.Finish();

  wgpu::Queue queue = device_.GetQueue();
  queue.Submit(1, &commands);

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  // Map the buffer and assert the pixel is the correct value.
  readback_buffer.MapAsync(wgpu::MapMode::Read, 0, buffer_desc.size,
                           wgpu::CallbackMode::AllowSpontaneous,
                           ToMockBufferMapCallback);
  EXPECT_CALL(*mock_buffer_map_callback,
              Call(wgpu::MapAsyncStatus::Success, testing::_))
      .Times(1);

  WaitForCompletion(device_);

  const uint8_t* data = static_cast<const uint8_t*>(
      readback_buffer.GetConstMappedRange(0, buffer_desc.size));
  // Contents should be black because the texture was lazily cleared.
  for (uint32_t i = 0; i < buffer_desc.size; ++i) {
    EXPECT_EQ(data[i], uint8_t(0));
  }
}

// Tests that using a shared image aftr it is dissociated produces an error.
TEST_P(WebGPUMailboxTextureTest, ErrorWhenUsingTextureAfterDissociate) {
  // Create the shared image.
  // NOTE: It's necessary to add WEBGPU_WRITE access as the created SharedImage
  // will be uncleared and hence require lazy clearing on access.
  // WebGPUDecoderImpl might also need to fall back to using Skia to read and
  // write, making it necessary to add those usages as well.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // NOTE: Accessing an uncleared Dawn texture requires passing a usage that
  // supports lazy clearing (otherwise AssociateMailbox() will generate an
  // error, which is not the error case that this test is looking to test).
  wgpu::TextureDescriptor desc = {.usage =
                                      wgpu::TextureUsage::CopySrc |
                                      wgpu::TextureUsage::RenderAttachment};

  // Associate and immediately dissociate the image.
  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);
  wgpu::Texture texture = webgpu_scoped_access->texture();
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  wgpu::TextureDescriptor dst_desc = {};
  dst_desc.size = {1, 1};
  dst_desc.usage = wgpu::TextureUsage::CopyDst;
  DCHECK(GetParam().format == viz::SinglePlaneFormat::kRGBA_8888 ||
         GetParam().format == viz::SinglePlaneFormat::kBGRA_8888 ||
         GetParam().format == viz::SinglePlaneFormat::kRGBA_F16);
  dst_desc.format = VizToWGPUFormat(GetParam().format);

  wgpu::TexelCopyTextureInfo src_image = {};
  src_image.texture = texture;

  wgpu::TexelCopyTextureInfo dst_image = {};
  dst_image.texture = device_.CreateTexture(&dst_desc);

  wgpu::Extent3D extent = {1, 1};

  // Try using the texture in a copy command; it should produce a validation
  // error.
  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyTextureToTexture(&src_image, &dst_image, &extent);
  wgpu::CommandBuffer commandBuffer = encoder.Finish();

  // Wait so it's clear the validation error after this when we call Submit.
  WaitForCompletion(device_);

  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation,
                      device_.GetQueue().Submit(1, &commandBuffer));
}

// This is a regression test for an issue when using multiple shared images
// where a `ScopedAccess` was destroyed after it's `SharedImageRepresentation`.
// The code was similar to the following.
//
//   struct Pair {
//       unique_ptr<Representation> representation;
//       unique_ptr<Access> access;
//   };
//
//   base::flat_map<Key, Pair> map;
//   map.erase(some_iterator);
//
// In the Pair destructor C++ guarantees that `access` is destroyed before
// `representation` but `erase` can move one element over another, causing
// the move-assignment operator to be called. In this case the defaulted
// move-assignment would first move `representation` then `access`. Causing
// incorrect member destruction order for the move-to object.
TEST_P(WebGPUMailboxTextureTest, UseA_UseB_DestroyA_DestroyB) {
  // Create a the shared images.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image_a =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);
  scoped_refptr<gpu::ClientSharedImage> shared_image_b =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Associate both mailboxes
  wgpu::TextureDescriptor desc = {.usage =
                                      wgpu::TextureUsage::RenderAttachment};

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access_a =
      shared_image_a->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);
  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access_b =
      shared_image_b->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  // Dissociate both mailboxes in the same order.
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access_a));
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access_b));

  // Send all the previous commands to the WebGPU decoder.
  webgpu()->FlushCommands();
}

// Regression test for a bug where the (id, generation) for associated shared
// images was stored globally instead of per-device. This meant that of two
// devices tried to create shared images with the same (id, generation) (which
// is possible because they can be on different Dawn wires) they would conflict.
TEST_P(WebGPUMailboxTextureTest, AssociateOnTwoDevicesAtTheSameTime) {
  // Create a the shared images.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image_a =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  scoped_refptr<gpu::ClientSharedImage> shared_image_b =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Two WebGPU devices to associate the shared images to.
  wgpu::Device device_a = GetNewDevice();
  wgpu::Device device_b = GetNewDevice();

  // Associate both mailboxes
  wgpu::TextureDescriptor desc = {.usage =
                                      wgpu::TextureUsage::RenderAttachment};

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access_a =
      shared_image_a->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_a, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access_b =
      shared_image_b->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_b, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  // Dissociate both mailboxes in the same order.
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access_a));
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access_b));

  // Send all the previous commands to the WebGPU decoder.
  webgpu()->FlushCommands();
}

// Test that passing a descriptor to ReserveTexture produces a client-side
// WGPUTexture that correctly reflects said descriptor.
TEST_P(WebGPUMailboxTextureTest, ReflectionOfDescriptor) {
  // Associate mailboxes so that releasing the reserved wgpu::Textures does not
  // fail. Note that these texture parameters do not match. It doesn't matter
  // since the textures are not used in this test except for frontend
  // reflection.
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image1 =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);
  scoped_refptr<gpu::ClientSharedImage> shared_image2 =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::Read),
                              "TestLabel"},
                             kNullSurfaceHandle);

  // Check that reserving a texture with a full descriptor give the same data
  // back through reflection.
  wgpu::TextureDescriptor desc1 = {};
  desc1.size = {1, 2, 3};
  desc1.format = wgpu::TextureFormat::R32Float;
  desc1.usage = wgpu::TextureUsage::CopyDst;
  desc1.dimension = wgpu::TextureDimension::e2D;
  desc1.sampleCount = 1;
  desc1.mipLevelCount = 1;

  // Test with a different descriptor to check data is not hardcoded. Not that
  // this is actually not a valid descriptor (diimension == 1D with height !=
  // 1), but that it should still be reflected exactly.
  wgpu::TextureDescriptor desc2 = {};
  desc2.size = {4, 5, 6};
  desc2.format = wgpu::TextureFormat::RGBA8Unorm;
  desc2.usage = wgpu::TextureUsage::CopySrc;
  desc2.dimension = wgpu::TextureDimension::e1D;
  desc2.sampleCount = 4;
  desc2.mipLevelCount = 3;

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access1 =
      shared_image1->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc1, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);
  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access2 =
      shared_image2->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc2, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  wgpu::Texture texture1 = webgpu_scoped_access1->texture();
  wgpu::Texture texture2 = webgpu_scoped_access2->texture();

  ASSERT_EQ(desc1.size.width, texture1.GetWidth());
  ASSERT_EQ(desc1.size.height, texture1.GetHeight());
  ASSERT_EQ(desc1.size.depthOrArrayLayers, texture1.GetDepthOrArrayLayers());
  ASSERT_EQ(desc1.format, texture1.GetFormat());
  ASSERT_EQ(desc1.usage, texture1.GetUsage());
  ASSERT_EQ(desc1.dimension, texture1.GetDimension());
  ASSERT_EQ(desc1.sampleCount, texture1.GetSampleCount());
  ASSERT_EQ(desc1.mipLevelCount, texture1.GetMipLevelCount());

  ASSERT_EQ(desc2.size.width, texture2.GetWidth());
  ASSERT_EQ(desc2.size.height, texture2.GetHeight());
  ASSERT_EQ(desc2.size.depthOrArrayLayers, texture2.GetDepthOrArrayLayers());
  ASSERT_EQ(desc2.format, texture2.GetFormat());
  ASSERT_EQ(desc2.usage, texture2.GetUsage());
  ASSERT_EQ(desc2.dimension, texture2.GetDimension());
  ASSERT_EQ(desc2.sampleCount, texture2.GetSampleCount());
  ASSERT_EQ(desc2.mipLevelCount, texture2.GetMipLevelCount());

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access1));
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access2));
}

// Test that passing a texture with invalid view formats to AssociateMailbox
// does not cause WebGPU validation errors on a later call to DissociateMailbox.
TEST_P(WebGPUMailboxTextureTest, AssociateInvalidViewFormats) {
  wgpu::TextureDescriptor desc = {};
  desc.size = {1, 1, 1};
  desc.format = VizToWGPUFormat(GetParam().format);
  desc.usage = wgpu::TextureUsage::RenderAttachment;
  desc.dimension = wgpu::TextureDimension::e2D;
  desc.sampleCount = 1;
  desc.mipLevelCount = 1;

  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);
  wgpu::TextureFormat view_formats = wgpu::TextureFormat::R8Unorm;
  desc.viewFormats = &view_formats;
  desc.viewFormatCount = 1;

  // AssociateMailbox may cause validation errors, given the invalid
  // viewFormats, so wrap it in an error scope.
  device_.PushErrorScope(wgpu::ErrorFilter::Validation);

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), sii->GenVerifiedSyncToken(), device_, desc, /*usage=*/0,
          webgpu::WEBGPU_MAILBOX_NONE);

  device_.PopErrorScope(
      wgpu::CallbackMode::AllowSpontaneous,
      [](wgpu::PopErrorScopeStatus, wgpu::ErrorType, wgpu::StringView) {});

  // DissociateMailbox should NOT cause validation errors.
  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));
}

// Test that if some other GL context is current when
// Associate/DissociateMailbox occurs, the operations do not fail. Some WebGPU
// shared image backings rely on GL and need to be responsible for making the
// context current.
TEST_P(WebGPUMailboxTextureTest, AssociateDissociateMailboxWhenNotCurrent) {
  // Create the shared image
  SharedImageInterface* sii = GetSharedImageInterface();
  scoped_refptr<gpu::ClientSharedImage> shared_image =
      sii->CreateSharedImage({GetParam().format,
                              {1, 1},
                              gfx::ColorSpace::CreateSRGB(),
                              GetSharedImageUsage(AccessType::ReadWrite),
                              "TestLabel"},
                             kNullSurfaceHandle);

  scoped_refptr<gl::GLContext> gl_context1;
  scoped_refptr<gl::GLContext> gl_context2;
  scoped_refptr<gl::GLSurface> gl_surface1;
  scoped_refptr<gl::GLSurface> gl_surface2;

  // Create and make a new gl context current.
  // Contexts must be created on the GPU thread, so this creates it on the GPU
  // thread and sets a scoped_refptr on the main thread.
  auto CreateAndMakeGLContextCurrent =
      [&](scoped_refptr<gl::GLContext>* gl_context_out,
          scoped_refptr<gl::GLSurface>* gl_surface_out) {
        GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
            [](scoped_refptr<gl::GLContext>* gl_context_out,
               scoped_refptr<gl::GLSurface>* gl_surface_out) {
              auto gl_surface = gl::init::CreateOffscreenGLSurface(
                  gl::GetDefaultDisplay(), gfx::Size(4, 4));
              auto gl_context = gl::init::CreateGLContext(
                  nullptr, gl_surface.get(), gl::GLContextAttribs());

              EXPECT_TRUE(gl_context->MakeCurrent(gl_surface.get()))
                  << "Failed to make GL context current";

              *gl_context_out = std::move(gl_context);
              *gl_surface_out = std::move(gl_surface);
            },
            gl_context_out, gl_surface_out));
        GetGpuServiceHolder()
            ->gpu_main_thread_task_runner()
            ->RunsTasksInCurrentSequence();
      };

  // Create a GL context and make it current.
  CreateAndMakeGLContextCurrent(&gl_context1, &gl_surface1);

  wgpu::TextureDescriptor desc = {
      .usage = wgpu::TextureUsage::RenderAttachment,
  };

  std::unique_ptr<WebGPUTextureScopedAccess> webgpu_scoped_access =
      shared_image->BeginWebGPUTextureAccess(
          webgpu(), GetSharedImageInterface()->GenVerifiedSyncToken(), device_,
          desc, /*usage=*/0, webgpu::WEBGPU_MAILBOX_NONE);

  // Clear the texture using a render pass.
  wgpu::RenderPassColorAttachment color_desc = {};
  color_desc.view = webgpu_scoped_access->texture().CreateView();
  color_desc.loadOp = wgpu::LoadOp::Clear;
  color_desc.storeOp = wgpu::StoreOp::Store;
  color_desc.clearValue = {0.0, 1.0, 0.0, 1.0};

  wgpu::RenderPassDescriptor render_pass_desc = {};
  render_pass_desc.colorAttachmentCount = 1;
  render_pass_desc.colorAttachments = &color_desc;

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&render_pass_desc);
  pass.End();
  wgpu::CommandBuffer commands = encoder.Finish();

  wgpu::Queue queue = device_.GetQueue();
  queue.Submit(1, &commands);

  WaitForCompletion(device_);

  // Create another context and make it current.
  // This is a distinct context to catch errors where Associate/Dissociate
  // always use the current context, and in the test, these just so happen to be
  // identical.
  CreateAndMakeGLContextCurrent(&gl_context2, &gl_surface2);

  WebGPUTextureScopedAccess::EndAccess(std::move(webgpu_scoped_access));

  WaitForCompletion(device_);

  // Delete the GL contexts on the GPU thread.
  GetGpuServiceHolder()->ScheduleGpuMainTask(
      base::BindOnce([](scoped_refptr<gl::GLContext> gl_context1,
                        scoped_refptr<gl::GLContext> gl_context2,
                        scoped_refptr<gl::GLSurface> gl_surface1,
                        scoped_refptr<gl::GLSurface> gl_surface2) {},
                     std::move(gl_context1), std::move(gl_context2),
                     std::move(gl_surface1), std::move(gl_surface2)));
}

INSTANTIATE_TEST_SUITE_P(
    ,
    WebGPUMailboxTextureTest,
    ::testing::ValuesIn(WebGPUMailboxTextureTest::TestParams()),
    ::testing::PrintToStringParamName());

class WebGPUMailboxBufferTest : public WebGPUMailboxTestBase {
 public:
  void SetUp() override {
    SKIP_TEST_IF(!WebGPUSupported());
    SKIP_TEST_IF(!WebGPUSharedImageSupported());
    WebGPUTest::SetUp();

    WebGPUTest::Options options = {};
    options.enable_unsafe_webgpu = true;
    Initialize(options);

    wgpu::AdapterInfo info;
    adapter_.GetInfo(&info);
    // Buffer-backed SharedImages are only supported on D3D12 right now.
    SKIP_TEST_IF(info.backendType != wgpu::BackendType::D3D12);

    device_ = GetNewDevice(kRequiredFeatures);

    mock_buffer_map_callback =
        std::make_unique<testing::StrictMock<MockBufferMapCallback>>();

    SharedImageInterface* sii = GetSharedImageInterface();
    shared_image_ = sii->CreateSharedImage(
        {viz::SharedImageFormat(),
         {kBufferSize, 1},
         gfx::ColorSpace(),
         kTopLeft_GrSurfaceOrigin,
         kUnknown_SkAlphaType,
         gpu::SHARED_IMAGE_USAGE_WEBGPU_READ |
             gpu::SHARED_IMAGE_USAGE_WEBGPU_WRITE |
             gpu::SHARED_IMAGE_USAGE_WEBGPU_SHARED_BUFFER,
         "TestLabel"},
        kNullSurfaceHandle);
  }

  void TearDown() override {
    mock_buffer_map_callback = nullptr;
    // Wait for all operations to catch any validation or device lost errors.
    PollUntilIdle();
    device_ = nullptr;
    WebGPUTest::TearDown();
  }

  struct AssociateMailboxForBufferCmdStorage {
    webgpu::cmds::AssociateMailboxForBufferImmediate cmd;

    // Immediate data is copied into the space immediately following `cmd`.
    // Allocate space to hold 1 mailbox.
    GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
  };

 protected:
  std::vector<wgpu::FeatureName> kRequiredFeatures = {
      wgpu::FeatureName::SharedBufferMemoryD3D12Resource};
  const int kBufferSize = 4;
  const uint32_t kBufferData = 0x12345678;
  wgpu::Device device_;
  scoped_refptr<gpu::ClientSharedImage> shared_image_;
};

// Test that AssociateMailboxForBuffer works as expected.
TEST_F(WebGPUMailboxBufferTest, AssociateMailboxForBufferCmd) {
  webgpu::ReservedBuffer reservation = webgpu()->ReserveBuffer(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedBuffer reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        const gpu::Mailbox& mailbox = shared_image->mailbox();

        // Error case: device client id doesn't exist.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId + 1, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: device generation is invalid.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration + 1,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: buffer ID invalid for the wire server.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id + 1, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Error case: packed data empty.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(error::kOutOfBounds,
                    ExecuteImmediateCmd(decoder, cmd.cmd, 0u));
        }

        // Control case: test a successful call to AssociateMailboxForBuffer.
        // The control case is not put first because it modifies the internal
        // state of the Dawn wire server and would make calls with the same
        // buffer ID and generation invalid.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(decoder, cmd.cmd,
                                                         sizeof(mailbox.name)));
        }

        // Error case: associated to an already associated buffer.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(
              error::kInvalidArguments,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(mailbox.name)));
        }

        // Dissociate the buffer from the control case to remove its reference.
        {
          webgpu::cmds::DissociateMailboxForBuffer cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kNoError, ExecuteCmd(decoder, cmd));
        }
      },
      GetDecoder(), reservation, std::move(shared_image_)));

  GetGpuServiceHolder()
      ->gpu_main_thread_task_runner()
      ->RunsTasksInCurrentSequence();
}

// Test that AssociateMailboxForBuffer with a bad mailbox produces an error
// buffer.
TEST_F(WebGPUMailboxBufferTest,
       AssociateMailboxForBufferCmdBadMailboxMakesErrorBuffer) {
  webgpu::ReservedBuffer reservation = webgpu()->ReserveBuffer(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedBuffer reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        // Calling AssociateMailboxForBuffer with an invalid Mailbox should
        // return an error buffer.
        {
          gpu::Mailbox bad_mailbox;
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_CopyDst,
                       reinterpret_cast<const GLuint*>(&bad_mailbox.name));
          EXPECT_EQ(
              error::kNoError,
              ExecuteImmediateCmd(decoder, cmd.cmd, sizeof(bad_mailbox.name)));
        }
      },
      GetDecoder(), reservation, std::move(shared_image_)));

  wgpu::Buffer buffer = wgpu::Buffer::Acquire(reservation.buffer);
  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.ClearBuffer(buffer, 0, kBufferSize);
  // Expect an error when finishing encoding because the buffer is an error.
  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation,
                      wgpu::CommandBuffer commands = encoder.Finish());
}

// Test that DissociateMailboxForBuffer works as expected.
TEST_F(WebGPUMailboxBufferTest, DissociateMailboxForBufferCmd) {
  webgpu::ReservedBuffer reservation = webgpu()->ReserveBuffer(device_.Get());

  GetGpuServiceHolder()->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder, webgpu::ReservedBuffer reservation,
         scoped_refptr<gpu::ClientSharedImage> shared_image) {
        const gpu::Mailbox& mailbox = shared_image->mailbox();

        // Associate a mailbox so we can later dissociate it.
        {
          AssociateMailboxForBufferCmdStorage cmd;
          cmd.cmd.Init(reservation.deviceId, reservation.deviceGeneration,
                       reservation.id, reservation.generation,
                       WGPUBufferUsage_Storage,
                       reinterpret_cast<const GLuint*>(&mailbox.name));
          EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(decoder, cmd.cmd,
                                                         sizeof(mailbox.name)));
        }

        // Error case: wrong buffer ID
        {
          webgpu::cmds::DissociateMailboxForBuffer cmd;
          cmd.Init(reservation.id + 1, reservation.generation);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }

        // Error case: wrong buffer generation
        {
          webgpu::cmds::DissociateMailboxForBuffer cmd;
          cmd.Init(reservation.id, reservation.generation + 1);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }

        // Success case
        {
          webgpu::cmds::DissociateMailboxForBuffer cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kNoError, ExecuteCmd(decoder, cmd));
        }

        // Error case: dissociate an already dissociated mailbox
        {
          webgpu::cmds::DissociateMailboxForBuffer cmd;
          cmd.Init(reservation.id, reservation.generation);
          EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(decoder, cmd));
        }
      },
      GetDecoder(), reservation, std::move(shared_image_)));

  GetGpuServiceHolder()
      ->gpu_main_thread_task_runner()
      ->RunsTasksInCurrentSequence();
}

// Tests using Associate/DissociateMailbox to share a buffer with Dawn.
TEST_F(WebGPUMailboxBufferTest, WriteToMailboxThenReadFromIt) {
  webgpu::ReservedBuffer reservation = webgpu()->ReserveBuffer(device_.Get());

  SharedImageInterface* sii = GetSharedImageInterface();
  SyncToken mailbox_produced_token = sii->GenVerifiedSyncToken();
  webgpu()->WaitSyncTokenCHROMIUM(mailbox_produced_token.GetConstData());

  webgpu()->AssociateMailboxForBuffer(
      reservation.deviceId, reservation.deviceGeneration, reservation.id,
      reservation.generation,
      WGPUBufferUsage_Storage | WGPUBufferUsage_CopySrc |
          WGPUBufferUsage_CopyDst,
      shared_image_->mailbox());
  wgpu::Buffer mailbox_buffer = wgpu::Buffer::Acquire(reservation.buffer);

  // Create an buffer and write data to it.
  wgpu::BufferDescriptor data_buffer_desc;
  data_buffer_desc.size = kBufferSize;
  data_buffer_desc.usage =
      wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
  wgpu::Buffer data_buffer = device_.CreateBuffer(&data_buffer_desc);

  wgpu::Queue queue = device_.GetQueue();
  queue.WriteBuffer(data_buffer, 0, &kBufferData, kBufferSize);

  // Create a readback buffer to store result data.
  wgpu::BufferDescriptor readback_buffer_desc;
  readback_buffer_desc.size = kBufferSize;
  readback_buffer_desc.usage =
      wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
  wgpu::Buffer readback_buffer = device_.CreateBuffer(&readback_buffer_desc);

  // Copy data from the upload buffer to the mailbox buffer, then from the
  // mailbox buffer to the readback buffer.
  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.CopyBufferToBuffer(data_buffer, 0, mailbox_buffer, 0, kBufferSize);
  encoder.CopyBufferToBuffer(mailbox_buffer, 0, readback_buffer, 0,
                             kBufferSize);
  wgpu::CommandBuffer commands = encoder.Finish();
  queue = device_.GetQueue();
  queue.Submit(1, &commands);

  webgpu()->DissociateMailboxForBuffer(reservation.id, reservation.generation);

  // Map the readback buffer and check that it contains the correct value.
  readback_buffer.MapAsync(wgpu::MapMode::Read, 0, 4,
                           wgpu::CallbackMode::AllowSpontaneous,
                           ToMockBufferMapCallback);
  EXPECT_CALL(*mock_buffer_map_callback,
              Call(wgpu::MapAsyncStatus::Success, testing::_))
      .Times(1);

  WaitForCompletion(device_);
  const void* readback_data = readback_buffer.GetConstMappedRange();
  EXPECT_EQ(kBufferData, *static_cast<const uint32_t*>(readback_data));
}

// Tests that using a mailbox buffer after it is dissociated produces an
// error.
TEST_F(WebGPUMailboxBufferTest, ErrorWhenUsingBufferAfterDissociate) {
  webgpu::ReservedBuffer reservation = webgpu()->ReserveBuffer(device_.Get());

  SharedImageInterface* sii = GetSharedImageInterface();
  SyncToken mailbox_produced_token = sii->GenVerifiedSyncToken();
  webgpu()->WaitSyncTokenCHROMIUM(mailbox_produced_token.GetConstData());

  wgpu::Buffer mailbox_buffer = wgpu::Buffer::Acquire(reservation.buffer);

  webgpu()->AssociateMailboxForBuffer(
      reservation.deviceId, reservation.deviceGeneration, reservation.id,
      reservation.generation,
      WGPUBufferUsage_Storage | WGPUBufferUsage_CopySrc |
          WGPUBufferUsage_CopyDst,
      shared_image_->mailbox());
  webgpu()->DissociateMailboxForBuffer(reservation.id, reservation.generation);

  wgpu::CommandEncoder encoder = device_.CreateCommandEncoder();
  encoder.ClearBuffer(mailbox_buffer, 0, kBufferSize);
  wgpu::CommandBuffer commands = encoder.Finish();

  // Wait so it's clear the validation error after this when we call Submit.
  WaitForCompletion(device_);
  EXPECT_WEBGPU_ERROR(device_, wgpu::ErrorType::Validation,
                      device_.GetQueue().Submit(1, &commands));

  WaitForCompletion(device_);
}

}  // namespace gpu
