// 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.

#include "gpu/command_buffer/service/webgpu_decoder_impl.h"

#include <algorithm>
#include <array>
#include <memory>
#include <optional>
#include <string_view>
#include <vector>

#include "base/auto_reset.h"
#include "base/bits.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/notimplemented.h"
#include "base/notreached.h"
#include "base/numerics/checked_math.h"
#include "base/power_monitor/power_monitor.h"
#include "base/strings/string_split.h"
#include "base/task/bind_post_task.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/webgpu_cmd_format.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/dawn_caching_interface.h"
#include "gpu/command_buffer/service/dawn_instance.h"
#include "gpu/command_buffer/service/dawn_platform.h"
#include "gpu/command_buffer/service/dawn_service_memory_transfer_service.h"
#include "gpu/command_buffer/service/dawn_service_serializer.h"
#include "gpu/command_buffer/service/dawn_wire_server.h"
#include "gpu/command_buffer/service/decoder_client.h"
#include "gpu/command_buffer/service/graphite_utils.h"
#include "gpu/command_buffer/service/isolation_key_provider.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image/shared_image_factory.h"
#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
#include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
#include "gpu/command_buffer/service/skia_utils.h"
#include "gpu/command_buffer/service/webgpu_decoder.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/config/webgpu_blocklist_impl.h"
#include "gpu/webgpu/callback.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/dawn/include/dawn/native/DawnNative.h"
#include "third_party/dawn/include/dawn/native/OpenGLBackend.h"
#include "third_party/dawn/include/dawn/platform/DawnPlatform.h"
#include "third_party/dawn/include/dawn/webgpu_cpp.h"
#include "third_party/dawn/include/dawn/webgpu_cpp_print.h"
#include "third_party/dawn/include/dawn/wire/WireServer.h"
#include "third_party/perfetto/include/perfetto/tracing/track_event_args.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/gpu/ganesh/GrBackendSemaphore.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
#include "third_party/skia/include/gpu/graphite/Context.h"
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_surface_egl.h"

#if BUILDFLAG(IS_WIN)
#include <dawn/native/D3D11Backend.h>
#include <dawn/native/D3D12Backend.h>
#include "ui/gl/gl_angle_util_win.h"
#endif

namespace gpu {
namespace webgpu {

namespace {

constexpr wgpu::TextureUsage kAllowedWritableMailboxTextureUsages =
    wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment |
    wgpu::TextureUsage::StorageBinding;

constexpr wgpu::TextureUsage kWritableUsagesSupportingLazyClear =
    wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment;

constexpr wgpu::TextureUsage kAllowedReadableMailboxTextureUsages =
    wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;

constexpr wgpu::TextureUsage kAllowedMailboxTextureUsages =
    kAllowedWritableMailboxTextureUsages | kAllowedReadableMailboxTextureUsages;

constexpr wgpu::BufferUsage kAllowedMailboxBufferUsages =
    wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst |
    wgpu::BufferUsage::Storage;

template <typename T1, typename T2>
void ChainStruct(T1& head, T2* struct_to_chain) {
  DCHECK(struct_to_chain->nextInChain == nullptr);
  struct_to_chain->nextInChain = head.nextInChain;
  head.nextInChain = struct_to_chain;
}

template <size_t N>
WGPUStringView MakeStringView(const char (&s)[N]) {
  return {s, N};
}
WGPUStringView MakeStringView(const char* s) {
  return {s, std::strlen(s)};
}
WGPUStringView MakeStringView() {
  return {nullptr, 0};
}

// This variable is set to DawnWireServer's parent decoder during execution of
// HandleCommands. It is cleared to nullptr after. This enables some of the
// overridden procs to be overridden with a WebGPUDecoderImpl member function.
// The proc will be set to a plain-old C function pointer, which loads the
// WebGPUDecoderImpl from thread-local storage and forwards the call to the
// member function.
class WebGPUDecoderImpl;
constinit thread_local WebGPUDecoderImpl* parent_decoder = nullptr;
base::AutoReset<WebGPUDecoderImpl*> ScopedParentDecoder(
    WebGPUDecoderImpl* parent) {
  return base::AutoReset<WebGPUDecoderImpl*>{&parent_decoder, parent};
}

class WebGPUDecoderImpl final : public WebGPUDecoder {
 public:
  WebGPUDecoderImpl(
      DecoderClient* client,
      CommandBufferServiceBase* command_buffer_service,
      SharedImageManager* shared_image_manager,
      scoped_refptr<MemoryTracker> memory_tracker,
      gles2::Outputter* outputter,
      const GpuPreferences& gpu_preferences,
      scoped_refptr<SharedContextState> shared_context_state,
      std::unique_ptr<DawnCachingInterface> dawn_caching_interface_factory,
      IsolationKeyProvider* isolation_key_provider);

  WebGPUDecoderImpl(const WebGPUDecoderImpl&) = delete;
  WebGPUDecoderImpl& operator=(const WebGPUDecoderImpl&) = delete;

  ~WebGPUDecoderImpl() override;

  // WebGPUDecoder implementation
  ContextResult Initialize(const GpuFeatureInfo& gpu_feature_info) override;

  // DecoderContext implementation.
  base::WeakPtr<DecoderContext> AsWeakPtr() override {
    return weak_ptr_factory_.GetWeakPtr();
  }
  const gles2::ContextState* GetContextState() override { NOTREACHED(); }
  void Destroy(bool have_context) override;
  bool MakeCurrent() override {
    if (gl_context_.get()) {
      gl_context_->MakeCurrentDefault();
    }
    return true;
  }
  gl::GLContext* GetGLContext() override { return nullptr; }
  gl::GLSurface* GetGLSurface() override { NOTREACHED(); }
  const gles2::FeatureInfo* GetFeatureInfo() const override { NOTREACHED(); }
  Capabilities GetCapabilities() override { return {}; }
  GLCapabilities GetGLCapabilities() override { return {}; }
  void RestoreGlobalState() const override { NOTREACHED(); }
  void ClearAllAttributes() const override { NOTREACHED(); }
  void RestoreAllAttributes() const override { NOTREACHED(); }
  void RestoreState(const gles2::ContextState* prev_state) override {
    NOTREACHED();
  }
  void RestoreActiveTexture() const override { NOTREACHED(); }
  void RestoreAllTextureUnitAndSamplerBindings(
      const gles2::ContextState* prev_state) const override {
    NOTREACHED();
  }
  void RestoreActiveTextureUnitBinding(unsigned int target) const override {
    NOTREACHED();
  }
  void RestoreBufferBinding(unsigned int target) override { NOTREACHED(); }
  void RestoreBufferBindings() const override { NOTREACHED(); }
  void RestoreFramebufferBindings() const override { NOTREACHED(); }
  void RestoreRenderbufferBindings() override { NOTREACHED(); }
  void RestoreProgramBindings() const override { NOTREACHED(); }
  void RestoreTextureState(unsigned service_id) override { NOTREACHED(); }
  void RestoreTextureUnitBindings(unsigned unit) const override {
    NOTREACHED();
  }
  void RestoreVertexAttribArray(unsigned index) override { NOTREACHED(); }
  void RestoreAllExternalTextureBindingsIfNeeded() override { NOTREACHED(); }
  QueryManager* GetQueryManager() override { NOTREACHED(); }
  void SetQueryCallback(unsigned int query_client_id,
                        base::OnceClosure callback) override {
    NOTREACHED();
  }
  void CancelAllQueries() override { NOTREACHED(); }
  gles2::GpuFenceManager* GetGpuFenceManager() override { NOTREACHED(); }
  bool HasPendingQueries() const override { return false; }
  void ProcessPendingQueries(bool did_finish) override {}
  bool HasMoreIdleWork() const override { return false; }
  void PerformIdleWork() override {}

  bool HasPollingWork() const override { return has_polling_work_; }

  void PerformPollingWork() override {
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
                 "WebGPUDecoderImpl::PerformPollingWork");
    if (known_device_metadata_.empty()) {
      return;
    }

    has_polling_work_ =
        dawn::native::InstanceProcessEvents(dawn_instance_->Get());

    for (auto it = known_device_metadata_.begin();
         it != known_device_metadata_.end();) {
      auto& device = it->first;
      const bool known = wire_server_->IsDeviceKnown(device.Get());
      if (!known) {
        // The client has dropped all references and the device has been
        // removed from the wire.
        // Release the device and erase it from the map.
        it = known_device_metadata_.erase(it);
      } else {
        ++it;
      }
    }
  }

  TextureBase* GetTextureBase(uint32_t client_id) override { NOTREACHED(); }
  void SetLevelInfo(uint32_t client_id,
                    int level,
                    unsigned internal_format,
                    unsigned width,
                    unsigned height,
                    unsigned depth,
                    unsigned format,
                    unsigned type,
                    const gfx::Rect& cleared_rect) override {
    NOTREACHED();
  }
  bool WasContextLost() const override {
    NOTIMPLEMENTED();
    return false;
  }
  bool WasContextLostByRobustnessExtension() const override { return false; }
  void MarkContextLost(error::ContextLostReason reason) override {
    NOTIMPLEMENTED();
  }
  bool CheckResetStatus() override { NOTREACHED(); }
  void BeginDecoding() override {}
  void EndDecoding() override {}
  const char* GetCommandName(unsigned int command_id) const;
  error::Error DoCommands(unsigned int num_commands,
                          const volatile void* buffer,
                          int num_entries,
                          int* entries_processed) override;
  std::string_view GetLogPrefix() override { return "WebGPUDecoderImpl"; }
  gles2::ContextGroup* GetContextGroup() override { return nullptr; }
  gles2::ErrorState* GetErrorState() override { NOTREACHED(); }
  void BindFramebuffer(unsigned target, uint32_t service_id) const override {
    NOTREACHED();
  }
  bool IsCompressedTextureFormat(unsigned format) override { NOTREACHED(); }
  bool ClearLevel(gles2::Texture* texture,
                  unsigned target,
                  int level,
                  unsigned format,
                  unsigned type,
                  int xoffset,
                  int yoffset,
                  int width,
                  int height) override {
    NOTREACHED();
  }
  bool ClearCompressedTextureLevel(gles2::Texture* texture,
                                   unsigned target,
                                   int level,
                                   unsigned format,
                                   int width,
                                   int height) override {
    NOTREACHED();
  }
  bool ClearCompressedTextureLevel3D(gles2::Texture* texture,
                                     unsigned target,
                                     int level,
                                     unsigned format,
                                     int width,
                                     int height,
                                     int depth) override {
    NOTREACHED();
  }
  bool ClearLevel3D(gles2::Texture* texture,
                    unsigned target,
                    int level,
                    unsigned format,
                    unsigned type,
                    int width,
                    int height,
                    int depth) override {
    NOTREACHED();
  }
  bool initialized() const override { return true; }
  void SetLogCommands(bool log_commands) override { NOTIMPLEMENTED(); }
  gles2::Outputter* outputter() const override {
    NOTIMPLEMENTED();
    return nullptr;
  }
  int GetRasterDecoderId() const override { NOTREACHED(); }

 private:
  typedef error::Error (WebGPUDecoderImpl::*CmdHandler)(
      uint32_t immediate_data_size,
      const volatile void* data);

  // A struct to hold info about each command.
  struct CommandInfo {
    CmdHandler cmd_handler;
    uint8_t arg_flags;   // How to handle the arguments for this command
    uint8_t cmd_flags;   // How to handle this command
    uint16_t arg_count;  // How many arguments are expected for this command.
  };

  // A table of CommandInfo for all the commands.
  static const std::array<CommandInfo, kNumCommands - kFirstWebGPUCommand>
      command_info;

// Generate a member function prototype for each command in an automated and
// typesafe way.
#define WEBGPU_CMD_OP(name) \
  Error Handle##name(uint32_t immediate_data_size, const volatile void* data);
  WEBGPU_COMMAND_LIST(WEBGPU_CMD_OP)
#undef WEBGPU_CMD_OP

  // The current decoder error communicates the decoder error through command
  // processing functions that do not return the error value. Should be set
  // only if not returning an error.
  error::Error current_decoder_error_ = error::kNoError;

  wgpu::Adapter CreatePreferredAdapter(wgpu::PowerPreference power_preference,
                                       bool force_fallback,
                                       wgpu::FeatureLevel feature_level,
                                       bool webgpu_on_vk_gl_interop) const;

  // Decide if a device feature is exposed to render process.
  bool IsFeatureExposed(wgpu::FeatureName feature) const;

  // Dawn wire uses procs which forward their calls to these methods.
  template <typename CallbackInfo>
  WGPUFuture RequestAdapterImpl(WGPUInstance instance,
                                const WGPURequestAdapterOptions* options,
                                CallbackInfo callback_info);
  WGPUBool AdapterHasFeatureImpl(WGPUAdapter adapter, WGPUFeatureName feature);
  void AdapterGetFeaturesImpl(WGPUAdapter adapter,
                              WGPUSupportedFeatures* features_out);
  template <typename CallbackInfo>
  WGPUFuture RequestDeviceImpl(WGPUAdapter adapter,
                               const WGPUDeviceDescriptor* descriptor,
                               CallbackInfo callback_info);

