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

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.
class WebGPUDecoderImpl;
constinit thread_local WebGPUDecoderImpl* parent_decoder = nullptr;

// DawnWireServer is a wrapper around dawn::wire::WireServer which allows
// overriding some of the WGPU procs the server delegates calls to.
// It has a special feature that around HandleDawnCommands, its owning
// WebGPUDecoderImpl is stored in thread-local storage. 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 DawnWireServer : public dawn::wire::WireServer {
 public:
  template <typename... Procs>
  static std::unique_ptr<DawnWireServer> Create(
      WebGPUDecoderImpl* decoder,
      dawn::wire::CommandSerializer* serializer,
      dawn::wire::server::MemoryTransferService* memory_transfer_service,
      const DawnProcTable& procs) {
    dawn::wire::WireServerDescriptor descriptor = {};
    descriptor.procs = &procs;
    descriptor.serializer = serializer;
    descriptor.memoryTransferService = memory_transfer_service;
    descriptor.useSpontaneousCallbacks =
        features::kWebGPUSpontaneousWireServer.Get();

    return base::WrapUnique(new DawnWireServer(decoder, descriptor));
  }

  ~DawnWireServer() override = default;

  base::AutoReset<WebGPUDecoderImpl*> ScopedParentDecoder() {
    return base::AutoReset<WebGPUDecoderImpl*>{&parent_decoder, decoder_};
  }

  // Handle Dawn commands. Forward the call to the base class, but
  // set |parent_decoder| around it.
  const volatile char* HandleCommands(const volatile char* commands,
                                      size_t size) override {
    const auto resetter = ScopedParentDecoder();
    const volatile char* rv =
        dawn::wire::WireServer::HandleCommands(commands, size);
    return rv;
  }

 private:
  DawnWireServer(WebGPUDecoderImpl* decoder,
                 const dawn::wire::WireServerDescriptor& desc)
      : dawn::wire::WireServer(desc), decoder_(decoder) {}

  raw_ptr<WebGPUDecoderImpl> decoder_;
};

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_ ||
           (!use_spontaneous_wire_server_ && wire_serializer_->NeedsFlush());
  }

  void PerformPollingWork() override {
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
                 "WebGPUDecoderImpl::PerformPollingWork");
    if (known_device_metadata_.empty()) {
      if (!use_spontaneous_wire_server_) {
        wire_serializer_->Flush();
      }
      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;
      }
    }
    if (!use_spontaneous_wire_server_) {
      wire_serializer_->Flush();
    }
  }

  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(); }
  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 CommandInfo command_info[kNumCommands - kFirstWebGPUCommand];

// 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_;
  bool use_spontaneous_wire_server_;

  // 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.
      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());
        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 true;
    }

    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 WebGPUDecoderImpl::CommandInfo 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;
  webgpu_on_vk_gl_interop_ = gpu_preferences.enable_webgpu_on_vk_via_gl_interop;
  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)...);
  };

  use_spontaneous_wire_server_ = features::kWebGPUSpontaneousWireServer.Get();
  wire_server_ = DawnWireServer::Create(
      this, 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;
    gl_context_ = new gl::GLContextEGL(nullptr);
    gl_context_->Initialize(gl_surface.get(), attribs);
    DCHECK(gl_context_->default_surface());
  }
  return ContextResult::kSuccess;
}

bool WebGPUDecoderImpl::IsFeatureExposed(wgpu::FeatureName feature) const {
  switch (feature) {
    case wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses:
    case wgpu::FeatureName::MultiDrawIndirect:
    case wgpu::FeatureName::SharedBufferMemoryD3D12Resource:
    case wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix:
      return safety_level_ == webgpu::SafetyLevel::kUnsafe;
    case wgpu::FeatureName::AdapterPropertiesD3D:
    case wgpu::FeatureName::AdapterPropertiesVk:
    case wgpu::FeatureName::AdapterPropertiesMemoryHeaps:
    case wgpu::FeatureName::ShaderModuleCompilationOptions:
      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: {
      // 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 = self->wire_server_->ScopedParentDecoder();
          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_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,
  };
  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 {
  // 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;
  if (!SUCCEEDED(dxgi_device->GetAdapter(&dxgi_adapter))) {
    LOG(ERROR) << "Failed to get IDXGIAdapter from ANGLE.";
    return nullptr;
  }

  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_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 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 < std::size(command_info)) {
      // Prevent all further WebGPU commands from being processed if the server
      // is destroyed.
      if (destroyed_) {
        result = error::kLostContext;
        break;
      }
      const CommandInfo& info = UNSAFE_TODO(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);
  uint32_t size = static_cast<uint32_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);

  const volatile char* shm_commands = GetSharedMemoryAs<const volatile char*>(
      commands_shm_id, commands_shm_offset, size);
  if (shm_commands == nullptr) {
    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);

  if (!wire_server_->HandleCommands(shm_commands, size)) {
    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_);

  if (!shared_buffer) {
    DLOG(ERROR) << "AssociateMailboxDawnBuffer: Couldn't produce shared image";
    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);
  DCHECK(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());
    bool wait_result = shared_context_state_->gr_context()->wait(
        begin_semaphores.size(), begin_semaphores.data(),
        /*deleteSemaphoresAfterWait=*/false);
    DCHECK(wait_result);
  }
  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);
  representation->SetCleared();

  // 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());
    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();

  if (!end_semaphores.empty()) {
    // gr_context() must not be null when end_semaphores is not empty.
    DCHECK(shared_context_state_->gr_context());
    GrFlushInfo flush_info = {
        .fNumSemaphores = end_semaphores.size(),
        .fSignalSemaphores = end_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();
  }

  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