  class SharedImageRepresentationAndAccess;

  bool ValidateAssociateMailboxAndSetSharedImageClearState(
      SharedImageRepresentation* shared_image,
      MailboxFlags flags,
      wgpu::TextureUsage usage,
      wgpu::TextureUsage internal_usage);

  std::unique_ptr<SharedImageRepresentationAndAccess> AssociateMailboxDawn(
      const Mailbox& mailbox,
      MailboxFlags flags,
      const wgpu::Device& device,
      wgpu::BackendType backendType,
      wgpu::TextureUsage usage,
      wgpu::TextureUsage internal_usage,
      std::vector<wgpu::TextureFormat> view_formats);

  std::unique_ptr<SharedImageRepresentationAndAccess>
  AssociateMailboxUsingSkiaFallback(
      const Mailbox& mailbox,
      MailboxFlags flags,
      const wgpu::Device& device,
      wgpu::TextureUsage usage,
      wgpu::TextureUsage internal_usage,
      std::vector<wgpu::TextureFormat> view_formats);

  class SharedBufferRepresentationAndAccess;

  std::unique_ptr<SharedBufferRepresentationAndAccess>
  AssociateMailboxDawnBuffer(const Mailbox& mailbox,
                             const wgpu::Device& device,
                             wgpu::BackendType backendType,
                             wgpu::BufferUsage usage);

  // Device creation requires that an isolation key has been set for the
  // decoder. As a result, this callback also runs all queued device creation
  // calls that were requested and queued before the isolation key was ready.
  void OnGetIsolationKey(const std::string& isolation_key);

  bool use_blocklist() const;

  bool ClearSharedImageWithSkia(const Mailbox& mailbox);

  scoped_refptr<SharedContextState> shared_context_state_;

  std::unique_ptr<SharedImageRepresentationFactory>
      shared_image_representation_factory_;

  std::unique_ptr<dawn::platform::Platform> dawn_platform_;
  std::unique_ptr<DawnInstance> dawn_instance_;
  std::unique_ptr<DawnServiceMemoryTransferService> memory_transfer_service_;

  webgpu::SafetyLevel safety_level_ = webgpu::SafetyLevel::kSafe;
  WebGPUAdapterName use_webgpu_adapter_ = WebGPUAdapterName::kDefault;
  WebGPUPowerPreference use_webgpu_power_preference_ =
      WebGPUPowerPreference::kNone;
  bool force_fallback_adapter_ = false;
  bool webgpu_on_vk_gl_interop_ = false;
  bool force_webgpu_compat_ = false;
  std::vector<std::string> require_enabled_toggles_;
  std::vector<std::string> require_disabled_toggles_;
  base::flat_set<std::string> runtime_unsafe_features_;
  bool tiered_adapter_limits_;

  // Isolation key that is necessary for device requests. Optional to
  // differentiate between an empty isolation key, and an unset one.
  std::optional<std::string> isolation_key_;

  std::unique_ptr<DawnWireServer> wire_server_;
  std::unique_ptr<DawnServiceSerializer> wire_serializer_;

  // Raw pointer to the isolation key provider because the provider must outlive
  // the decoder. Currently, the only implementation of the provider is
  // GpuChannel which is required to outlive the decoder.
  raw_ptr<IsolationKeyProvider> isolation_key_provider_;

  // A queue of RequestAdapter callbacks that were deferred because the
  // isolation key wasn't available yet.
  // The boolean argument should be true iff the device request should be
  // executed. (Passing false will drop the adapter and call back with status
  // RequestDeviceStatus_CallbackCancelled. Cancelling is used on destroy to
  // ensure that all callbacks are resolved. Note the adapter itself is always
  // created immediately, only the callback itself is deferred.)
  using DeferredRequestAdapterCallback = base::OnceCallback<void(bool)>;
  std::vector<DeferredRequestAdapterCallback>
      deferred_request_adapter_callbacks_;

  // Helper class whose derived implementations holds a representation
  // and its ScopedAccess, ensuring safe destruction order.
  class SharedImageRepresentationAndAccess {
   public:
    virtual ~SharedImageRepresentationAndAccess() = default;
    // Get an unowned reference to the wgpu::Texture for the shared image.
    virtual wgpu::Texture texture() const = 0;
    virtual Mailbox mailbox() const = 0;
  };

  // Wraps a |DawnImageRepresentation| as a wgpu::Texture.
  class SharedImageRepresentationAndAccessDawn
      : public SharedImageRepresentationAndAccess {
   public:
    SharedImageRepresentationAndAccessDawn(
        std::unique_ptr<DawnImageRepresentation> representation,
        std::unique_ptr<DawnImageRepresentation::ScopedAccess> access)
        : representation_(std::move(representation)),
          access_(std::move(access)) {}

    wgpu::Texture texture() const override { return access_->texture(); }
    Mailbox mailbox() const override { return representation_->mailbox(); }

   private:
    std::unique_ptr<DawnImageRepresentation> representation_;
    std::unique_ptr<DawnImageRepresentation::ScopedAccess> access_;
  };

  // Wraps a |SkiaImageRepresentation| and exposes
  // it as a wgpu::Texture by performing CPU readbacks/uploads.
  class SharedImageRepresentationAndAccessSkiaFallback
      : public SharedImageRepresentationAndAccess {
   public:
    static std::unique_ptr<SharedImageRepresentationAndAccessSkiaFallback>
    Create(scoped_refptr<SharedContextState> shared_context_state,
           std::unique_ptr<SkiaImageRepresentation> representation,
           wgpu::Instance instance,
           wgpu::Device device,
           wgpu::TextureUsage usage,
           wgpu::TextureUsage internal_usage,
           std::vector<wgpu::TextureFormat> view_formats) {
      viz::SharedImageFormat format = representation->format();
      // Include list of formats this is tested to work with.
      // See gpu/command_buffer/tests/webgpu_mailbox_unittest.cc
      if (format != viz::SinglePlaneFormat::kBGRA_8888 &&
// TODO(crbug.com/40823053): Support "rgba8unorm" canvas context format on Apple
#if !BUILDFLAG(IS_APPLE)
          format != viz::SinglePlaneFormat::kRGBA_8888 &&
#endif
          format != viz::SinglePlaneFormat::kRGBA_F16) {
        return nullptr;
      }

      // Make sure we can create a WebGPU texture for this format
      if (ToDawnFormat(format) == wgpu::TextureFormat::Undefined) {
        return nullptr;
      }

      const bool is_initialized = representation->IsCleared();
      // Create a wgpu::Texture to hold the image contents.
      // It must be internally copyable as this class itself uses the texture as
      // the dest and source of copies for transfer back and forth between Skia
      // and Dawn.
      wgpu::DawnTextureInternalUsageDescriptor internal_usage_desc;
      internal_usage_desc.internalUsage = internal_usage |
                                          wgpu::TextureUsage::CopyDst |
                                          wgpu::TextureUsage::CopySrc;
      wgpu::TextureDescriptor texture_desc = {
          .nextInChain = &internal_usage_desc,
          .usage = usage,
          .dimension = wgpu::TextureDimension::e2D,
          .size = {static_cast<uint32_t>(representation->size().width()),
                   static_cast<uint32_t>(representation->size().height()), 1},
          .format = ToDawnFormat(representation->format()),
          .mipLevelCount = 1,
          .sampleCount = 1,
          .viewFormatCount = view_formats.size(),
          .viewFormats =
              reinterpret_cast<wgpu::TextureFormat*>(view_formats.data()),
      };

      // CreateTexture() may cause a validation error on an invalid texture
      // descriptor, but is suppressed here. It will be caught in by the
      // ValidateTextureDescriptor() call in
      // GPUCanvasContext::getCurrentTexture() instead.
      device.PushErrorScope(wgpu::ErrorFilter::Validation);
      auto texture = device.CreateTexture(&texture_desc);
      bool error = false;
      device.PopErrorScope(
          wgpu::CallbackMode::AllowSpontaneous,
          [&error](wgpu::PopErrorScopeStatus status, wgpu::ErrorType type,
                   wgpu::StringView message) {
            if (type == wgpu::ErrorType::Validation) {
              error = true;
            }
          });
      auto status = instance.WaitAny(0, nullptr, 0);
      DCHECK(status == wgpu::WaitStatus::Success);
      if (error) {
        // If the CreateTexture() call failed, fail this function so that an
        // ErrorSharedImageRepresentationAndAccess is created instead.
        return nullptr;
      }
      auto result =
          base::WrapUnique(new SharedImageRepresentationAndAccessSkiaFallback(
              std::move(shared_context_state), std::move(representation),
              std::move(instance), std::move(device), std::move(texture), usage,
              internal_usage));
      if (is_initialized && !result->PopulateFromSkia()) {
        return nullptr;
      }
      return result;
    }

    ~SharedImageRepresentationAndAccessSkiaFallback() override {
      // If we have write access, flush any writes by uploading
      // into the SkSurface.
      if ((usage_ & kAllowedWritableMailboxTextureUsages) != 0 ||
          (internal_usage_ & kAllowedWritableMailboxTextureUsages) != 0) {
        // Before using the shared context, ensure it is current if we're on GL.
        if (shared_context_state_->GrContextIsGL()) {
          shared_context_state_->MakeCurrent(/* gl_surface */ nullptr);
        }
        if (UploadContentsToSkia()) {
          // Upload to skia was successful. Mark the contents as initialized.
          representation_->SetCleared();
        } else {
          DLOG(ERROR) << "Failed to write to SkSurface.";
        }
      }

      texture_.Destroy();
    }

    wgpu::Texture texture() const override { return texture_.Get(); }
    Mailbox mailbox() const override { return representation_->mailbox(); }

   private:
    SharedImageRepresentationAndAccessSkiaFallback(
        scoped_refptr<SharedContextState> shared_context_state,
        std::unique_ptr<SkiaImageRepresentation> representation,
        wgpu::Instance instance,
        wgpu::Device device,
        wgpu::Texture texture,
        wgpu::TextureUsage usage,
        wgpu::TextureUsage internal_usage)
        : shared_context_state_(std::move(shared_context_state)),
          representation_(std::move(representation)),
          instance_(std::move(instance)),
          device_(std::move(device)),
          texture_(std::move(texture)),
          usage_(usage),
          internal_usage_(internal_usage) {}

    bool ComputeStagingBufferParams(viz::SharedImageFormat format,
                                    const gfx::Size& size,
                                    uint32_t* bytes_per_row,
                                    size_t* buffer_size) const {
      DCHECK(bytes_per_row);
      DCHECK(buffer_size);

      base::CheckedNumeric<uint32_t> checked_bytes_per_row(
          format.BytesPerPixel());
      checked_bytes_per_row *= size.width();

      uint32_t packed_bytes_per_row;
      if (!checked_bytes_per_row.AssignIfValid(&packed_bytes_per_row)) {
        return false;
      }

      // Align up to 256, required by WebGPU buffer->texture and texture->buffer
      // copies.
      checked_bytes_per_row =
          base::bits::AlignUp(packed_bytes_per_row, uint32_t{256});
      if (!checked_bytes_per_row.AssignIfValid(bytes_per_row)) {
        return false;
      }
      if (*bytes_per_row < packed_bytes_per_row) {
        // Overflow in AlignUp.
        return false;
      }

      base::CheckedNumeric<size_t> checked_buffer_size = checked_bytes_per_row;
      checked_buffer_size *= size.height();

      return checked_buffer_size.AssignIfValid(buffer_size);
    }

    bool ReadPixelsIntoBuffer(void* dst_pointer, uint32_t bytes_per_row) {
      // TODO(crbug.com/40924444): Support multiplanar format.
      DCHECK(representation_->format().NumberOfPlanes() == 1);
      DCHECK(dst_pointer);
      std::vector<GrBackendSemaphore> begin_semaphores;
      std::vector<GrBackendSemaphore> end_semaphores;
      auto scoped_read_access = representation_->BeginScopedReadAccess(
          &begin_semaphores, &end_semaphores);
      if (!scoped_read_access) {
        DLOG(ERROR) << "PopulateFromSkia: Couldn't begin shared image access";
        return false;
      }

      // Wait for any work that previously used the image.
      WaitForSemaphores(std::move(begin_semaphores));

      // Success status will be stored here instead of returning early
      // because proper cleanup up the read access must be done at the
      // end of the function.
      bool success = true;

      // Make an SkImage to read the image contents
      auto sk_image =
          scoped_read_access->CreateSkImage(shared_context_state_.get());
      if (!sk_image) {
        DLOG(ERROR) << "Couldn't make SkImage";
        // Don't return early so we can perform proper cleanup later.
        success = false;
      }

      // Read back the Skia image contents into the staging buffer.
      DCHECK(dst_pointer);
      if (shared_context_state_->gr_context()) {
        if (success &&
            !sk_image->readPixels(shared_context_state_->gr_context(),
                                  sk_image->imageInfo(), dst_pointer,
                                  bytes_per_row, 0, 0)) {
          DLOG(ERROR) << "Failed to read from SkImage";
          success = false;
        }
      } else {
        DCHECK(shared_context_state_->graphite_shared_context());
        DCHECK(shared_context_state_->gpu_main_graphite_recorder());
        if (success && !GraphiteReadPixelsSync(
                           shared_context_state_->graphite_shared_context(),
                           shared_context_state_->gpu_main_graphite_recorder(),
                           sk_image.get(), sk_image->imageInfo(), dst_pointer,
                           bytes_per_row, 0, 0)) {
          DLOG(ERROR) << "Failed to read from SkImage";
          success = false;
        }
      }

      // Transition the image back to the desired end state. This is used
      // for transitioning the image to the external queue for Vulkan/GL
      // interop.
      scoped_read_access->ApplyBackendSurfaceEndState();
      // Signal the semaphores.
      SignalSemaphores(std::move(end_semaphores));
      return success;
    }

    bool PopulateFromSkia() {
      uint32_t bytes_per_row;
      size_t buffer_size;
      if (!ComputeStagingBufferParams(representation_->format(),
                                      representation_->size(), &bytes_per_row,
                                      &buffer_size)) {
        return false;
      }

      // Create a staging buffer to hold pixel data which will be uploaded into
      // a texture.
      wgpu::BufferDescriptor buffer_desc = {
          .usage = wgpu::BufferUsage::CopySrc,
          .size = buffer_size,
          .mappedAtCreation = true,
      };
      wgpu::Buffer buffer = device_.CreateBuffer(&buffer_desc);
      void* dst_pointer = buffer.GetMappedRange(0, wgpu::kWholeMapSize);

      if (!ReadPixelsIntoBuffer(dst_pointer, bytes_per_row)) {
        return false;
      }
      // Unmap the buffer.
      buffer.Unmap();

      // Copy from the staging WGPUBuffer into the wgpu::Texture.
      wgpu::DawnEncoderInternalUsageDescriptor internal_usage_desc;
      internal_usage_desc.useInternalUsages = true;
      wgpu::CommandEncoderDescriptor command_encoder_desc = {
          .nextInChain = &internal_usage_desc,
      };

      wgpu::CommandEncoder encoder =
          device_.CreateCommandEncoder(&command_encoder_desc);
      wgpu::TexelCopyBufferInfo buffer_copy = {
          .layout =
              {
                  .bytesPerRow = bytes_per_row,
                  .rowsPerImage = wgpu::kCopyStrideUndefined,
              },
          .buffer = buffer.Get(),
      };
      wgpu::TexelCopyTextureInfo texture_copy = {
          .texture = texture_,
      };
      wgpu::Extent3D extent = {
          static_cast<uint32_t>(representation_->size().width()),
          static_cast<uint32_t>(representation_->size().height()), 1};
      encoder.CopyBufferToTexture(&buffer_copy, &texture_copy, &extent);
      wgpu::CommandBuffer commandBuffer = encoder.Finish();

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

      return true;
    }

    bool UploadContentsToSkia() {
      // TODO(crbug.com/40924444): Support multiplanar format.
      DCHECK(representation_->format().NumberOfPlanes() == 1);

      uint32_t bytes_per_row;
      size_t buffer_size;
      if (!ComputeStagingBufferParams(representation_->format(),
                                      representation_->size(), &bytes_per_row,
                                      &buffer_size)) {
        return false;
      }

      // Create a staging buffer to read back from the texture.
      wgpu::BufferDescriptor buffer_desc = {
          .usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
          .size = buffer_size,
      };
      wgpu::Buffer buffer = device_.CreateBuffer(&buffer_desc);

      wgpu::TexelCopyTextureInfo texture_copy = {
          .texture = texture_,
      };
      wgpu::TexelCopyBufferInfo buffer_copy = {
          .layout =
              {
                  .bytesPerRow = bytes_per_row,
                  .rowsPerImage = wgpu::kCopyStrideUndefined,
              },
          .buffer = buffer,
      };
      wgpu::Extent3D extent = {
          static_cast<uint32_t>(representation_->size().width()),
          static_cast<uint32_t>(representation_->size().height()), 1};

      // Copy from the texture into the staging buffer.
      wgpu::DawnEncoderInternalUsageDescriptor internal_usage_desc;
      internal_usage_desc.useInternalUsages = true;
      wgpu::CommandEncoderDescriptor command_encoder_desc = {
          .nextInChain = &internal_usage_desc,
          .label = "WebGPUDecoderImpl::UploadContentsToSkia",
      };
      wgpu::CommandEncoder encoder =
          device_.CreateCommandEncoder(&command_encoder_desc);
      encoder.CopyTextureToBuffer(&texture_copy, &buffer_copy, &extent);
      wgpu::CommandBuffer commandBuffer = encoder.Finish();

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

      // Map the staging buffer for read.
      bool success = false;
      wgpu::FutureWaitInfo waitInfo{buffer.MapAsync(
          wgpu::MapMode::Read, 0, wgpu::kWholeMapSize,
          wgpu::CallbackMode::WaitAnyOnly,
          [&](wgpu::MapAsyncStatus status, wgpu::StringView message) {
            success = status == wgpu::MapAsyncStatus::Success;
            if (!success) {
              DLOG(ERROR) << message;
            }
          })};

      wgpu::WaitStatus status =
          instance_.WaitAny(1, &waitInfo, std::numeric_limits<uint64_t>::max());
      DCHECK(status == wgpu::WaitStatus::Success);
      if (!success) {
        return false;
      }

      const void* data = buffer.GetConstMappedRange(0, wgpu::kWholeMapSize);
      DCHECK(data);

      std::vector<GrBackendSemaphore> begin_semaphores;
      std::vector<GrBackendSemaphore> end_semaphores;
      auto scoped_write_access = representation_->BeginScopedWriteAccess(
          &begin_semaphores, &end_semaphores,
          SharedImageRepresentation::AllowUnclearedAccess::kYes);
      if (!scoped_write_access) {
        DLOG(ERROR)
            << "UploadContentsToSkia: Couldn't begin shared image access";
        return false;
      }

      auto* surface = scoped_write_access->surface();

      WaitForSemaphores(std::move(begin_semaphores));
      surface->writePixels(SkPixmap(surface->imageInfo(), data, bytes_per_row),
                           /*x*/ 0, /*y*/ 0);

      // It's ok to pass in empty GrFlushInfo here since SignalSemaphores()
      // will populate it with semaphores and call GrDirectContext::flush.
      success = true;
      if (shared_context_state_->gr_context()) {
        skgpu::ganesh::Flush(surface);
      } else {
        DCHECK(shared_context_state_->graphite_shared_context());
        DCHECK(shared_context_state_->gpu_main_graphite_recorder());
        success = GraphiteFlushAndSubmit(
            shared_context_state_->graphite_shared_context(),
            shared_context_state_->gpu_main_graphite_recorder());
      }
      // Transition the image back to the desired end state. This is used for
      // transitioning the image to the external queue for Vulkan/GL interop.
      scoped_write_access->ApplyBackendSurfaceEndState();

      SignalSemaphores(std::move(end_semaphores));

      return success;
    }

    void WaitForSemaphores(std::vector<GrBackendSemaphore> semaphores) {
      if (semaphores.empty())
        return;

      bool wait_result = shared_context_state_->gr_context()->wait(
          semaphores.size(), semaphores.data(),
          /*deleteSemaphoresAfterWait=*/false);
      DCHECK(wait_result);
    }

    void SignalSemaphores(std::vector<GrBackendSemaphore> semaphores) {
      if (semaphores.empty())
        return;

      GrFlushInfo flush_info = {
          .fNumSemaphores = semaphores.size(),
          .fSignalSemaphores = semaphores.data(),
      };
      // Note: this is a no-op if vk_context_provider is null.
      AddVulkanCleanupTaskForSkiaFlush(
          shared_context_state_->vk_context_provider(), &flush_info);
      auto flush_result =
          shared_context_state_->gr_context()->flush(flush_info);
      DCHECK(flush_result == GrSemaphoresSubmitted::kYes);
      shared_context_state_->gr_context()->submit();
    }

    scoped_refptr<SharedContextState> shared_context_state_;
    std::unique_ptr<SkiaImageRepresentation> representation_;
    wgpu::Instance instance_;
    wgpu::Device device_;
    wgpu::Texture texture_;
    wgpu::TextureUsage usage_;
    wgpu::TextureUsage internal_usage_;
  };

  // Implementation of SharedImageRepresentationAndAccess that yields an error
  // texture.
  class ErrorSharedImageRepresentationAndAccess
      : public SharedImageRepresentationAndAccess {
   public:
    ErrorSharedImageRepresentationAndAccess(const wgpu::Device& device,
                                            wgpu::TextureUsage usage,
                                            const Mailbox& mailbox) {
      // Note: the texture descriptor matters little since this texture won't be
      // used for reflection, and all validation check the error state of the
      // texture before the texture attributes.
      wgpu::TextureDescriptor texture_desc = {
          .usage = usage,
          .dimension = wgpu::TextureDimension::e2D,
          .size = {1, 1, 1},
          .format = wgpu::TextureFormat::RGBA8Unorm,
          .mipLevelCount = 1,
          .sampleCount = 1,
      };
      texture_ = device.CreateErrorTexture(&texture_desc);
      mailbox_ = mailbox;
    }
    ~ErrorSharedImageRepresentationAndAccess() override = default;

    wgpu::Texture texture() const override { return texture_.Get(); }
    Mailbox mailbox() const override { return mailbox_; }

   private:
    wgpu::Texture texture_;
    Mailbox mailbox_;
  };

  // Map from the <ID, generation> pair for a wire texture to the shared image
  // representation and access for it.
  base::flat_map<std::tuple<uint32_t, uint32_t>,
                 std::unique_ptr<SharedImageRepresentationAndAccess>>
      associated_shared_image_map_;

  // Helper class whose derived implementations holds a representation
  // and its ScopedAccess, ensuring safe destruction order.
  class SharedBufferRepresentationAndAccess {
   public:
    virtual ~SharedBufferRepresentationAndAccess() = default;
    // Get an unowned reference to the wgpu::Buffer for the shared image.
    virtual wgpu::Buffer buffer() const = 0;
    virtual Mailbox mailbox() const = 0;
  };

  // Wraps a |DawnBufferRepresentation| as a wgpu::Buffer.
  class SharedBufferRepresentationAndAccessDawn
      : public SharedBufferRepresentationAndAccess {
   public:
    SharedBufferRepresentationAndAccessDawn(
        std::unique_ptr<DawnBufferRepresentation> representation,
        std::unique_ptr<DawnBufferRepresentation::ScopedAccess> access)
        : representation_(std::move(representation)),
          access_(std::move(access)) {}

    wgpu::Buffer buffer() const override { return access_->buffer(); }
    Mailbox mailbox() const override { return representation_->mailbox(); }

   private:
    std::unique_ptr<DawnBufferRepresentation> representation_;
    std::unique_ptr<DawnBufferRepresentation::ScopedAccess> access_;
  };

  // Implementation of SharedBufferRepresentationAndAccess that yields an error
  // buffer.
  class ErrorSharedBufferRepresentationAndAccess
      : public SharedBufferRepresentationAndAccess {
   public:
    ErrorSharedBufferRepresentationAndAccess(const wgpu::Device& device,
                                             wgpu::BufferUsage usage,
                                             const Mailbox& mailbox) {
      // Note: the buffer descriptor doesn't matter since this buffer won't be
      // used for reflection and all validation checks the error state of the
      // buffer before the buffer attributes.
      wgpu::BufferDescriptor buffer_desc = {};
      buffer_desc.usage = usage;
      buffer_ = device.CreateErrorBuffer(&buffer_desc);
      mailbox_ = mailbox;
    }
    ~ErrorSharedBufferRepresentationAndAccess() override = default;

    wgpu::Buffer buffer() const override { return buffer_.Get(); }
    Mailbox mailbox() const override { return mailbox_; }

   private:
    wgpu::Buffer buffer_;
    Mailbox mailbox_;
  };

  // Map from the <ID, generation> pair for a wire buffer to the shared buffer
  // representation and access for it.
  base::flat_map<std::tuple<uint32_t, uint32_t>,
                 std::unique_ptr<SharedBufferRepresentationAndAccess>>
      associated_shared_buffer_map_;

  // A container of devices that we've seen on the wire, and their associated
  // metadata. Not all of them may be valid, so it gets pruned when
  // iterating through it in PerformPollingWork.
  struct DeviceMetadata {
    wgpu::AdapterType adapterType;
    wgpu::BackendType backendType;
  };
  struct DeviceHash {
    size_t operator()(const wgpu::Device& device) const {
      return std::hash<WGPUDevice>()(device.Get());
    }
  };
  struct DeviceEqual {
    bool operator()(const wgpu::Device& lhs, const wgpu::Device& rhs) const {
      return lhs.Get() == rhs.Get();
    }
  };
  std::unordered_map<wgpu::Device, DeviceMetadata, DeviceHash, DeviceEqual>
      known_device_metadata_;

  bool has_polling_work_ = false;
  bool destroyed_ = false;

  scoped_refptr<gl::GLContext> gl_context_;

  base::WeakPtrFactory<WebGPUDecoderImpl> weak_ptr_factory_{this};
};

constexpr std::array<WebGPUDecoderImpl::CommandInfo,
                     kNumCommands - kFirstWebGPUCommand>
    WebGPUDecoderImpl::command_info = {{
#define WEBGPU_CMD_OP(name)                                \
  {                                                        \
      &WebGPUDecoderImpl::Handle##name,                    \
      cmds::name::kArgFlags,                               \
      cmds::name::cmd_flags,                               \
      sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
  }, /* NOLINT */
        WEBGPU_COMMAND_LIST(WEBGPU_CMD_OP)
#undef WEBGPU_CMD_OP
    }};

}  // namespace

std::unique_ptr<WebGPUDecoder> CreateWebGPUDecoderImpl(
    DecoderClient* client,
    CommandBufferServiceBase* command_buffer_service,
    SharedImageManager* shared_image_manager,
    scoped_refptr<MemoryTracker> memory_tracker,
    gles2::Outputter* outputter,
    const GpuPreferences& gpu_preferences,
    scoped_refptr<SharedContextState> shared_context_state,
    const DawnCacheOptions& dawn_cache_options,
    IsolationKeyProvider* isolation_key_provider) {
  // Construct a Dawn caching interface if the Dawn configurations enables it.
  // If a handle was set, pass the relevant handle and CacheBlob callback so that
  // writing to disk is enabled. Otherwise pass an incognito in-memory version.
  std::unique_ptr<webgpu::DawnCachingInterface> dawn_caching_interface =
      nullptr;
  if (auto* caching_interface_factory =
          dawn_cache_options.caching_interface_factory.get()) {
    if (dawn_cache_options.handle) {
      // The DecoderClient outlives the DawnCachingInterface, so it is safe
      dawn_caching_interface = caching_interface_factory->CreateInstance(
          *dawn_cache_options.handle,
          base::BindRepeating(&DecoderClient::CacheBlob,
                              base::Unretained(client),
                              gpu::GpuDiskCacheType::kDawnWebGPU));
    } else {
      dawn_caching_interface = caching_interface_factory->CreateInstance();
    }
  }

  return std::make_unique<WebGPUDecoderImpl>(
      client, command_buffer_service, shared_image_manager,
      std::move(memory_tracker), outputter, gpu_preferences,
      std::move(shared_context_state), std::move(dawn_caching_interface),
      isolation_key_provider);
}

WebGPUDecoderImpl::WebGPUDecoderImpl(
    DecoderClient* client,
    CommandBufferServiceBase* command_buffer_service,
    SharedImageManager* shared_image_manager,
    scoped_refptr<MemoryTracker> memory_tracker,
    gles2::Outputter* outputter,
    const GpuPreferences& gpu_preferences,
    scoped_refptr<SharedContextState> shared_context_state,
    std::unique_ptr<DawnCachingInterface> dawn_caching_interface,
    IsolationKeyProvider* isolation_key_provider)
    : WebGPUDecoder(client, command_buffer_service, outputter),
      shared_context_state_(std::move(shared_context_state)),
      shared_image_representation_factory_(
          std::make_unique<SharedImageRepresentationFactory>(
              shared_image_manager,
              std::move(memory_tracker))),
      dawn_platform_(new DawnPlatform(
          base::FeatureList::IsEnabled(features::kWebGPUBlobCache)
              ? std::move(dawn_caching_interface)
              : nullptr,
          /*progress_reporter=*/nullptr,
          /*uma_prefix=*/"GPU.WebGPU.",
          /*record_cache_count_uma=*/false)),
      memory_transfer_service_(new DawnServiceMemoryTransferService(this)),
      wire_serializer_(new DawnServiceSerializer(client)),
      isolation_key_provider_(isolation_key_provider) {
  if (gpu_preferences.enable_webgpu_developer_features ||
      gpu_preferences.enable_webgpu_experimental_features) {
    safety_level_ = webgpu::SafetyLevel::kSafeExperimental;
  }
  if (gpu_preferences.enable_unsafe_webgpu) {
    safety_level_ = webgpu::SafetyLevel::kUnsafe;
  }
  dawn_instance_ = DawnInstance::Create(dawn_platform_.get(), gpu_preferences,
                                        safety_level_);

  use_webgpu_adapter_ = gpu_preferences.use_webgpu_adapter;
  use_webgpu_power_preference_ = gpu_preferences.use_webgpu_power_preference;
  // TODO(crbug.com/500918256): Move VulkanContextProvider creation earlier
  // so `enable_webgpu_on_vk_via_gl_interop` is only true if it exists.
  webgpu_on_vk_gl_interop_ =
      gpu_preferences.enable_webgpu_on_vk_via_gl_interop &&
      shared_context_state_->vk_context_provider();
  force_webgpu_compat_ = gpu_preferences.force_webgpu_compat;
  require_enabled_toggles_ = gpu_preferences.enabled_dawn_features_list;
  require_disabled_toggles_ = gpu_preferences.disabled_dawn_features_list;
  for (std::string& f :
       base::SplitString(features::kWebGPUEnabledToggles.Get(), ",",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
    require_enabled_toggles_.push_back(std::move(f));
  }
  for (std::string& f :
       base::SplitString(features::kWebGPUDisabledToggles.Get(), ",",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
    require_disabled_toggles_.push_back(std::move(f));
  }
  for (std::string& f :
       base::SplitString(features::kWebGPUUnsafeFeatures.Get(), ",",
                         base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
    runtime_unsafe_features_.insert(std::move(f));
  }

  // Force adapters to report their limits in predetermined tiers unless the
  // adapter_limit_tiers toggle is explicitly disabled.
  tiered_adapter_limits_ = !std::ranges::contains(require_disabled_toggles_,
                                                  "tiered_adapter_limits");

  DawnProcTable wire_procs = dawn::native::GetProcs();
  wire_procs.createInstance =
      [](const WGPUInstanceDescriptor*) -> WGPUInstance { NOTREACHED(); };
  wire_procs.instanceRequestAdapter = [](auto... args) {
    DCHECK(parent_decoder);
    return parent_decoder->RequestAdapterImpl(
        std::forward<decltype(args)>(args)...);
  };
  wire_procs.adapterHasFeature = [](auto... args) {
    DCHECK(parent_decoder);
    return parent_decoder->AdapterHasFeatureImpl(
        std::forward<decltype(args)>(args)...);
  };
  wire_procs.adapterGetFeatures = [](auto... args) {
    DCHECK(parent_decoder);
    return parent_decoder->AdapterGetFeaturesImpl(
        std::forward<decltype(args)>(args)...);
  };
  wire_procs.supportedFeaturesFreeMembers =
      [](WGPUSupportedFeatures supported_features) -> void {
    // We don't need any state so we don't need the parent decoder and can free
    // immediately.
    delete[] supported_features.features;
  };
  wire_procs.adapterRequestDevice = [](auto... args) {
    DCHECK(parent_decoder);
    return parent_decoder->RequestDeviceImpl(
        std::forward<decltype(args)>(args)...);
  };

  wire_server_ = DawnWireServer::Create(
      wire_serializer_.get(), memory_transfer_service_.get(), wire_procs);

  wire_server_->InjectInstance(dawn_instance_->Get(), {1, 0});

  // If there is no isolation key provider we don't want to wait for an
  // isolation key to come when processing device requests. Therefore, we can
  // set the isolation key to an empty string to avoid blocking and disable
  // caching in Dawn. Note that the isolation key provider is not available in
  // some testing scenarios and the in-process command buffer case.
  if (isolation_key_provider_ == nullptr) {
    isolation_key_ = "";
  }
}

WebGPUDecoderImpl::~WebGPUDecoderImpl() {
  Destroy(false);
}

void WebGPUDecoderImpl::Destroy(bool have_context) {
  // Resolve all outstanding callbacks for queued device requests if they
  // exist.
  if (isolation_key_) {
    DCHECK(deferred_request_adapter_callbacks_.empty());
  }
  for (auto& request : deferred_request_adapter_callbacks_) {
    std::move(request).Run(false);
  }
  deferred_request_adapter_callbacks_.clear();

  associated_shared_image_map_.clear();
  associated_shared_buffer_map_.clear();

  // Destroy all known devices to ensure that any service-side objects holding
  // refs to these objects observe that the devices are lost and can drop their
  // refs as well as any associated state they are holding.
  for (auto& device_it : known_device_metadata_) {
    device_it.first.Destroy();
  }

  known_device_metadata_.clear();
  wire_server_ = nullptr;

  dawn_instance_->DisconnectDawnPlatform();

  destroyed_ = true;
}

ContextResult WebGPUDecoderImpl::Initialize(
    const GpuFeatureInfo& gpu_feature_info) {
  // TODO(senorblanco): forceFallbackAdapter with --force-webgpu-compat
  // overrides the OpenGLES backend and gives SwiftShader/Vk with Compat
  // validation. Fix this is dawn, and then remove the "!= OpenGLES" clause
  // below.
  if (kGpuFeatureStatusSoftware ==
          gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGPU] &&
      use_webgpu_adapter_ != WebGPUAdapterName::kOpenGLES) {
    force_fallback_adapter_ = true;
  }

  // Create a Chrome-side EGL context. Dawn actually creates its own
  // EGL contexts per-device, but since Chrome is unaware of those
  // contexts, this wrapper context keeps Chrome's virtual context
  // bookkeeping up-to-date.
  // This is only an issue for native EGL/GLES, not ANGLE (which is
  // aware of the the EGL contexts created by Dawn).
  if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
    scoped_refptr<gl::GLSurface> gl_surface(new gl::SurfacelessEGL(
        gl::GLSurfaceEGL::GetGLDisplayEGL(), gfx::Size(1, 1)));
    gl::GLContextAttribs attribs;
    attribs.client_major_es_version = 3;
    attribs.client_minor_es_version = 1;
    // ES 3.1 is required for compute.
    attribs.allow_es_version_fallback = false;
    gl_context_ = new gl::GLContextEGL(nullptr);
    if (!gl_context_->Initialize(gl_surface.get(), attribs)) {
      return ContextResult::kFatalFailure;
    }
    DCHECK(gl_context_->default_surface());
  }
  return ContextResult::kSuccess;
}

bool WebGPUDecoderImpl::IsFeatureExposed(wgpu::FeatureName feature) const {
  switch (feature) {
    case wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses:
    case wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable:
    case wgpu::FeatureName::MultiDrawIndirect:
    case wgpu::FeatureName::SharedBufferMemoryD3D12Resource:
    case wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix:
    case wgpu::FeatureName::TextureCompressionUnaligned:
      return safety_level_ == webgpu::SafetyLevel::kUnsafe;
    case wgpu::FeatureName::AdapterPropertiesD3D:
    case wgpu::FeatureName::AdapterPropertiesVk:
    case wgpu::FeatureName::AdapterPropertiesMemoryHeaps:
    case wgpu::FeatureName::ShaderModuleCompilationOptions:
    case wgpu::FeatureName::AtomicVec2uMinMax:
      return safety_level_ == webgpu::SafetyLevel::kUnsafe ||
             safety_level_ == webgpu::SafetyLevel::kSafeExperimental;
    case wgpu::FeatureName::CoreFeaturesAndLimits:
    case wgpu::FeatureName::DepthClipControl:
    case wgpu::FeatureName::Depth32FloatStencil8:
    case wgpu::FeatureName::TextureCompressionBC:
    case wgpu::FeatureName::TextureCompressionBCSliced3D:
    case wgpu::FeatureName::TextureCompressionETC2:
    case wgpu::FeatureName::TextureCompressionASTC:
    case wgpu::FeatureName::TextureCompressionASTCSliced3D:
    case wgpu::FeatureName::TimestampQuery:
    case wgpu::FeatureName::IndirectFirstInstance:
    case wgpu::FeatureName::ShaderF16:
    case wgpu::FeatureName::RG11B10UfloatRenderable:
    case wgpu::FeatureName::BGRA8UnormStorage:
    case wgpu::FeatureName::Float32Filterable:
    case wgpu::FeatureName::Float32Blendable:
    case wgpu::FeatureName::ClipDistances:
    case wgpu::FeatureName::DualSourceBlending:
    case wgpu::FeatureName::Subgroups:
    case wgpu::FeatureName::DawnMultiPlanarFormats:
    case wgpu::FeatureName::TextureFormatsTier1:
    case wgpu::FeatureName::TextureFormatsTier2:
    case wgpu::FeatureName::PrimitiveIndex:
    case wgpu::FeatureName::TextureComponentSwizzle:
    case wgpu::FeatureName::SubgroupSizeControl: {
      // Likely case when no features are blocked.
      if (runtime_unsafe_features_.empty() ||
          safety_level_ == webgpu::SafetyLevel::kUnsafe) {
        return true;
      }

      auto* info = dawn::native::GetFeatureInfo(feature);
      if (info == nullptr) {
        return false;
      }

      return !runtime_unsafe_features_.contains(info->name);
    }
    default:
      return false;
  }
}

template <typename CallbackInfo>
WGPUFuture WebGPUDecoderImpl::RequestAdapterImpl(
    WGPUInstance instance,
    const WGPURequestAdapterOptions* options,
    CallbackInfo callback_info) {
  WGPURequestAdapterOptions default_options;
  if (options == nullptr) {
    default_options = {};
    options = &default_options;
  }

  bool force_fallback_adapter = force_fallback_adapter_;
  if (use_webgpu_adapter_ == WebGPUAdapterName::kSwiftShader) {
    force_fallback_adapter = true;
  }

  wgpu::FeatureLevel feature_level = wgpu::FeatureLevel::Core;
  if (force_webgpu_compat_ ||
      (static_cast<wgpu::FeatureLevel>(options->featureLevel) ==
           wgpu::FeatureLevel::Compatibility &&
       (safety_level_ == webgpu::SafetyLevel::kUnsafe ||
        safety_level_ == webgpu::SafetyLevel::kSafeExperimental ||
        base::FeatureList::IsEnabled(features::kWebGPUCompatibilityMode)))) {
    feature_level = wgpu::FeatureLevel::Compatibility;
  }

  wgpu::Adapter adapter = CreatePreferredAdapter(
      static_cast<wgpu::PowerPreference>(options->powerPreference),
      options->forceFallbackAdapter || force_fallback_adapter, feature_level,
      webgpu_on_vk_gl_interop_);

  if (adapter == nullptr) {
    // There are no adapters to return since webgpu is not supported here
    callback_info.callback(WGPURequestAdapterStatus_Unavailable, nullptr,
                           MakeStringView("No available adapters."),
                           callback_info.userdata1, callback_info.userdata2);
    return {};
  }

  if (isolation_key_) {
    callback_info.callback(WGPURequestAdapterStatus_Success,
                           adapter.MoveToCHandle(), MakeStringView(),
                           callback_info.userdata1, callback_info.userdata2);
  } else {
    // We can't RequestDevice until we have an isolation key. Defer the
    // RequestAdapter callback until we do. (This is simpler than deferring
    // RequestDevice.)
    DCHECK_NE(isolation_key_provider_, nullptr);
    deferred_request_adapter_callbacks_.emplace_back(base::BindOnce(
        [](WebGPUDecoderImpl* self, wgpu::Adapter adapter,
           CallbackInfo callback_info, bool run) {
          // Set parent_decoder so that the callback can call into webgpu procs.
          const auto resetter = ScopedParentDecoder(self);
          if (run) {
            callback_info.callback(WGPURequestAdapterStatus_Success,
                                   adapter.MoveToCHandle(), MakeStringView(),
                                   callback_info.userdata1,
                                   callback_info.userdata2);
          } else {
            callback_info.callback(
                WGPURequestAdapterStatus_CallbackCancelled, nullptr,
                MakeStringView("Deferred request adapter callback cancelled."),
                callback_info.userdata1, callback_info.userdata2);
          }
        },
        // Note that it is ok to bind the decoder as unretained in this case
        // because the decoder's dtor explicitly resolves all these callbacks.
        base::Unretained(this), adapter, callback_info));
    return {};
  }
  return {};
}

WGPUBool WebGPUDecoderImpl::AdapterHasFeatureImpl(WGPUAdapter adapter,
                                                  WGPUFeatureName feature) {
  if (!IsFeatureExposed(static_cast<wgpu::FeatureName>(feature))) {
    return false;
  }
  wgpu::Adapter adapter_obj(adapter);
  return adapter_obj.HasFeature(static_cast<wgpu::FeatureName>(feature));
}

void WebGPUDecoderImpl::AdapterGetFeaturesImpl(
    WGPUAdapter adapter,
    WGPUSupportedFeatures* features_out) {
  wgpu::Adapter adapter_obj(adapter);
  wgpu::SupportedFeatures supported_features;
  adapter_obj.GetFeatures(&supported_features);

  std::vector<wgpu::FeatureName> exposed_features;
  for (uint32_t i = 0; i < supported_features.featureCount; ++i) {
    wgpu::FeatureName feature = UNSAFE_TODO(supported_features.features[i]);
    if (IsFeatureExposed(feature)) {
      exposed_features.push_back(feature);
    };
  }
  const size_t count = exposed_features.size();
  WGPUFeatureName* features = new WGPUFeatureName[count];
  uint32_t index = 0;
  for (wgpu::FeatureName feature : exposed_features) {
    UNSAFE_TODO(features[index++]) = static_cast<WGPUFeatureName>(feature);
  }
  features_out->featureCount = count;
  features_out->features = features;
}

template <typename CallbackInfo>
WGPUFuture WebGPUDecoderImpl::RequestDeviceImpl(
    WGPUAdapter adapter,
    const WGPUDeviceDescriptor* descriptor,
    CallbackInfo callback_info) {
  wgpu::Adapter adapter_obj(adapter);

  // Copy the descriptor so we can modify it.
  wgpu::DeviceDescriptor desc;
  if (descriptor != nullptr) {
    desc = *reinterpret_cast<const wgpu::DeviceDescriptor*>(descriptor);
  }

  // Check that the only chained struct allowed is DawnConsumeAdapterDescriptor.
  for (auto* chain = desc.nextInChain; chain != nullptr;
       chain = chain->nextInChain) {
    switch (chain->sType) {
      case wgpu::SType::DawnConsumeAdapterDescriptor:
        break;
      default:
        callback_info.callback(
            WGPURequestDeviceStatus_Error, nullptr,
            MakeStringView("Disallowed chained struct requested."),
            callback_info.userdata1, callback_info.userdata2);
        return {};
    }
  }

  std::vector<wgpu::FeatureName> required_features;

  if (desc.requiredFeatureCount) {
    size_t requiredFeatureCount = desc.requiredFeatureCount;
    required_features = {
        desc.requiredFeatures,
        UNSAFE_TODO(desc.requiredFeatures + requiredFeatureCount),
    };

    // Check that no disallowed features were requested. They should be hidden
    // by AdapterGetFeaturesImpl.
    for (const wgpu::FeatureName& feature : required_features) {
      if (!IsFeatureExposed(feature)) {
        callback_info.callback(WGPURequestDeviceStatus_Error, nullptr,
                               MakeStringView("Disallowed feature requested."),
                               callback_info.userdata1,
                               callback_info.userdata2);
        return {};
      }
    }
  }

  // We need to request internal usage to be able to do operations with internal
  // SharedImage / interop methods that would need specific usages.
  required_features.push_back(wgpu::FeatureName::DawnInternalUsages);

  const wgpu::FeatureName kOptionalFeatures[] = {
      // Always require "multi-planar-formats" as long as supported, although
      // currently this feature is not exposed to render process if unsafe apis
      // disallowed.
      wgpu::FeatureName::DawnMultiPlanarFormats,

      // Require platform-specific SharedTextureMemory features for use by the
      // relevant SharedImage backings. These features should always be
      // supported when running on the corresponding backend.
      wgpu::FeatureName::SharedTextureMemoryIOSurface,
      wgpu::FeatureName::SharedFenceMTLSharedEvent,

#if BUILDFLAG(IS_CHROMEOS)
      wgpu::FeatureName::SharedTextureMemoryDmaBuf,
      wgpu::FeatureName::SharedFenceSyncFD,
#endif

#if BUILDFLAG(IS_ANDROID)
      wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer,
      wgpu::FeatureName::SharedFenceSyncFD,
#endif

      wgpu::FeatureName::SharedTextureMemoryD3D11Texture2D,
      wgpu::FeatureName::SharedTextureMemoryDXGISharedHandle,
      wgpu::FeatureName::SharedFenceDXGISharedHandle,

      // Require SharedBufferMemoryD3D12Resource feature for use by the
      // D3DImageBacking. This feature should always be supported when
      // running on the D3D12 backend.
      wgpu::FeatureName::SharedBufferMemoryD3D12Resource,

      // Require platform-specific SharedBufferMemory feature to support
      // importing transfer buffer into Dawn as shared buffer memory in dawn
      // wire.
      wgpu::FeatureName::SharedBufferMemoryHostPointer,
  };
  for (const wgpu::FeatureName& feature : kOptionalFeatures) {
    if (adapter_obj.HasFeature(feature)) {
      required_features.push_back(feature);
    }
  }

#if BUILDFLAG(USE_DAWN) && BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
  // If adapter_options.forceFallbackAdapter is set to true,
  // fallback (Swiftshader) instead of OpenGLES Adapter can still be
  // selected.
  // Make sure the adapter backend type is OpenGLES.
  // Then if on Desktop GL via ANGLE, require GL texture sharing.
  wgpu::AdapterInfo adapter_info = {};
  adapter_obj.GetInfo(&adapter_info);
  if (adapter_info.backendType == wgpu::BackendType::OpenGLES &&
      gl::GetANGLEImplementation() == gl::ANGLEImplementation::kOpenGL) {
    DCHECK(adapter_obj.HasFeature(wgpu::FeatureName::ANGLETextureSharing));
    required_features.push_back(wgpu::FeatureName::ANGLETextureSharing);
  }
#endif

  desc.requiredFeatures = required_features.data();
  desc.requiredFeatureCount = required_features.size();

  // If a new toggle is added here, GetDawnTogglesForWebGPU() which collects
  // info for about:gpu should be updated as well.
  wgpu::DawnTogglesDescriptor dawn_device_toggles;
  std::vector<const char*> require_device_enabled_toggles;
  std::vector<const char*> require_device_disabled_toggles;

  // Disallows usage of SPIR-V by default for security (we only ensure that WGSL
  // is secure).
  require_device_enabled_toggles.push_back("disallow_spirv");

  // Enable timestamp quantization by default for privacy, unless
  // --enable-webgpu-developer-features is used.
  if (safety_level_ == webgpu::SafetyLevel::kSafe) {
    require_device_enabled_toggles.push_back("timestamp_quantization");
  } else {
    require_device_disabled_toggles.push_back("timestamp_quantization");
  }

  // We need the isolation key to create a device. We should already have it
  // because RequestAdapter waits to reply until we do.
  CHECK(isolation_key_.has_value());
  // Disable the blob cache if we don't have an isolation key.
  if (isolation_key_->empty()) {
    require_device_enabled_toggles.push_back("disable_blob_cache");
  }

  for (const std::string& toggles : require_enabled_toggles_) {
    require_device_enabled_toggles.push_back(toggles.c_str());
  }
  for (const std::string& toggles : require_disabled_toggles_) {
    require_device_disabled_toggles.push_back(toggles.c_str());
  }
  dawn_device_toggles.enabledToggles = require_device_enabled_toggles.data();
  dawn_device_toggles.enabledToggleCount =
      require_device_enabled_toggles.size();
  dawn_device_toggles.disabledToggles = require_device_disabled_toggles.data();
  dawn_device_toggles.disabledToggleCount =
      require_device_disabled_toggles.size();
  ChainStruct(desc, &dawn_device_toggles);

  // Dawn caching isolation key information needs to be passed per device. If an
  // isolation key is empty, we do not pass this extra descriptor, and disable
  // the blob cache via toggles above.
  wgpu::DawnCacheDeviceDescriptor dawn_cache;
  if (!isolation_key_->empty()) {
    dawn_cache.isolationKey = isolation_key_->c_str();
    ChainStruct(desc, &dawn_cache);
  }

  bool called = false;
  auto f = adapter_obj.RequestDevice(
      &desc, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestDeviceStatus status, wgpu::Device device,
          wgpu::StringView message) {
        called = true;
        // Copy the device to save in known_device_metadata_.
        wgpu::Device device_copy = device;
        // Forward to the original callback.
        callback_info.callback(
            static_cast<WGPURequestDeviceStatus>(status),
            device.MoveToCHandle(), {message.data, message.length},
            callback_info.userdata1, callback_info.userdata2);
        if (device_copy) {
          // Intercept the response so we can add a device ref to the list of
          // known devices on.
          wgpu::AdapterInfo info;
          adapter_obj.GetInfo(&info);
          known_device_metadata_.emplace(
              std::move(device_copy),
              DeviceMetadata{info.adapterType, info.backendType});
        }
      });
  // The callback must have been called synchronously. We could allow async
  // here, but it would require careful handling of the decoder lifetime.
  CHECK(called);
  return f;
}

bool WebGPUDecoderImpl::use_blocklist() const {
  // Enable the blocklist unless --enable-unsafe-webgpu or
  // --disable-dawn-features=adapter_blocklist
  return !(
      safety_level_ == webgpu::SafetyLevel::kUnsafe ||
      std::ranges::contains(require_disabled_toggles_, "adapter_blocklist"));
}

wgpu::Adapter WebGPUDecoderImpl::CreatePreferredAdapter(
    wgpu::PowerPreference power_preference,
    bool force_fallback,
    wgpu::FeatureLevel feature_level,
    bool webgpu_on_vk_gl_interop) const {
  // The fallback adapter is SwiftShader, which is only allowed with
  // --enable-unsafe-webgpu. Don't make Dawn load it otherwise.
  const bool allow_fallback_adapter =
      safety_level_ == webgpu::SafetyLevel::kUnsafe;
  if (force_fallback && !allow_fallback_adapter) {
    return nullptr;
  }

  // Update power_preference based on command-line flag
  // use_webgpu_power_preference_.
  switch (use_webgpu_power_preference_) {
    case WebGPUPowerPreference::kNone:
      if (power_preference == wgpu::PowerPreference::Undefined) {
        // If on battery power, default to the integrated GPU.
        if (auto* power_monitor = base::PowerMonitor::GetInstance();
            !power_monitor->IsInitialized() ||
            power_monitor->IsOnBatteryPower()) {
          power_preference = wgpu::PowerPreference::LowPower;
        } else {
          power_preference = wgpu::PowerPreference::HighPerformance;
        }
      }
      break;
    case WebGPUPowerPreference::kDefaultLowPower:
      if (power_preference == wgpu::PowerPreference::Undefined) {
        power_preference = wgpu::PowerPreference::LowPower;
      }
      break;
    case WebGPUPowerPreference::kDefaultHighPerformance:
      if (power_preference == wgpu::PowerPreference::Undefined) {
        power_preference = wgpu::PowerPreference::HighPerformance;
      }
      break;
    case WebGPUPowerPreference::kForceLowPower:
      power_preference = wgpu::PowerPreference::LowPower;
      break;
    case WebGPUPowerPreference::kForceHighPerformance:
      power_preference = wgpu::PowerPreference::HighPerformance;
      break;
  }

  // Prepare wgpu::RequestAdapterOptions.
  wgpu::RequestAdapterOptions adapter_options;
  adapter_options.featureLevel = feature_level;
  adapter_options.forceFallbackAdapter = force_fallback;
  adapter_options.powerPreference = power_preference;

  // Prepare adapter toggles descriptor based on required toggles
  wgpu::DawnTogglesDescriptor dawn_adapter_toggles;
  std::vector<const char*> require_adapter_enabled_toggles;
  std::vector<const char*> require_adapter_disabled_toggles;

  for (const std::string& toggles : require_enabled_toggles_) {
    require_adapter_enabled_toggles.push_back(toggles.c_str());
  }
  for (const std::string& toggles : require_disabled_toggles_) {
    require_adapter_disabled_toggles.push_back(toggles.c_str());
  }
  dawn_adapter_toggles.enabledToggles = require_adapter_enabled_toggles.data();
  dawn_adapter_toggles.enabledToggleCount =
      require_adapter_enabled_toggles.size();
  dawn_adapter_toggles.disabledToggles =
      require_adapter_disabled_toggles.data();
  dawn_adapter_toggles.disabledToggleCount =
      require_adapter_disabled_toggles.size();
  ChainStruct(adapter_options, &dawn_adapter_toggles);

#if BUILDFLAG(IS_WIN)
  // On Windows, query the LUID of ANGLE's adapter.
  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
      gl::QueryD3D11DeviceObjectFromANGLE();
  if (!d3d11_device) {
    LOG(ERROR) << "Failed to query ID3D11Device from ANGLE.";
    return nullptr;
  }

  Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
  HRESULT hr = d3d11_device.As(&dxgi_device);
  CHECK_EQ(hr, S_OK);
  Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
  hr = dxgi_device->GetAdapter(&dxgi_adapter);
  CHECK_EQ(hr, S_OK);

  DXGI_ADAPTER_DESC adapter_desc;
  if (!SUCCEEDED(dxgi_adapter->GetDesc(&adapter_desc))) {
    LOG(ERROR) << "Failed to get DXGI_ADAPTER_DESC from ANGLE.";
    return nullptr;
  }

  // Chain the LUID from ANGLE.
  dawn::native::d3d::RequestAdapterOptionsLUID adapter_options_luid = {};
  adapter_options_luid.adapterLUID = adapter_desc.AdapterLuid;
  ChainStruct(adapter_options, &adapter_options_luid);
#endif

#if BUILDFLAG(USE_DAWN) && BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
  dawn::native::opengl::RequestAdapterOptionsGetGLProc
      adapter_options_get_gl_proc = {};
  adapter_options_get_gl_proc.getProc = gl::GetGLProcAddress;
  gl::GLDisplayEGL* gl_display = gl::GLSurfaceEGL::GetGLDisplayEGL();
  if (gl_display) {
    adapter_options_get_gl_proc.display = gl_display->GetDisplay();
  } else {
    adapter_options_get_gl_proc.display = EGL_NO_DISPLAY;
  }

  ChainStruct(adapter_options, &adapter_options_get_gl_proc);
#endif

  // Build a list of backend types we will search for, in order of preference.
  std::vector<wgpu::BackendType> backend_types;
  switch (use_webgpu_adapter_) {
    case WebGPUAdapterName::kD3D11:
      backend_types = {wgpu::BackendType::D3D11};
      break;
    case WebGPUAdapterName::kOpenGLES:
      backend_types = {wgpu::BackendType::OpenGLES};
      break;
    case WebGPUAdapterName::kSwiftShader:
      backend_types = {wgpu::BackendType::Vulkan};
      break;
    case WebGPUAdapterName::kDefault: {
#if BUILDFLAG(IS_WIN)
      backend_types = {wgpu::BackendType::D3D12};
#elif BUILDFLAG(IS_APPLE)
      backend_types = {wgpu::BackendType::Metal};
#elif BUILDFLAG(IS_LINUX)
      if (shared_context_state_->GrContextIsVulkan() ||
          webgpu_on_vk_gl_interop_ ||
          shared_context_state_->IsGraphiteDawnVulkan()) {
        backend_types = {wgpu::BackendType::Vulkan};
      } else {
        // Deliberately disable compat on linux.
        backend_types = {wgpu::BackendType::Null};
      }
#else
      backend_types = {wgpu::BackendType::Vulkan, wgpu::BackendType::OpenGLES};
#endif
      break;
    }
  }

  // `CanUseAdapter` is a helper to determine if an adapter is not blocklisted,
  // supports all required features, and matches the requested adapter options
  // (some of which may be set by command-line flags).
  auto CanUseAdapter = [&](const dawn::native::Adapter& native_adapter) {
    wgpu::Adapter adapter(native_adapter.Get());

    wgpu::AdapterInfo adapter_info = {};
    adapter.GetInfo(&adapter_info);

    if (use_blocklist() && IsWebGPUAdapterBlocklisted(adapter).blocked) {
      return false;
    }

    const bool is_swiftshader =
        adapter_info.adapterType == wgpu::AdapterType::CPU &&
        adapter_info.vendorID == 0x1AE0 && adapter_info.deviceID == 0xC0DE;

    // The adapter must be able to import external textures, or it must be a
    // SwiftShader adapter. For SwiftShader, we will perform a manual
    // upload/readback to/from shared images.
    bool supports_external_textures = false;

#if BUILDFLAG(IS_CHROMEOS)
    if (!adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryDmaBuf) ||
        !adapter.HasFeature(wgpu::FeatureName::SharedFenceSyncFD)) {
      return false;
    }
#endif

#if BUILDFLAG(IS_APPLE)
    supports_external_textures =
        adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface);
#elif BUILDFLAG(IS_ANDROID)
    if (adapter_info.backendType == wgpu::BackendType::OpenGLES) {
      if (!base::FeatureList::IsEnabled(features::kWebGPUAndroidOpenGLES)) {
        return false;
      }
      supports_external_textures = native_adapter.SupportsExternalImages();
    } else {
      supports_external_textures = adapter.HasFeature(
          wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer);
    }
#else
    // Chromium is in the midst of being transitioned to SharedTextureMemory
    // platform by platform. On platforms that have not yet been transitioned,
    // Chromium uses the platform-specific ExternalImage API surfaces.  NOTE:
    // These platforms should be switched to the corresponding
    // SharedTextureMemory feature check as they are converted to using
    // SharedTextureMemory.
    supports_external_textures = native_adapter.SupportsExternalImages();
#endif
    if (!(supports_external_textures || is_swiftshader)) {
      return false;
    }

    // If the power preference is forced, only accept specific adapter
    // types.
    if (use_webgpu_power_preference_ == WebGPUPowerPreference::kForceLowPower &&
        adapter_info.adapterType != wgpu::AdapterType::IntegratedGPU) {
      return false;
    }
    if (use_webgpu_power_preference_ ==
            WebGPUPowerPreference::kForceHighPerformance &&
        adapter_info.adapterType != wgpu::AdapterType::DiscreteGPU) {
      return false;
    }

    return true;
  };

  // Enumerate adapters in order of the preferred backend type.
  for (wgpu::BackendType backend_type : backend_types) {
    adapter_options.backendType = backend_type;
    for (dawn::native::Adapter& native_adapter :
         dawn_instance_->EnumerateAdapters(&adapter_options)) {
      native_adapter.SetUseTieredLimits(tiered_adapter_limits_);

      if (!CanUseAdapter(native_adapter)) {
        continue;
      }

      return wgpu::Adapter(native_adapter.Get());
    }
  }

  if (!allow_fallback_adapter) {
    return nullptr;
  }

  // If we still don't have an adapter, now try to find the fallback adapter.
  adapter_options.forceFallbackAdapter = true;
  adapter_options.backendType = wgpu::BackendType::Vulkan;
  for (dawn::native::Adapter& native_adapter :
       dawn_instance_->EnumerateAdapters(&adapter_options)) {
    native_adapter.SetUseTieredLimits(tiered_adapter_limits_);

    if (!CanUseAdapter(native_adapter)) {
      continue;
    }

    return wgpu::Adapter(native_adapter.Get());
  }

  // No adapter could be found.
  return nullptr;
}

const char* WebGPUDecoderImpl::GetCommandName(unsigned int command_id) const {
  if (command_id >= kFirstWebGPUCommand && command_id < kNumCommands) {
    return webgpu::GetCommandName(static_cast<CommandId>(command_id));
  }
  return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
}

error::Error WebGPUDecoderImpl::DoCommands(unsigned int num_commands,
                                           const volatile void* buffer,
                                           int num_entries,
                                           int* entries_processed) {
  DCHECK(entries_processed);
  int commands_to_process = num_commands;
  error::Error result = error::kNoError;
  const volatile CommandBufferEntry* cmd_data =
      static_cast<const volatile CommandBufferEntry*>(buffer);
  int process_pos = 0;
  CommandId command = static_cast<CommandId>(0);

  while (process_pos < num_entries && result == error::kNoError &&
         commands_to_process--) {
    const unsigned int size = cmd_data->value_header.size;
    command = static_cast<CommandId>(cmd_data->value_header.command);

    if (size == 0) {
      result = error::kInvalidSize;
      break;
    }

    if (static_cast<int>(size) + process_pos > num_entries) {
      result = error::kOutOfBounds;
      break;
    }

    const unsigned int arg_count = size - 1;
    unsigned int command_index = command - kFirstWebGPUCommand;
    if (command_index < command_info.size()) {
      // Prevent all further WebGPU commands from being processed if the server
      // is destroyed.
      if (destroyed_) {
        result = error::kLostContext;
        break;
      }
      const CommandInfo& info = command_info[command_index];
      unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
      if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
          (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
        uint32_t immediate_data_size = (arg_count - info_arg_count) *
                                       sizeof(CommandBufferEntry);  // NOLINT
        result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
      } else {
        result = error::kInvalidArguments;
      }
    } else {
      result = DoCommonCommand(command, arg_count, cmd_data);
    }

    if (result == error::kNoError &&
        current_decoder_error_ != error::kNoError) {
      result = current_decoder_error_;
      current_decoder_error_ = error::kNoError;
    }

    if (result != error::kDeferCommandUntilLater) {
      process_pos += size;
      UNSAFE_TODO(cmd_data += size);
    }
  }

  *entries_processed = process_pos;

  if (error::IsError(result)) {
    LOG(ERROR) << "Error: " << result << " for Command "
               << GetCommandName(command);
  }

  return result;
}

error::Error WebGPUDecoderImpl::HandleDawnCommands(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::DawnCommands& c =
      *static_cast<const volatile webgpu::cmds::DawnCommands*>(cmd_data);
  uint32_t trace_id_high = static_cast<uint32_t>(c.trace_id_high);
  uint32_t trace_id_low = static_cast<uint32_t>(c.trace_id_low);
  size_t size = static_cast<size_t>(c.size);
  uint32_t commands_shm_id = static_cast<uint32_t>(c.commands_shm_id);
  uint32_t commands_shm_offset = static_cast<uint32_t>(c.commands_shm_offset);

  auto shm_commands =
      GetSharedMemoryAsSpan(commands_shm_id, commands_shm_offset, size);
  if (!shm_commands) {
    return error::kOutOfBounds;
  }

  uint64_t trace_id =
      (static_cast<uint64_t>(trace_id_high) << 32) + trace_id_low;
  TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"), "DawnCommands",
              perfetto::TerminatingFlow::Global(trace_id));

  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
               "WebGPUDecoderImpl::HandleDawnCommands", "bytes", size);

  {
    const auto resetter = ScopedParentDecoder(this);
    if (!wire_server_->HandleCommands(*shm_commands)) {
      return error::kLostContext;
    }
  }

  // TODO(crbug.com/40167398): This is O(N) where N is the number of devices.
  // Multiple submits would be O(N*M). We should find a way to more
  // intelligently poll for work on only the devices that need it.
  PerformPollingWork();

  return error::kNoError;
}

bool WebGPUDecoderImpl::ValidateAssociateMailboxAndSetSharedImageClearState(
    SharedImageRepresentation* shared_image,
    MailboxFlags flags,
    wgpu::TextureUsage usage,
    wgpu::TextureUsage internal_usage) {
  if (!shared_image) {
    DLOG(ERROR) << "AssociateMailbox: Couldn't produce shared image";
    return false;
  }

  // Note this usage could come from the webpage. It's important to handle
  // this gracefully without losing the command buffer or WebGPU device.
  if (usage & ~kAllowedMailboxTextureUsages) {
    DLOG(ERROR) << "AssociateMailbox: Invalid usage";
    return false;
  }

  if (internal_usage & ~kAllowedMailboxTextureUsages) {
    LOG(ERROR) << "AssociateMailbox: Invalid internal usage";
    return false;
  }

  if ((usage & kAllowedWritableMailboxTextureUsages) &&
      (!shared_image->usage().Has(SHARED_IMAGE_USAGE_WEBGPU_WRITE))) {
    LOG(ERROR) << "AssociateMailbox: Passing writable usages requires "
                  "WebGPU write access to the SharedImage";
    return false;
  }

  if ((internal_usage & kAllowedWritableMailboxTextureUsages) &&
      (!shared_image->usage().Has(SHARED_IMAGE_USAGE_WEBGPU_WRITE))) {
    LOG(ERROR) << "AssociateMailbox: Passing writable internal usages requires "
                  "WebGPU write access to the SharedImage";
    return false;
  }

  if (flags & WEBGPU_MAILBOX_DISCARD) {
    if (!shared_image->usage().Has(SHARED_IMAGE_USAGE_WEBGPU_WRITE)) {
      LOG(ERROR)
          << "AssociateMailbox: Using WEBGPU_MAILBOX_DISCARD to clear the "
             "texture requires WebGPU write access to the SharedImage";
      return false;
    }
    // Set contents to uncleared.
    shared_image->SetClearedRect(gfx::Rect());

    if (!(usage & kWritableUsagesSupportingLazyClear) &&
        !(internal_usage & kWritableUsagesSupportingLazyClear)) {
      LOG(ERROR) << "AssociateMailbox: Using WEBGPU_MAILBOX_DISCARD to clear "
                    "the texture requires passing a usage that supports lazy "
                    "clearing";
      return false;
    }
  } else if (!shared_image->IsCleared()) {
    if (!shared_image->usage().Has(SHARED_IMAGE_USAGE_WEBGPU_WRITE)) {
      LOG(ERROR) << "AssociateMailbox: Accessing an uncleared texture requires "
                    "WebGPU write access to the SharedImage";
      return false;
    }

    if (!(usage & kWritableUsagesSupportingLazyClear) &&
        !(internal_usage & kWritableUsagesSupportingLazyClear)) {
      LOG(ERROR) << "AssociateMailbox: Accessing an uncleared texture "
                    "requires passing a usage that supports lazy clearing";
      return false;
    }
  }

  return true;
}

std::unique_ptr<WebGPUDecoderImpl::SharedImageRepresentationAndAccess>
WebGPUDecoderImpl::AssociateMailboxDawn(
    const Mailbox& mailbox,
    MailboxFlags flags,
    const wgpu::Device& device,
    wgpu::BackendType backendType,
    wgpu::TextureUsage usage,
    wgpu::TextureUsage internal_usage,
    std::vector<wgpu::TextureFormat> view_formats) {
  std::unique_ptr<DawnImageRepresentation> shared_image =
      shared_image_representation_factory_->ProduceDawn(
          mailbox, device, backendType, std::move(view_formats),
          shared_context_state_);

  if (!ValidateAssociateMailboxAndSetSharedImageClearState(
          shared_image.get(), flags, usage, internal_usage)) {
    return nullptr;
  }

#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_APPLE) && \
    !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_LINUX)
  if (usage & wgpu::TextureUsage::StorageBinding) {
    LOG(ERROR) << "AssociateMailbox: wgpu::TextureUsage::StorageBinding is NOT "
                  "supported yet on this platform.";
    return nullptr;
  }
#endif

  std::unique_ptr<DawnImageRepresentation::ScopedAccess> scoped_access =
      shared_image->BeginScopedAccess(
          usage, internal_usage,
          SharedImageRepresentation::AllowUnclearedAccess::kYes);
  if (!scoped_access) {
    DLOG(ERROR) << "AssociateMailbox: Couldn't begin shared image access";
    return nullptr;
  }

  return std::make_unique<SharedImageRepresentationAndAccessDawn>(
      std::move(shared_image), std::move(scoped_access));
}

std::unique_ptr<WebGPUDecoderImpl::SharedImageRepresentationAndAccess>
WebGPUDecoderImpl::AssociateMailboxUsingSkiaFallback(
    const Mailbox& mailbox,
    MailboxFlags flags,
    const wgpu::Device& device,
    wgpu::TextureUsage usage,
    wgpu::TextureUsage internal_usage,
    std::vector<wgpu::TextureFormat> view_formats) {
  // Before using the shared context, ensure it is current if we're on GL.
  if (shared_context_state_->GrContextIsGL()) {
    shared_context_state_->MakeCurrent(/* gl_surface */ nullptr);
  }

  // Produce a Skia image from the mailbox.
  std::unique_ptr<SkiaImageRepresentation> shared_image =
      shared_image_representation_factory_->ProduceSkia(
          mailbox, shared_context_state_.get());

  if (!ValidateAssociateMailboxAndSetSharedImageClearState(
          shared_image.get(), flags, usage, internal_usage)) {
    return nullptr;
  }

  return SharedImageRepresentationAndAccessSkiaFallback::Create(
      shared_context_state_, std::move(shared_image), dawn_instance_->Get(),
      device, usage, internal_usage, std::move(view_formats));
}

error::Error WebGPUDecoderImpl::HandleAssociateMailboxImmediate(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::AssociateMailboxImmediate& c =
      *static_cast<const volatile webgpu::cmds::AssociateMailboxImmediate*>(
          cmd_data);
  uint32_t device_id = static_cast<uint32_t>(c.device_id);
  uint32_t device_generation = static_cast<uint32_t>(c.device_generation);
  uint32_t id = static_cast<uint32_t>(c.id);
  uint32_t generation = static_cast<uint32_t>(c.generation);
  wgpu::TextureUsage usage = static_cast<wgpu::TextureUsage>(c.usage);
  wgpu::TextureUsage internal_usage =
      static_cast<wgpu::TextureUsage>(c.internal_usage);
  MailboxFlags flags = static_cast<MailboxFlags>(c.flags);
  uint32_t view_format_count = static_cast<uint32_t>(c.view_format_count);

  GLuint packed_entry_count = c.count;
  // The immediate_data should be uint32_t-sized words that exactly matches
  // the packed_entry_count.
  if (immediate_data_size % sizeof(uint32_t) != 0 ||
      immediate_data_size / sizeof(uint32_t) != packed_entry_count) {
    return error::kOutOfBounds;
  }

  volatile const uint32_t* packed_data =
      gles2::GetImmediateDataAs<volatile const uint32_t*>(
          c, immediate_data_size, immediate_data_size);

  // Compute the expected number of packed entries. Cast to uint64_t to
  // avoid overflow.
  static_assert(sizeof(Mailbox) % sizeof(uint32_t) == 0u);
  constexpr uint32_t kMailboxNumEntries = sizeof(Mailbox) / sizeof(uint32_t);
  uint64_t expected_packed_entries =
      static_cast<uint64_t>(kMailboxNumEntries) + view_format_count;

  // The packed data should be non-empty and exactly match the expected number
  // of entries.
  if (packed_data == nullptr || packed_entry_count != expected_packed_entries) {
    return error::kOutOfBounds;
  }

  // Unpack the mailbox
  Mailbox mailbox = Mailbox::FromVolatile(
      *reinterpret_cast<const volatile Mailbox*>(packed_data));
  UNSAFE_TODO(packed_data += kMailboxNumEntries);
  DLOG_IF(ERROR, !mailbox.Verify())
      << "AssociateMailbox was passed an invalid mailbox";

  // Copy the view formats into a vector.
  static_assert(sizeof(wgpu::TextureFormat) == sizeof(uint32_t));
  std::vector<wgpu::TextureFormat> view_formats(view_format_count);
  UNSAFE_TODO(memcpy(view_formats.data(),
                     const_cast<const uint32_t*>(packed_data),
                     view_format_count * sizeof(wgpu::TextureFormat)));

  wgpu::Device device = wire_server_->GetDevice(device_id, device_generation);
  if (device == nullptr) {
    return error::kInvalidArguments;
  }

  {
    std::tuple<uint32_t, uint32_t> id_and_generation{id, generation};
    auto it = associated_shared_image_map_.find(id_and_generation);
    if (it != associated_shared_image_map_.end()) {
      DLOG(ERROR) << "AssociateMailbox to an already associated texture.";
      return error::kInvalidArguments;
    }
  }

  std::unique_ptr<SharedImageRepresentationAndAccess> representation_and_access;
  auto it = known_device_metadata_.find(device);
  CHECK(it != known_device_metadata_.end());
  if (it->second.adapterType == wgpu::AdapterType::CPU) {
    representation_and_access = AssociateMailboxUsingSkiaFallback(
        mailbox, flags, device, usage, internal_usage, std::move(view_formats));
  } else {
    representation_and_access =
        AssociateMailboxDawn(mailbox, flags, device, it->second.backendType,
                             usage, internal_usage, std::move(view_formats));
  }

  if (!representation_and_access) {
    // According to the WebGPU specification, failing to create a wgpu::Texture
    // which wraps a shared image (like the canvas drawing buffer) should yield
    // an error wgpu::Texture. Use an implementation of
    // SharedImageRepresentationAndAccess which always provides an error.
    representation_and_access =
        std::make_unique<ErrorSharedImageRepresentationAndAccess>(device, usage,
                                                                  mailbox);
  }

  // Inject the texture in the dawn::wire::Server and remember which shared
  // image it is associated with.
  if (!wire_server_->InjectTexture(representation_and_access->texture().Get(),
                                   {id, generation},
                                   {device_id, device_generation})) {
    DLOG(ERROR) << "AssociateMailbox: Invalid texture ID";
    return error::kInvalidArguments;
  }

  std::tuple<uint32_t, uint32_t> id_and_generation{id, generation};
  auto insertion = associated_shared_image_map_.emplace(
      id_and_generation, std::move(representation_and_access));

  // InjectTexture already validated that the (ID, generation) can't have been
  // registered before.
  DCHECK(insertion.second);
  return error::kNoError;
}

error::Error WebGPUDecoderImpl::HandleDissociateMailbox(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::DissociateMailbox& c =
      *static_cast<const volatile webgpu::cmds::DissociateMailbox*>(cmd_data);
  uint32_t texture_id = static_cast<uint32_t>(c.texture_id);
  uint32_t texture_generation = static_cast<uint32_t>(c.texture_generation);

  std::tuple<uint32_t, uint32_t> id_and_generation{texture_id,
                                                   texture_generation};
  auto it = associated_shared_image_map_.find(id_and_generation);
  if (it == associated_shared_image_map_.end()) {
    DLOG(ERROR) << "DissociateMailbox: Invalid texture ID";
    return error::kInvalidArguments;
  }

  associated_shared_image_map_.erase(it);
  return error::kNoError;
}

error::Error WebGPUDecoderImpl::HandleDissociateMailboxForPresent(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::DissociateMailboxForPresent& c =
      *static_cast<const volatile webgpu::cmds::DissociateMailboxForPresent*>(
          cmd_data);
  uint32_t device_id = static_cast<uint32_t>(c.device_id);
  uint32_t device_generation = static_cast<uint32_t>(c.device_generation);
  uint32_t texture_id = static_cast<uint32_t>(c.texture_id);
  uint32_t texture_generation = static_cast<uint32_t>(c.texture_generation);

  std::tuple<uint32_t, uint32_t> id_and_generation{texture_id,
                                                   texture_generation};
  auto it = associated_shared_image_map_.find(id_and_generation);
  if (it == associated_shared_image_map_.end()) {
    DLOG(ERROR) << "DissociateMailbox: Invalid texture ID";
    return error::kInvalidArguments;
  }

  wgpu::Device device = wire_server_->GetDevice(device_id, device_generation);
  if (!device) {
    return error::kInvalidArguments;
  }

  Mailbox mailbox = it->second->mailbox();
  wgpu::Texture texture = it->second->texture();
  DCHECK(texture);
  bool is_initialized =
      dawn::native::IsTextureSubresourceInitialized(texture.Get(), 0, 1, 0, 1);

  associated_shared_image_map_.erase(it);
  // The compositor renders uninitialized textures as red. If the texture is
  // not initialized, we need to explicitly clear its contents to black.
  if (!is_initialized && !ClearSharedImageWithSkia(mailbox)) {
    return error::kInvalidArguments;
  }
  return error::kNoError;
}

std::unique_ptr<WebGPUDecoderImpl::SharedBufferRepresentationAndAccess>
WebGPUDecoderImpl::AssociateMailboxDawnBuffer(const Mailbox& mailbox,
                                              const wgpu::Device& device,
                                              wgpu::BackendType backendType,
                                              wgpu::BufferUsage usage) {
  std::unique_ptr<DawnBufferRepresentation> shared_buffer =
      shared_image_representation_factory_->ProduceDawnBuffer(
          mailbox, device, backendType, shared_context_state_);

  // Checks similar to ValidateAssociateMailboxAndSetSharedImageClearState but
  // for buffers.
  if (!shared_buffer) {
    DLOG(ERROR) << "AssociateMailboxDawnBuffer: Couldn't produce shared image";
    return nullptr;
  }
  if (usage & ~kAllowedMailboxBufferUsages) {
    DLOG(ERROR) << "AssociateMailboxDawnBuffer: Unsupported Buffer usages.";
    return nullptr;
  }
  if (!shared_buffer->usage().HasAll(SHARED_IMAGE_USAGE_WEBGPU_READ |
                                     SHARED_IMAGE_USAGE_WEBGPU_WRITE)) {
    DLOG(ERROR) << "AssociateMailboxDawnBuffer: Missing SharedImage usages.";
    return nullptr;
  }

  std::unique_ptr<DawnBufferRepresentation::ScopedAccess> scoped_access =
      shared_buffer->BeginScopedAccess(usage);
  if (!scoped_access) {
    DLOG(ERROR)
        << "AssociateMailboxDawnBuffer: Couldn't begin shared image access";
    return nullptr;
  }

  return std::make_unique<SharedBufferRepresentationAndAccessDawn>(
      std::move(shared_buffer), std::move(scoped_access));
}

error::Error WebGPUDecoderImpl::HandleAssociateMailboxForBufferImmediate(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::AssociateMailboxForBufferImmediate& c =
      *static_cast<
          const volatile webgpu::cmds::AssociateMailboxForBufferImmediate*>(
          cmd_data);
  uint32_t device_id = static_cast<uint32_t>(c.device_id);
  uint32_t device_generation = static_cast<uint32_t>(c.device_generation);
  uint32_t id = static_cast<uint32_t>(c.id);
  uint32_t generation = static_cast<uint32_t>(c.generation);
  wgpu::BufferUsage usage = static_cast<wgpu::BufferUsage>(c.usage);

  if (sizeof(Mailbox) != immediate_data_size) {
    return error::kOutOfBounds;
  }

  volatile const GLbyte* immediate_data =
      gles2::GetImmediateDataAs<volatile const GLbyte*>(c, sizeof(Mailbox),
                                                        immediate_data_size);
  Mailbox mailbox = Mailbox::FromVolatile(
      *reinterpret_cast<const volatile Mailbox*>(immediate_data));
  DLOG_IF(ERROR, !mailbox.Verify())
      << "AssociateMailboxForBuffer was passed an invalid mailbox";

  wgpu::Device device = wire_server_->GetDevice(device_id, device_generation);
  if (device == nullptr) {
    return error::kInvalidArguments;
  }

  {
    auto it = associated_shared_buffer_map_.find({id, generation});
    if (it != associated_shared_buffer_map_.end()) {
      DLOG(ERROR)
          << "AssociateMailboxForBuffer to an already associated buffer.";
      return error::kInvalidArguments;
    }
  }

  std::unique_ptr<SharedBufferRepresentationAndAccess>
      representation_and_access;
  auto it = known_device_metadata_.find(device);
  CHECK(it != known_device_metadata_.end());
  representation_and_access = AssociateMailboxDawnBuffer(
      mailbox, device, it->second.backendType, usage);

  if (!representation_and_access) {
    // The WebGPU specification error model is that failure to create a buffer
    // returns an error buffer instead. Follow this pattern here.
    representation_and_access =
        std::make_unique<ErrorSharedBufferRepresentationAndAccess>(
            device, usage, mailbox);
  }

  // Inject the buffer in the dawn::wire::Server and remember which shared
  // image it is associated with.
  if (!wire_server_->InjectBuffer(representation_and_access->buffer().Get(),
                                  {id, generation},
                                  {device_id, device_generation})) {
    DLOG(ERROR) << "AssociateMailboxForBuffer: Invalid buffer ID";
    return error::kInvalidArguments;
  }

  auto insertion = associated_shared_buffer_map_.emplace(
      std::tuple<uint32_t, uint32_t>(id, generation),
      std::move(representation_and_access));

  // InjectBuffer already validated that the (ID, generation) can't have been
  // registered before.
  DCHECK(insertion.second);
  return error::kNoError;
}

error::Error WebGPUDecoderImpl::HandleDissociateMailboxForBuffer(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::DissociateMailboxForBuffer& c =
      *static_cast<const volatile webgpu::cmds::DissociateMailboxForBuffer*>(
          cmd_data);
  uint32_t buffer_id = static_cast<uint32_t>(c.buffer_id);
  uint32_t buffer_generation = static_cast<uint32_t>(c.buffer_generation);

  auto it = associated_shared_buffer_map_.find({buffer_id, buffer_generation});
  if (it == associated_shared_buffer_map_.end()) {
    DLOG(ERROR) << "DissociateMailboxForBuffer: Invalid buffer ID";
    return error::kInvalidArguments;
  }

  associated_shared_buffer_map_.erase(it);
  return error::kNoError;
}

bool WebGPUDecoderImpl::ClearSharedImageWithSkia(const Mailbox& mailbox) {
  // Before using the shared context, ensure it is current if we're on GL.
  if (shared_context_state_->GrContextIsGL()) {
    shared_context_state_->MakeCurrent(/* gl_surface */ nullptr);
  }

  std::unique_ptr<SkiaImageRepresentation> representation =
      shared_image_representation_factory_->ProduceSkia(
          mailbox, shared_context_state_.get());
  if (!representation) {
    return false;
  }

  std::vector<GrBackendSemaphore> begin_semaphores;
  std::vector<GrBackendSemaphore> end_semaphores;
  auto scoped_write_access = representation->BeginScopedWriteAccess(
      &begin_semaphores, &end_semaphores,
      SharedImageRepresentation::AllowUnclearedAccess::kYes);
  if (!scoped_write_access) {
    DLOG(ERROR) << "ClearSharedImage: Couldn't begin shared image access";
    return false;
  }

  auto* surface = scoped_write_access->surface();
  if (!begin_semaphores.empty()) {
    // gr_context() must not be null when begin_semaphores is not empty.
    DCHECK(shared_context_state_->gr_context());
    if (!shared_context_state_->gr_context()->wait(
            begin_semaphores.size(), begin_semaphores.data(),
            /*deleteSemaphoresAfterWait=*/false)) {
      DLOG(ERROR) << "ClearSharedImage: Skia GrContext wait failed";
      return false;
    }
  }
  auto* canvas = surface->getCanvas();
  SkColor4f clear_color;
  if (representation->alpha_type() == kOpaque_SkAlphaType) {
    clear_color = {0, 0, 0, 1};
  } else {
    clear_color = {0, 0, 0, 0};
  }
  canvas->drawColor(clear_color, SkBlendMode::kSrc);

  // It's ok to pass in empty GrFlushInfo here since SignalSemaphores()
  // will populate it with semaphores and call GrDirectContext::flush.
  if (shared_context_state_->gr_context()) {
    skgpu::ganesh::Flush(surface);
  } else {
    DCHECK(shared_context_state_->graphite_shared_context());
    DCHECK(shared_context_state_->gpu_main_graphite_recorder());
    if (!GraphiteFlushAndSubmit(
            shared_context_state_->graphite_shared_context(),
            shared_context_state_->gpu_main_graphite_recorder())) {
      DLOG(ERROR) << "ClearSharedImage: GraphiteFlushAndSubmit failed";
      return false;
    }
  }
  // Transition the image back to the desired end state. This is used for
  // transitioning the image to the external queue for Vulkan/GL interop.
  scoped_write_access->ApplyBackendSurfaceEndState();
  if (!shared_context_state_->SubmitIfNecessary(
          std::move(end_semaphores), /*need_graphite_submit=*/false)) {
    DLOG(ERROR) << "ClearSharedImage: SharedContextState submit failed";
    return false;
  }
  representation->SetCleared();
  return true;
}

void WebGPUDecoderImpl::OnGetIsolationKey(const std::string& isolation_key) {
  DCHECK(!isolation_key_.has_value());
  isolation_key_ = isolation_key;

  for (auto& callback : deferred_request_adapter_callbacks_) {
    std::move(callback).Run(true);
  }
  deferred_request_adapter_callbacks_.clear();

  // The requests have been handled, but they may need to be flushed, so perform
  // polling work.
  PerformPollingWork();
}

error::Error WebGPUDecoderImpl::HandleSetWebGPUExecutionContextToken(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile webgpu::cmds::SetWebGPUExecutionContextToken& c = *static_cast<
      const volatile webgpu::cmds::SetWebGPUExecutionContextToken*>(cmd_data);
  blink::WebGPUExecutionContextToken::Tag type{c.type};
  uint64_t high = uint64_t(c.high_high) << 32 | uint64_t(c.high_low);
  uint64_t low = uint64_t(c.low_high) << 32 | uint64_t(c.low_low);
  std::optional<base::UnguessableToken> unguessable_token =
      base::UnguessableToken::Deserialize(high, low);
  if (!unguessable_token.has_value()) {
    return error::kInvalidArguments;
  }
  blink::WebGPUExecutionContextToken execution_context_token;
  switch (type) {
    case blink::WebGPUExecutionContextToken::IndexOf<blink::DocumentToken>(): {
      execution_context_token = blink::WebGPUExecutionContextToken(
          blink::DocumentToken(unguessable_token.value()));
      break;
    }
    case blink::WebGPUExecutionContextToken::IndexOf<
        blink::DedicatedWorkerToken>(): {
      execution_context_token = blink::WebGPUExecutionContextToken(
          blink::DedicatedWorkerToken(unguessable_token.value()));
      break;
    }
    case blink::WebGPUExecutionContextToken::IndexOf<
        blink::SharedWorkerToken>(): {
      execution_context_token = blink::WebGPUExecutionContextToken(
          blink::SharedWorkerToken(unguessable_token.value()));
      break;
    }
    case blink::WebGPUExecutionContextToken::IndexOf<
        blink::ServiceWorkerToken>(): {
      execution_context_token = blink::WebGPUExecutionContextToken(
          blink::ServiceWorkerToken(unguessable_token.value()));
      break;
    }
    default:
      NOTREACHED();
  }
  isolation_key_provider_->GetIsolationKey(
      execution_context_token,
      base::BindPostTask(base::SingleThreadTaskRunner::GetCurrentDefault(),
                         base::BindOnce(&WebGPUDecoderImpl::OnGetIsolationKey,
                                        weak_ptr_factory_.GetWeakPtr())));
  return error::kNoError;
}

}  // namespace webgpu
}  // namespace gpu
