// Copyright 2018 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/client/raster_implementation.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
#include <GLES3/gl3.h>
#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <array>
#include <limits>
#include <set>
#include <sstream>
#include <string>

#include "base/atomic_sequence_num.h"
#include "base/atomicops.h"
#include "base/bits.h"
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/stack_allocated.h"
#include "base/notimplemented.h"
#include "base/numerics/safe_math.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/paint/decode_stashing_image_provider.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_cache.h"
#include "cc/paint/paint_op_buffer_serializer.h"
#include "cc/paint/skottie_serialization_history.h"
#include "cc/paint/transfer_cache_entry.h"
#include "cc/paint/transfer_cache_serialize_helper.h"
#include "gpu/command_buffer/client/gpu_control.h"
#include "gpu/command_buffer/client/query_tracker.h"
#include "gpu/command_buffer/client/raster_cmd_helper.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"

#if defined(GPU_CLIENT_DEBUG)
#define GPU_CLIENT_SINGLE_THREAD_CHECK() SingleThreadChecker checker(this);
#else  // !defined(GPU_CLIENT_DEBUG)
#define GPU_CLIENT_SINGLE_THREAD_CHECK()
#endif  // defined(GPU_CLIENT_DEBUG)

// TODO(backer): Update APIs to always write to the destination? See below.
//
// Check that destination pointers point to initialized memory.
// When the context is lost, calling GL function has no effect so if destination
// pointers point to initialized memory it can often lead to crash bugs. eg.
//
// If it was up to us we'd just always write to the destination but the OpenGL
// spec defines the behavior of OpenGL functions, not us. :-(
#if defined(GPU_DCHECK)
#define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) GPU_DCHECK(v)
#define GPU_CLIENT_DCHECK(v) GPU_DCHECK(v)
#elif defined(DCHECK)
#define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) DCHECK(v)
#define GPU_CLIENT_DCHECK(v) DCHECK(v)
#else
#define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) ASSERT(v)
#define GPU_CLIENT_DCHECK(v) ASSERT(v)
#endif

#define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(type, ptr) \
  GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(          \
      ptr &&                                                     \
      (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1)));

#define GPU_CLIENT_VALIDATE_DESTINATION_OPTIONAL_INITALIZATION(type, ptr) \
  GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(                   \
      !ptr ||                                                             \
      (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1)));

using gpu::gles2::GLES2Util;

namespace gpu {
namespace raster {

namespace {

// TODO(crbug.com/40058879): Disable this work-around, once call-sites are
// handling failures correctly.
BASE_FEATURE(kDisableErrorHandlingForReadback,
             "kDisableErrorHandlingForReadback",
             base::FEATURE_ENABLED_BY_DEFAULT);

const uint32_t kMaxTransferCacheEntrySizeForTransferBuffer = 1024;
const size_t kMaxImmediateDeletedPaintCachePaths = 1024;
constexpr size_t kMaxImmediateDeletedPaintCacheEffects = 10u;

#define DEFINE_PAINT_CACHE_DELETION(                                     \
    IMMEDIATE_SIZE_CONSTANT, IMMEDIATE_FUNCTION, NON_IMMEDIATE_FUNCTION) \
  if (ids.size() <= IMMEDIATE_SIZE_CONSTANT) {                           \
    helper_->IMMEDIATE_FUNCTION(ids.size(), ids.data());                 \
  } else {                                                               \
    size_t data_size = ids.size() * sizeof(GLuint);                      \
    ScopedSharedMemoryPtr dest(data_size, transfer_buffer_,              \
                               mapped_memory_.get(), helper());          \
    if (dest.valid()) {                                                  \
      memcpy(dest.address(), ids.data(), data_size);                     \
      helper_->NON_IMMEDIATE_FUNCTION(ids.size(), dest.shm_id(),         \
                                      dest.offset());                    \
    } else {                                                             \
      SetGLError(GL_INVALID_OPERATION, "glDeletePaintCacheINTERNAL",     \
                 "couldn't allocate shared memory");                     \
    }                                                                    \
  }

class ScopedSharedMemoryPtr {
 public:
  ScopedSharedMemoryPtr(size_t size,
                        TransferBufferInterface* transfer_buffer,
                        MappedMemoryManager* mapped_memory,
                        RasterCmdHelper* helper) {
    // Prefer transfer buffer but fall back to MappedMemory if there's not
    // enough free space.
    if (transfer_buffer->GetFreeSize() < size) {
      scoped_mapped_ptr_.emplace(size, helper, mapped_memory);
    } else {
      scoped_transfer_ptr_.emplace(size, helper, transfer_buffer);
    }
  }
  ~ScopedSharedMemoryPtr() = default;

  GLuint size() {
    return scoped_transfer_ptr_ ? scoped_transfer_ptr_->size()
                                : scoped_mapped_ptr_->size();
  }

  GLint shm_id() {
    return scoped_transfer_ptr_ ? scoped_transfer_ptr_->shm_id()
                                : scoped_mapped_ptr_->shm_id();
  }

  GLuint offset() {
    return scoped_transfer_ptr_ ? scoped_transfer_ptr_->offset()
                                : scoped_mapped_ptr_->offset();
  }

  bool valid() {
    return scoped_transfer_ptr_ ? scoped_transfer_ptr_->valid()
                                : scoped_mapped_ptr_->valid();
  }

  void* address() {
    return scoped_transfer_ptr_ ? scoped_transfer_ptr_->address()
                                : scoped_mapped_ptr_->address();
  }

 private:
  std::optional<ScopedMappedMemoryPtr> scoped_mapped_ptr_;
  std::optional<ScopedTransferBufferPtr> scoped_transfer_ptr_;
};

}  // namespace

// Helper to copy data to the GPU service over the transfer cache.
class RasterImplementation::TransferCacheSerializeHelperImpl final
    : public cc::TransferCacheSerializeHelper {
 public:
  explicit TransferCacheSerializeHelperImpl(RasterImplementation* ri)
      : ri_(ri) {}

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

  ~TransferCacheSerializeHelperImpl() final = default;

  uint32_t take_end_offset_of_last_inlined_entry() {
    auto offset = end_offset_of_last_inlined_entry_;
    end_offset_of_last_inlined_entry_ = 0u;
    return offset;
  }

 private:
  bool LockEntryInternal(const EntryKey& key) final {
    return ri_->ThreadsafeLockTransferCacheEntry(
        static_cast<uint32_t>(key.first), key.second);
  }

  uint32_t CreateEntryInternal(const cc::ClientTransferCacheEntry& entry,
                               base::span<uint8_t> memory) final {
    uint32_t size = entry.SerializedSize();
    // Cap the entries inlined to a specific size.
    if (size <= ri_->max_inlined_entry_size_ && ri_->raster_mapped_buffer_) {
      uint32_t written = InlineEntry(entry, memory);
      if (written > 0u) {
        return written;
      }
    }

    base::span<uint8_t> data = ri_->MapTransferCacheEntry(size);
    if (data.empty()) {
      return 0u;
    }

    bool succeeded = entry.Serialize(data);
    DCHECK(succeeded);
    ri_->UnmapAndCreateTransferCacheEntry(entry.UnsafeType(), entry.Id());
    return 0u;
  }

  void FlushEntriesInternal(std::set<EntryKey> entries) final {
    std::vector<std::pair<uint32_t, uint32_t>> transformed;
    transformed.reserve(entries.size());
    for (const auto& e : entries) {
      transformed.emplace_back(static_cast<uint32_t>(e.first), e.second);
    }
    ri_->UnlockTransferCacheEntries(transformed);
  }

  // Writes the entry into `memory` if there is enough space. Returns the number
  // of bytes written on success or 0u on failure due to insufficient size.
  uint32_t InlineEntry(const cc::ClientTransferCacheEntry& entry,
                       base::span<uint8_t> memory) {
    DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory.data())));

    // The memory passed from the PaintOpWriter for inlining the transfer cache
    // entry must be from the transfer buffer mapped during RasterCHROMIUM.
    const auto& buffer = ri_->raster_mapped_buffer_;
    DCHECK(buffer->BelongsToBuffer(memory.data()));

    base::span<const uint8_t> buffer_span = buffer->as_byte_span();
    DCHECK(base::CheckedNumeric<uint32_t>(memory.data() - buffer_span.data())
               .IsValid());
    uint32_t memory_offset = memory.data() - buffer_span.data();
    uint32_t bytes_to_write = entry.SerializedSize();
    DCHECK_GT(bytes_to_write, 0u);

    if (bytes_to_write > memory.size()) {
      return 0u;
    }

    bool succeeded = entry.Serialize(memory.first(bytes_to_write));
    DCHECK(succeeded);
    ri_->transfer_cache_.AddTransferCacheEntry(
        entry.UnsafeType(), entry.Id(), buffer->shm_id(),
        buffer->offset() + memory_offset, bytes_to_write);

    end_offset_of_last_inlined_entry_ = memory_offset + bytes_to_write;
    return bytes_to_write;
  }

  const raw_ptr<RasterImplementation> ri_;
  uint32_t end_offset_of_last_inlined_entry_ = 0u;
};

// Helper to copy PaintOps to the GPU service over the transfer buffer.
class RasterImplementation::PaintOpSerializer {
  STACK_ALLOCATED();

 public:
  PaintOpSerializer(uint32_t initial_size,
                    RasterImplementation* ri,
                    cc::DecodeStashingImageProvider* stashing_image_provider,
                    TransferCacheSerializeHelperImpl* transfer_cache_helper,
                    ClientFontManager* font_manager,
                    size_t* max_op_size_hint)
      : ri_(ri),
        stashing_image_provider_(stashing_image_provider),
        transfer_cache_helper_(transfer_cache_helper),
        font_manager_(font_manager),
        max_op_size_hint_(max_op_size_hint) {
    buffer_ = ri_->MapRasterCHROMIUM(initial_size);
  }

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

  ~PaintOpSerializer() {
    // Need to call SendSerializedData;
    DCHECK(!written_bytes_);
  }

  size_t SerializeImpl(const cc::PaintOp& op,
                       const cc::PaintOp::SerializeOptions& options,
                       const cc::PaintFlags* flags_to_serialize,
                       const SkM44& current_ctm,
                       const SkM44& original_ctm) {
    if (!valid()) {
      return 0;
    }

    size_t size = op.Serialize(buffer_.subspan(written_bytes_), options,
                               flags_to_serialize, current_ctm, original_ctm);
    size_t block_size = *max_op_size_hint_;

    if (!size) {
      // The entries serialized for |op| above will not be transferred since the
      // op will be re-serialized once the buffer is remapped.
      ri_->paint_cache_->AbortPendingEntries();
      SendSerializedData();

      const unsigned int max_size = ri_->transfer_buffer_->GetMaxSize();
      DCHECK_LE(block_size, max_size);
      while (true) {
        buffer_ = ri_->MapRasterCHROMIUM(block_size);
        if (buffer_.empty()) {
          return 0;
        }

        size = op.Serialize(buffer_.subspan(written_bytes_), options,
                            flags_to_serialize, current_ctm, original_ctm);
        if (size) {
          *max_op_size_hint_ = std::max(size, *max_op_size_hint_);
          break;
        }

        ri_->paint_cache_->AbortPendingEntries();
        ri_->UnmapRasterCHROMIUM(0u, 0u);

        if (block_size == max_size) {
          break;
        }
        block_size = std::min(block_size * 2, static_cast<size_t>(max_size));
      }

      if (!size) {
        LOG(ERROR) << "Failed to serialize op in " << block_size << " bytes.";
        return 0u;
      }
    }

    DCHECK_LE(size, buffer_.size() - written_bytes_);
    DCHECK(base::CheckAdd<uint32_t>(written_bytes_, size).IsValid());

    ri_->paint_cache_->FinalizePendingEntries();
    written_bytes_ += size;
    return size;
  }

  static size_t Serialize(void* instance,
                          const cc::PaintOp& op,
                          const cc::PaintOp::SerializeOptions& options,
                          const cc::PaintFlags* flags_to_serialize,
                          const SkM44& current_ctm,
                          const SkM44& original_ctm) {
    return reinterpret_cast<PaintOpSerializer*>(instance)->SerializeImpl(
        op, options, flags_to_serialize, current_ctm, original_ctm);
  }

  void SendSerializedData() {
    if (!valid()) {
      return;
    }

    // Serialize fonts before sending raster commands.
    font_manager_->Serialize();

    // Check the address of the last inlined entry to figured out whether
    // transfer cache entries were written past the last successfully serialized
    // op.
    uint32_t total_written_size = std::max(
        written_bytes_,
        transfer_cache_helper_->take_end_offset_of_last_inlined_entry());

    // Send the raster command itself now that the commands for its
    // dependencies have been sent.
    ri_->UnmapRasterCHROMIUM(written_bytes_, total_written_size);

    // Now that we've issued the RasterCHROMIUM referencing the stashed
    // images, Reset the |stashing_image_provider_|, causing us to issue
    // unlock commands for these images.
    stashing_image_provider_->Reset();

    // Unlock all the transfer cache entries used (both immediate and deferred).
    transfer_cache_helper_->FlushEntries();
    written_bytes_ = 0;
  }

  bool valid() const { return !buffer_.empty(); }

 private:
  RasterImplementation* const ri_ = nullptr;
  base::span<uint8_t> buffer_;
  cc::DecodeStashingImageProvider* const stashing_image_provider_ = nullptr;
  TransferCacheSerializeHelperImpl* const transfer_cache_helper_ = nullptr;
  ClientFontManager* font_manager_ = nullptr;

  uint32_t written_bytes_ = 0;

  size_t* max_op_size_hint_ = nullptr;
};

RasterImplementation::SingleThreadChecker::SingleThreadChecker(
    RasterImplementation* raster_implementation)
    : raster_implementation_(raster_implementation) {
  CHECK_EQ(0, raster_implementation_->use_count_);
  ++raster_implementation_->use_count_;
}

RasterImplementation::SingleThreadChecker::~SingleThreadChecker() {
  --raster_implementation_->use_count_;
  CHECK_EQ(0, raster_implementation_->use_count_);
}

struct RasterImplementation::AsyncARGBReadbackRequest {
  AsyncARGBReadbackRequest(void* dst_pixels,
                           const SkImageInfo& dst_info,
                           GLuint dst_row_bytes,
                           GLuint pixels_offset,
                           GLuint finished_query,
                           std::unique_ptr<ScopedMappedMemoryPtr> shared_memory,
                           base::OnceCallback<void(bool)> callback)
      : dst_pixels(dst_pixels),
        dst_info(dst_info),
        dst_row_bytes(dst_row_bytes),
        pixels_offset(pixels_offset),
        shared_memory(std::move(shared_memory)),
        callback(std::move(callback)),
        query(finished_query),
        done(false),
        readback_successful(false) {}
  ~AsyncARGBReadbackRequest() {
    // Sometimes `callback` owns `dst_pixels`, this prevents dangling raw ptr
    dst_pixels = nullptr;
    std::move(callback).Run(readback_successful);
  }

  raw_ptr<void> dst_pixels;
  SkImageInfo dst_info;
  GLuint dst_row_bytes;
  GLuint pixels_offset;
  std::unique_ptr<ScopedMappedMemoryPtr> shared_memory;
  base::OnceCallback<void(bool)> callback;
  GLuint query;
  bool done;
  bool readback_successful;
};

struct RasterImplementation::AsyncYUVReadbackRequest {
  AsyncYUVReadbackRequest(gfx::Rect output_rect,
                          GLuint query,
                          int y_plane_stride,
                          GLuint y_plane_offset,
                          uint8_t* y_plane_data,
                          int u_plane_stride,
                          GLuint u_plane_offset,
                          uint8_t* u_plane_data,
                          int v_plane_stride,
                          GLuint v_plane_offset,
                          uint8_t* v_plane_data,
                          std::unique_ptr<ScopedMappedMemoryPtr> shared_memory,
                          base::OnceCallback<void()> release_mailbox,
                          base::OnceCallback<void(bool)> readback_done)
      : output_rect(output_rect),
        query(query),
        y_plane_stride(y_plane_stride),
        y_plane_offset(y_plane_offset),
        y_plane_data(y_plane_data),
        u_plane_stride(u_plane_stride),
        u_plane_offset(u_plane_offset),
        u_plane_data(u_plane_data),
        v_plane_stride(v_plane_stride),
        v_plane_offset(v_plane_offset),
        v_plane_data(v_plane_data),
        shared_memory(std::move(shared_memory)),
        release_mailbox(std::move(release_mailbox)),
        readback_done(std::move(readback_done)) {}
  ~AsyncYUVReadbackRequest() {
    // Sometimes `callback` owns plane ptrs, this prevents dangling raw ptrs
    y_plane_data = nullptr;
    u_plane_data = nullptr;
    v_plane_data = nullptr;
    std::move(release_mailbox).Run();
    std::move(readback_done).Run(readback_successful);
  }

  void CopyYUVPlanes() {
    void* shm_address = shared_memory->address();
    auto* result =
        static_cast<cmds::ReadbackYUVImagePixelsINTERNALImmediate::Result*>(
            shm_address);
    if (!*result) {
      return;
    }

    CopyYUVPlane(output_rect.width(), output_rect.height(), y_plane_stride,
                 y_plane_offset, shm_address, y_plane_data);

    // U and V planes are half the size of the Y plane.
    CopyYUVPlane(output_rect.width() / 2, output_rect.height() / 2,
                 u_plane_stride, u_plane_offset, shm_address, u_plane_data);
    CopyYUVPlane(output_rect.width() / 2, output_rect.height() / 2,
                 v_plane_stride, v_plane_offset, shm_address, v_plane_data);

    readback_successful = true;
  }

  const gfx::Rect output_rect;
  GLuint query;

  int y_plane_stride;
  GLuint y_plane_offset;
  raw_ptr<uint8_t> y_plane_data;

  int u_plane_stride;
  GLuint u_plane_offset;
  raw_ptr<uint8_t> u_plane_data;

  int v_plane_stride;
  GLuint v_plane_offset;
  raw_ptr<uint8_t> v_plane_data;

  std::unique_ptr<ScopedMappedMemoryPtr> shared_memory;
  base::OnceCallback<void()> release_mailbox;
  base::OnceCallback<void(bool)> readback_done;

  bool done = false;
  bool readback_successful = false;

 private:
  void CopyYUVPlane(GLuint plane_width,
                    GLuint plane_height,
                    int plane_stride,
                    GLuint plane_offset,
                    void* in_buffer,
                    uint8_t* out_buffer) {
    // RasterDecoder writes the pixels into |in_buffer| with the requested
    // stride so we can copy the whole block here.
    size_t plane_size = plane_height * plane_stride;
    auto dst = UNSAFE_TODO(base::span(out_buffer, plane_size));
    auto src = UNSAFE_TODO(base::span(
        static_cast<uint8_t*>(in_buffer) + plane_offset, plane_size));
    RelaxedAtomicWriteMemcpyImageRowsSkippingPadding(
        /*dst=*/dst, /*src=*/src, /*row_bytes=*/plane_width,
        /*height=*/plane_height, /*stride=*/plane_stride);
  }
};

RasterImplementation::RasterImplementation(
    RasterCmdHelper* helper,
    TransferBufferInterface* transfer_buffer,
    bool lose_context_when_out_of_memory,
    GpuControl* gpu_control)
    : ImplementationBase(helper, transfer_buffer, gpu_control),
      helper_(helper),
      error_bits_(0),
      lose_context_when_out_of_memory_(lose_context_when_out_of_memory),
      use_count_(0),
      current_trace_stack_(0),
      aggressively_free_resources_(false),
      font_manager_(this, helper->command_buffer()),
      lost_(false),
      max_inlined_entry_size_(kMaxTransferCacheEntrySizeForTransferBuffer),
      transfer_cache_(this) {
  DCHECK(helper);
  DCHECK(transfer_buffer);
  DCHECK(gpu_control);

  std::stringstream ss;
  ss << std::hex << this;
  this_in_hex_ = ss.str();
}

gpu::ContextResult RasterImplementation::Initialize(
    const SharedMemoryLimits& limits) {
  TRACE_EVENT0("gpu", "RasterImplementation::Initialize");

  auto result = ImplementationBase::Initialize(limits);
  if (result != gpu::ContextResult::kSuccess) {
    return result;
  }

  return gpu::ContextResult::kSuccess;
}

RasterImplementation::~RasterImplementation() {
  // Make sure the queries are finished otherwise we'll delete the
  // shared memory (mapped_memory_) which will free the memory used
  // by the queries. The GPU process when validating that memory is still
  // shared will fail and abort (ie, it will stop running).
  WaitForCmd();

  // Run callbacks for all pending AsyncReadbackRequests to inform them of the
  // failure
  CancelRequests();
  query_tracker_.reset();

  // Make sure the commands make it the service.
  WaitForCmd();
}

RasterCmdHelper* RasterImplementation::helper() const {
  return helper_;
}

IdAllocator* RasterImplementation::GetIdAllocator(IdNamespaces namespace_id) {
  DCHECK_EQ(namespace_id, IdNamespaces::kQueries);
  return &query_id_allocator_;
}

void RasterImplementation::OnGpuControlLostContext() {
  OnGpuControlLostContextMaybeReentrant();

  // This should never occur more than once.
  DCHECK(!lost_context_callback_run_);
  lost_context_callback_run_ = true;
  if (!lost_context_callback_.is_null()) {
    std::move(lost_context_callback_).Run();
  }
}

void RasterImplementation::OnGpuControlLostContextMaybeReentrant() {
  {
    base::AutoLock hold(lost_lock_);
    lost_ = true;
  }
}

void RasterImplementation::OnGpuControlErrorMessage(const char* message,
                                                    int32_t id) {
  if (!error_message_callback_.is_null()) {
    error_message_callback_.Run(message, id);
  }
}

void RasterImplementation::OnGpuControlReturnData(
    base::span<const uint8_t> data) {
  NOTIMPLEMENTED();
}

void RasterImplementation::SetAggressivelyFreeResources(
    bool aggressively_free_resources) {
  TRACE_EVENT1("gpu", "RasterImplementation::SetAggressivelyFreeResources",
               "aggressively_free_resources", aggressively_free_resources);
  aggressively_free_resources_ = aggressively_free_resources;

  if (aggressively_free_resources_) {
    ClearPaintCache();
  }

  if (aggressively_free_resources_ && helper_->HaveRingBuffer()) {
    // Flush will delete transfer buffer resources if
    // |aggressively_free_resources_| is true.
    Flush();
  } else {
    ShallowFlushCHROMIUM();
  }

  if (aggressively_free_resources_) {
    temp_raster_offsets_.clear();
    temp_raster_offsets_.shrink_to_fit();
  }
}

void RasterImplementation::SetErrorMessageCallback(
    base::RepeatingCallback<void(const char*, int32_t)> callback) {
  error_message_callback_ = std::move(callback);
}

base::span<uint8_t> RasterImplementation::MapTransferCacheEntry(
    uint32_t serialized_size) {
  // Prefer to use transfer buffer when possible, since transfer buffer
  // allocations are much cheaper.
  if (raster_mapped_buffer_ ||
      transfer_buffer_->GetFreeSize() < serialized_size) {
    return transfer_cache_.MapEntry(mapped_memory_.get(), serialized_size);
  }

  return transfer_cache_.MapTransferBufferEntry(transfer_buffer_,
                                                serialized_size);
}

void RasterImplementation::UnmapAndCreateTransferCacheEntry(uint32_t type,
                                                            uint32_t id) {
  transfer_cache_.UnmapAndCreateEntry(type, id);
}

bool RasterImplementation::ThreadsafeLockTransferCacheEntry(uint32_t type,
                                                            uint32_t id) {
  return transfer_cache_.LockEntry(type, id);
}

void RasterImplementation::UnlockTransferCacheEntries(
    const std::vector<std::pair<uint32_t, uint32_t>>& entries) {
  transfer_cache_.UnlockEntries(entries);
}

void RasterImplementation::DeleteTransferCacheEntry(uint32_t type,
                                                    uint32_t id) {
  transfer_cache_.DeleteEntry(type, id);
}

unsigned int RasterImplementation::GetTransferBufferFreeSize() const {
  return transfer_buffer_->GetFreeSize();
}

const std::string& RasterImplementation::GetLogPrefix() const {
  const std::string& prefix(debug_marker_manager_.GetMarker());
  return prefix.empty() ? this_in_hex_ : prefix;
}

GLenum RasterImplementation::GetError() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
  GLenum err = GetGLError();
  GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err));
  return err;
}

void RasterImplementation::IssueBeginQuery(GLenum target,
                                           GLuint id,
                                           uint32_t sync_data_shm_id,
                                           uint32_t sync_data_shm_offset) {
  helper_->BeginQueryEXT(target, id, sync_data_shm_id, sync_data_shm_offset);
}

void RasterImplementation::IssueEndQuery(GLenum target, GLuint submit_count) {
  helper_->EndQueryEXT(target, submit_count);
}

void RasterImplementation::IssueQueryCounter(GLuint id,
                                             GLenum target,
                                             uint32_t sync_data_shm_id,
                                             uint32_t sync_data_shm_offset,
                                             GLuint submit_count) {
  // This callback is invoked only by QueryTracker::QueryCounter(), which
  // RasterImplementation never calls.
  NOTREACHED();
}

void RasterImplementation::IssueSetDisjointValueSync(
    uint32_t sync_data_shm_id,
    uint32_t sync_data_shm_offset) {
  NOTIMPLEMENTED();
}

GLenum RasterImplementation::GetClientSideGLError() {
  if (error_bits_ == 0) {
    return GL_NO_ERROR;
  }

  GLenum error = GL_NO_ERROR;
  for (uint32_t mask = 1; mask != 0; mask = mask << 1) {
    if ((error_bits_ & mask) != 0) {
      error = GLES2Util::GLErrorBitToGLError(mask);
      break;
    }
  }
  error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
  return error;
}

CommandBufferHelper* RasterImplementation::cmd_buffer_helper() {
  return helper_;
}

void RasterImplementation::IssueCreateTransferCacheEntry(
    GLuint entry_type,
    GLuint entry_id,
    GLuint handle_shm_id,
    GLuint handle_shm_offset,
    GLuint data_shm_id,
    GLuint data_shm_offset,
    GLuint data_size) {
  helper_->CreateTransferCacheEntryINTERNAL(entry_type, entry_id, handle_shm_id,
                                            handle_shm_offset, data_shm_id,
                                            data_shm_offset, data_size);
}

void RasterImplementation::IssueDeleteTransferCacheEntry(GLuint entry_type,
                                                         GLuint entry_id) {
  helper_->DeleteTransferCacheEntryINTERNAL(entry_type, entry_id);
}

void RasterImplementation::IssueUnlockTransferCacheEntry(GLuint entry_type,
                                                         GLuint entry_id) {
  helper_->UnlockTransferCacheEntryINTERNAL(entry_type, entry_id);
}

CommandBuffer* RasterImplementation::command_buffer() const {
  return helper_->command_buffer();
}

GLenum RasterImplementation::GetGLError() {
  TRACE_EVENT0("gpu", "RasterImplementation::GetGLError");
  // Check the GL error first, then our wrapped error.
  auto result = GetResultAs<cmds::GetError::Result>();
  // If we couldn't allocate a result the context is lost.
  if (!result) {
    return GL_NO_ERROR;
  }
  *result = GL_NO_ERROR;
  helper_->GetError(GetResultShmId(), result.offset());
  WaitForCmd();
  GLenum error = *result;
  if (error == GL_NO_ERROR) {
    error = GetClientSideGLError();
  } else {
    // There was an error, clear the corresponding wrapped error.
    error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
  }
  return error;
}

#if defined(RASTER_CLIENT_FAIL_GL_ERRORS)
void RasterImplementation::FailGLError(GLenum error) {
  if (error != GL_NO_ERROR) {
    NOTREACHED() << "Error:" << error;
  }
}
// NOTE: Calling GetGLError overwrites data in the result buffer.
void RasterImplementation::CheckGLError() {
  FailGLError(GetGLError());
}
#endif  // defined(RASTER_CLIENT_FAIL_GL_ERRORS)

void RasterImplementation::SetGLError(GLenum error,
                                      const char* function_name,
                                      const char* msg) {
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
                     << GLES2Util::GetStringError(error) << ": "
                     << function_name << ": " << msg);
  FailGLError(error);
  if (msg) {
    last_error_ = msg;
  }
  if (!error_message_callback_.is_null()) {
    std::string temp(GLES2Util::GetStringError(error) + " : " + function_name +
                     ": " + (msg ? msg : ""));
    error_message_callback_.Run(temp.c_str(), 0);
  }
  error_bits_ |= GLES2Util::GLErrorToErrorBit(error);

  if (error == GL_OUT_OF_MEMORY && lose_context_when_out_of_memory_) {
    helper_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
                                 GL_UNKNOWN_CONTEXT_RESET_ARB);
  }
}

void RasterImplementation::SetGLErrorInvalidEnum(const char* function_name,
                                                 GLenum value,
                                                 const char* label) {
  SetGLError(
      GL_INVALID_ENUM, function_name,
      (std::string(label) + " was " + GLES2Util::GetStringEnum(value)).c_str());
}

bool RasterImplementation::GetQueryObjectValueHelper(const char* function_name,
                                                     GLuint id,
                                                     GLenum pname,
                                                     GLuint64* params) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper(" << id
                     << ", " << GLES2Util::GetStringQueryObjectParameter(pname)
                     << ", " << static_cast<const void*>(params) << ")");

  gles2::QueryTracker::Query* query = query_tracker_->GetQuery(id);
  if (!query) {
    SetGLError(GL_INVALID_OPERATION, function_name, "unknown query id");
    return false;
  }

  if (query->Active()) {
    SetGLError(GL_INVALID_OPERATION, function_name,
               "query active. Did you call glEndQueryEXT?");
    return false;
  }

  if (query->NeverUsed()) {
    SetGLError(GL_INVALID_OPERATION, function_name,
               "Never used. Did you call glBeginQueryEXT?");
    return false;
  }

  bool valid_value = false;
  const bool flush_if_pending =
      pname != GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT;
  switch (pname) {
    case GL_QUERY_RESULT_EXT:
      if (!query->CheckResultsAvailable(helper_, flush_if_pending)) {
        helper_->WaitForToken(query->token());
        if (!query->CheckResultsAvailable(helper_, flush_if_pending)) {
          FinishHelper();
          CHECK(query->CheckResultsAvailable(helper_, flush_if_pending));
        }
      }
      *params = query->GetResult();
      valid_value = true;
      break;
    case GL_QUERY_RESULT_AVAILABLE_EXT:
    case GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT:
      *params = query->CheckResultsAvailable(helper_, flush_if_pending);
      valid_value = true;
      break;
    default:
      SetGLErrorInvalidEnum(function_name, pname, "pname");
      break;
  }
  GPU_CLIENT_LOG("  " << *params);
  CheckGLError();
  return valid_value;
}

void RasterImplementation::Flush() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
  // Insert the cmd to call glFlush
  helper_->Flush();
  FlushHelper();
}

// InterfaceBase implementation.
void RasterImplementation::GenSyncTokenCHROMIUM(GLbyte* sync_token) {
  ImplementationBase::GenSyncToken(sync_token);
}
void RasterImplementation::GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) {
  ImplementationBase::GenUnverifiedSyncToken(sync_token);
}
void RasterImplementation::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
                                                    GLsizei count) {
  ImplementationBase::VerifySyncTokens(sync_tokens, count);
}
void RasterImplementation::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) {
  ImplementationBase::WaitSyncToken(sync_token);
}
void RasterImplementation::ShallowFlushCHROMIUM() {
  IssueShallowFlush();
}

// ImplementationBase implementation.
void RasterImplementation::IssueShallowFlush() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
  FlushHelper();
}

void RasterImplementation::FlushHelper() {
  // Flush our command buffer
  // (tell the service to execute up to the flush cmd.)
  helper_->CommandBufferHelper::Flush();

  if (aggressively_free_resources_) {
    FreeEverything();
  }
}

void RasterImplementation::OrderingBarrierCHROMIUM() {
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
  // Flush command buffer at the GPU channel level.  May be implemented as
  // Flush().
  helper_->CommandBufferHelper::OrderingBarrier();
}

void RasterImplementation::Finish() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  FinishHelper();
}

void RasterImplementation::FinishHelper() {
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
  TRACE_EVENT0("gpu", "RasterImplementation::Finish");
  // Insert the cmd to call glFinish
  helper_->Finish();
  // Finish our command buffer
  // (tell the service to execute up to the Finish cmd and wait for it to
  // execute.)
  helper_->CommandBufferHelper::Finish();

  if (aggressively_free_resources_) {
    FreeEverything();
  }
}

void RasterImplementation::GenQueriesEXTHelper(GLsizei /* n */,
                                               const GLuint* /* queries */) {}

GLenum RasterImplementation::GetGraphicsResetStatusKHR() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");

  base::AutoLock hold(lost_lock_);
  if (lost_) {
    return GL_UNKNOWN_CONTEXT_RESET_KHR;
  }
  return GL_NO_ERROR;
}

void RasterImplementation::DeleteQueriesEXTHelper(GLsizei n,
                                                  const GLuint* queries) {
  IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::kQueries);
  for (GLsizei ii = 0; ii < n; ++ii) {
    query_tracker_->RemoveQuery(UNSAFE_TODO(queries[ii]));
    id_allocator->FreeID(UNSAFE_TODO(queries[ii]));
  }

  helper_->DeleteQueriesEXTImmediate(n, queries);
}

void RasterImplementation::BeginQueryEXT(GLenum target, GLuint id) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
                     << GLES2Util::GetStringQueryTarget(target) << ", " << id
                     << ")");

  switch (target) {
    case GL_COMMANDS_ISSUED_CHROMIUM:
      break;
    case GL_COMMANDS_COMPLETED_CHROMIUM:
      if (!capabilities_.sync_query) {
        SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
                   "not enabled for commands completed queries");
        return;
      }
      break;
    default:
      SetGLError(GL_INVALID_ENUM, "glBeginQueryEXT", "unknown query target");
      return;
  }

  // if any outstanding queries INV_OP
  if (query_tracker_->GetCurrentQuery(target)) {
    SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
               "query already in progress");
    return;
  }

  if (id == 0) {
    SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
    return;
  }

  if (!GetIdAllocator(IdNamespaces::kQueries)->InUse(id)) {
    SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "invalid id");
    return;
  }

  if (query_tracker_->BeginQuery(id, target, this)) {
    CheckGLError();
  }
}

void RasterImplementation::EndQueryEXT(GLenum target) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
                     << GLES2Util::GetStringQueryTarget(target) << ")");
  if (query_tracker_->EndQuery(target, this)) {
    CheckGLError();
  }
}

void RasterImplementation::GetQueryObjectuivEXT(GLuint id,
                                                GLenum pname,
                                                GLuint* params) {
  GLuint64 result = 0;
  if (GetQueryObjectValueHelper("glGetQueryObjectuivEXT", id, pname, &result)) {
    *params = base::saturated_cast<GLuint>(result);
  }
}

base::span<uint8_t> RasterImplementation::MapRasterCHROMIUM(uint32_t size) {
  if (raster_mapped_buffer_) {
    SetGLError(GL_INVALID_OPERATION, "glMapRasterCHROMIUM", "already mapped");
    return {};
  }
  raster_mapped_buffer_.emplace(size, helper_, transfer_buffer_);
  if (!raster_mapped_buffer_->valid()) {
    SetGLError(GL_INVALID_OPERATION, "glMapRasterCHROMIUM", "size too big");
    raster_mapped_buffer_ = std::nullopt;
    return {};
  }
  return raster_mapped_buffer_->as_byte_span();
}

base::span<uint8_t> RasterImplementation::MapFontBuffer(uint32_t size) {
  DCHECK(size > 0);
  if (font_mapped_buffer_) {
    SetGLError(GL_INVALID_OPERATION, "glMapFontBufferCHROMIUM",
               "already mapped");
    return {};
  }
  if (!raster_mapped_buffer_) {
    SetGLError(GL_INVALID_OPERATION, "glMapFontBufferCHROMIUM",
               "mapped font buffer with no raster buffer");
    return {};
  }

  font_mapped_buffer_.emplace(size, helper_, mapped_memory_.get());
  if (!font_mapped_buffer_->valid()) {
    SetGLError(GL_INVALID_OPERATION, "glMapFontBufferCHROMIUM", "size too big");
    font_mapped_buffer_ = std::nullopt;
    return {};
  }

  return font_mapped_buffer_->as_byte_span();
}

void RasterImplementation::UnmapRasterCHROMIUM(uint32_t raster_written_size,
                                               uint32_t total_written_size) {
  if (!raster_mapped_buffer_) {
    SetGLError(GL_INVALID_OPERATION, "glUnmapRasterCHROMIUM", "not mapped");
    return;
  }
  DCHECK(raster_mapped_buffer_->valid());
  if (total_written_size == 0) {
    raster_mapped_buffer_->Discard();
    raster_mapped_buffer_ = std::nullopt;
    return;
  }
  raster_mapped_buffer_->Shrink(total_written_size);

  uint32_t font_shm_id = 0u;
  uint32_t font_shm_offset = 0u;
  uint32_t font_shm_size = 0u;
  if (font_mapped_buffer_) {
    font_shm_id = font_mapped_buffer_->shm_id();
    font_shm_offset = font_mapped_buffer_->offset();
    font_shm_size = font_mapped_buffer_->size();
  }

  if (raster_written_size != 0u) {
    helper_->RasterCHROMIUM(
        raster_mapped_buffer_->shm_id(), raster_mapped_buffer_->offset(),
        raster_written_size, font_shm_id, font_shm_offset, font_shm_size);
  }

  raster_mapped_buffer_ = std::nullopt;
  font_mapped_buffer_ = std::nullopt;
  CheckGLError();
}

// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
#include "gpu/command_buffer/client/raster_implementation_impl_autogen.h"

const Capabilities& RasterImplementation::GetCapabilities() const {
  return capabilities();
}

void RasterImplementation::CopySharedImage(const gpu::Mailbox& source_mailbox,
                                           const gpu::Mailbox& dest_mailbox,
                                           GLint xoffset,
                                           GLint yoffset,
                                           GLint x,
                                           GLint y,
                                           GLsizei width,
                                           GLsizei height) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopySharedImage("
                     << source_mailbox.ToDebugString() << ", "
                     << dest_mailbox.ToDebugString() << ", " << xoffset << ", "
                     << yoffset << ", " << x << ", " << y << ", " << width
                     << ", " << height << ")");
  if (width < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "width < 0");
    return;
  }
  if (height < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "height < 0");
    return;
  }
  GLbyte mailboxes[sizeof(source_mailbox.name) * 2];
  UNSAFE_TODO(
      memcpy(mailboxes, source_mailbox.name, sizeof(source_mailbox.name)));
  UNSAFE_TODO(memcpy(mailboxes + sizeof(source_mailbox.name), dest_mailbox.name,
                     sizeof(dest_mailbox.name)));
  helper_->CopySharedImageINTERNALImmediate(xoffset, yoffset, x, y, width,
                                            height, width, height, mailboxes);
  CheckGLError();
}

void RasterImplementation::CopySharedImage(const gpu::Mailbox& source_mailbox,
                                           const gpu::Mailbox& dest_mailbox,
                                           const gfx::Rect& source_rect,
                                           const gfx::Rect& dest_rect) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopySharedImage("
                     << source_mailbox.ToDebugString() << ", "
                     << dest_mailbox.ToDebugString() << ", "
                     << source_rect.ToString() << ", " << dest_rect.ToString()
                     << ")");
  if (source_rect.width() < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "src_width < 0");
    return;
  }
  if (source_rect.height() < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "src_height < 0");
    return;
  }
  if (dest_rect.width() < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "dst_width < 0");
    return;
  }
  if (dest_rect.height() < 0) {
    SetGLError(GL_INVALID_VALUE, "glCopySharedImage", "dst_height < 0");
    return;
  }
  GLbyte mailboxes[sizeof(source_mailbox.name) * 2];
  UNSAFE_TODO(
      memcpy(mailboxes, source_mailbox.name, sizeof(source_mailbox.name)));
  UNSAFE_TODO(memcpy(mailboxes + sizeof(source_mailbox.name), dest_mailbox.name,
                     sizeof(dest_mailbox.name)));
  helper_->CopySharedImageINTERNALImmediate(
      dest_rect.x(), dest_rect.y(), source_rect.x(), source_rect.y(),
      source_rect.width(), source_rect.height(), dest_rect.width(),
      dest_rect.height(), mailboxes);
  CheckGLError();
}

void RasterImplementation::WritePixels(const gpu::Mailbox& dest_mailbox,
                                       int dst_x_offset,
                                       int dst_y_offset,
                                       GLenum texture_target,
                                       const SkPixmap& src_sk_pixmap) {
  TRACE_EVENT0("gpu", "RasterImplementation::WritePixels");
  const auto& src_info = src_sk_pixmap.info();
  const auto& src_row_bytes = src_sk_pixmap.rowBytes();
  DCHECK_GE(src_row_bytes, src_info.minRowBytes());

  // Get the size of the SkColorSpace while maintaining 8-byte alignment.
  GLuint pixels_offset = 0;
  if (src_info.colorSpace()) {
    pixels_offset = base::bits::AlignUp(
        src_info.colorSpace()->writeToMemory(nullptr), sizeof(uint64_t));
  }

  GLuint src_size = src_sk_pixmap.computeByteSize();
  GLuint total_size =
      pixels_offset +
      base::bits::AlignUp(src_size, static_cast<GLuint>(sizeof(uint64_t)));

  std::unique_ptr<ScopedSharedMemoryPtr> scoped_shared_memory =
      std::make_unique<ScopedSharedMemoryPtr>(total_size, transfer_buffer_,
                                              mapped_memory_.get(), helper());

  if (!scoped_shared_memory->valid()) {
    SetGLError(GL_INVALID_OPERATION, "WritePixels", "size too big");
    return;
  }

  GLint shm_id = scoped_shared_memory->shm_id();
  GLuint shm_offset = scoped_shared_memory->offset();
  void* address = scoped_shared_memory->address();

  if (src_info.colorSpace()) {
    size_t bytes_written = src_info.colorSpace()->writeToMemory(address);
    DCHECK_LE(bytes_written, pixels_offset);
  }
  UNSAFE_TODO(memcpy(static_cast<uint8_t*>(address) + pixels_offset,
                     src_sk_pixmap.addr(), src_size));

  helper_->WritePixelsINTERNALImmediate(
      dst_x_offset, dst_y_offset, src_info.width(), src_info.height(),
      src_row_bytes, src_info.colorType(), src_info.alphaType(), shm_id,
      shm_offset, pixels_offset, dest_mailbox.name);
}

void RasterImplementation::WritePixelsYUV(const gpu::Mailbox& dest_mailbox,
                                          const SkYUVAPixmaps& src_yuv_pixmap) {
  TRACE_EVENT0("gpu", "RasterImplementation::WritePixelsYUV");
  if (!capabilities().texture_rg) {
    SetGLError(GL_INVALID_OPERATION, "WritePixelsYUV", "unsupported");
    return;
  }

  const auto& src_yuv_info = src_yuv_pixmap.yuvaInfo();
  const auto& src_yuv_pixmap_info = src_yuv_pixmap.pixmapsInfo();
  const std::array<SkPixmap, SkYUVAInfo::kMaxPlanes>& src_sk_pixmaps =
      src_yuv_pixmap.planes();

  GLuint total_size = 0;
  for (int plane = 0; plane < src_yuv_info.numPlanes(); plane++) {
    CHECK(src_sk_pixmaps[plane].addr());
    total_size += base::bits::AlignUp(src_sk_pixmaps[plane].computeByteSize(),
                                      sizeof(uint64_t));
  }

  ScopedSharedMemoryPtr scoped_shared_memory(total_size, transfer_buffer_,
                                             mapped_memory_.get(), helper());
  if (!scoped_shared_memory.valid()) {
    SetGLError(GL_INVALID_OPERATION, "WritePixelsYUV", "size too big");
    return;
  }

  GLint shm_id = scoped_shared_memory.shm_id();
  GLuint shm_offset = scoped_shared_memory.offset();
  void* address = scoped_shared_memory.address();

  // Copy the pixels for first plane at `address`.
  CHECK(src_sk_pixmaps[0].addr());
  UNSAFE_TODO(memcpy(static_cast<uint8_t*>(address), src_sk_pixmaps[0].addr(),
                     src_sk_pixmaps[0].computeByteSize()));

  std::array<GLuint, SkYUVAInfo::kMaxPlanes> plane_offsets = {};
  for (int plane = 1; plane < src_yuv_info.numPlanes(); plane++) {
    CHECK(src_sk_pixmaps[plane].addr());
    // Calculate the offset based on previous plane offset and previous plane
    // size, and copy pixels for current plane starting at current plane
    // offset.
    GLuint prev_plane_size = src_sk_pixmaps[plane - 1].computeByteSize();
    plane_offsets[plane] =
        plane_offsets[plane - 1] +
        base::bits::AlignUp(prev_plane_size,
                            static_cast<GLuint>(sizeof(uint64_t)));
    UNSAFE_TODO(memcpy(static_cast<uint8_t*>(address) + plane_offsets[plane],
                       src_sk_pixmaps[plane].addr(),
                       src_sk_pixmaps[plane].computeByteSize()));
  }

  helper_->WritePixelsYUVINTERNALImmediate(
      src_yuv_info.width(), src_yuv_info.height(), src_sk_pixmaps[0].rowBytes(),
      src_sk_pixmaps[1].rowBytes(), src_sk_pixmaps[2].rowBytes(),
      src_sk_pixmaps[3].rowBytes(),
      static_cast<int>(src_yuv_info.planeConfig()),
      static_cast<int>(src_yuv_info.subsampling()),
      static_cast<int>(src_yuv_pixmap_info.dataType()), shm_id, shm_offset,
      plane_offsets[1], plane_offsets[2], plane_offsets[3], dest_mailbox.name);
}

void RasterImplementation::BeginRasterCHROMIUM(
    SkColor4f sk_color_4f,
    GLboolean needs_clear,
    GLuint msaa_sample_count,
    MsaaMode msaa_mode,
    GLboolean can_use_lcd_text,
    GLboolean visible,
    const gfx::ColorSpace& color_space,
    float hdr_headroom,
    const GLbyte* mailbox) {
  DCHECK(!raster_properties_);

  helper_->BeginRasterCHROMIUMImmediate(
      sk_color_4f.fR, sk_color_4f.fG, sk_color_4f.fB, sk_color_4f.fA,
      needs_clear, msaa_sample_count, msaa_mode, can_use_lcd_text, visible,
      hdr_headroom, mailbox);

  raster_properties_.emplace(sk_color_4f, can_use_lcd_text,
                             color_space.ToSkColorSpace());
}

void RasterImplementation::RasterCHROMIUM(
    const cc::DisplayItemList* list,
    cc::ImageProvider* provider,
    const gfx::Size& content_size,
    const gfx::Rect& full_raster_rect,
    const gfx::Rect& playback_rect,
    const gfx::Vector2dF& post_translate,
    const gfx::Vector2dF& post_scale,
    bool requires_clear,
    const ScrollOffsetMap* raster_inducing_scroll_offsets,
    size_t* max_op_size_hint,
    base::RepeatingCallback<void(SkCanvas*, uint32_t)> custom_raster_callback) {
  TRACE_EVENT1("gpu", "RasterImplementation::RasterCHROMIUM",
               "raster_chromium_id", ++raster_chromium_id_);
  DCHECK(max_op_size_hint);

  if (std::abs(post_scale.x()) < std::numeric_limits<float>::epsilon() ||
      std::abs(post_scale.y()) < std::numeric_limits<float>::epsilon()) {
    return;
  }

  gfx::Rect query_rect = gfx::ScaleToEnclosingRect(
      playback_rect, 1.f / post_scale.x(), 1.f / post_scale.y());
  list->SearchOpsByRect(query_rect, &temp_raster_offsets_);
  // We can early out if we have nothing to draw and we don't need a clear. Note
  // that if there is nothing to draw, but a clear is required, then those
  // commands would be serialized in the preamble and it's important to play
  // those back.
  if (temp_raster_offsets_.empty() && !requires_clear) {
    return;
  }

  // TODO(enne): Tune these numbers
  static constexpr uint32_t kMinAlloc = 16 * 1024;
  uint32_t free_size = std::max(GetTransferBufferFreeSize(), kMinAlloc);

  // This section duplicates RasterSource::PlaybackToCanvas setup preamble.
  cc::PaintOpBufferSerializer::Preamble preamble;
  preamble.content_size = content_size;
  preamble.full_raster_rect = full_raster_rect;
  preamble.playback_rect = playback_rect;
  preamble.post_translation = post_translate;
  preamble.post_scale = post_scale;
  preamble.requires_clear = requires_clear;
  preamble.background_color = raster_properties_->background_color;

  // Wrap the provided provider in a stashing provider so that we can delay
  // unrefing images until we have serialized dependent commands.
  cc::DecodeStashingImageProvider stashing_image_provider(provider);

  // TODO(enne): Don't access private members of DisplayItemList.
  TransferCacheSerializeHelperImpl transfer_cache_serialize_helper(this);
  PaintOpSerializer op_serializer(free_size, this, &stashing_image_provider,
                                  &transfer_cache_serialize_helper,
                                  &font_manager_, max_op_size_hint);

  cc::PaintOp::SerializeOptions options(
      &stashing_image_provider, &transfer_cache_serialize_helper,
      GetOrCreatePaintCache(), font_manager_.strike_server(),
      raster_properties_->color_space, &skottie_serialization_history_,
      raster_properties_->can_use_lcd_text,
      capabilities().context_supports_distance_field_text,
      capabilities().max_texture_size, raster_inducing_scroll_offsets);
  options.custom_callback = custom_raster_callback;

  cc::PaintOpBufferSerializer serializer(PaintOpSerializer::Serialize,
                                         &op_serializer, options);
  serializer.Serialize(list->paint_op_buffer(), &temp_raster_offsets_,
                       preamble);
  // TODO(piman): raise error if !serializer.valid()?
  op_serializer.SendSerializedData();
}

void RasterImplementation::EndRasterCHROMIUM() {
  DCHECK(raster_properties_);

  raster_properties_.reset();
  helper_->EndRasterCHROMIUM();

  if (aggressively_free_resources_) {
    ClearPaintCache();
  } else {
    FlushPaintCachePurgedEntries();
  }

  skottie_serialization_history_.RequestInactiveAnimationsPurge();
}

bool RasterImplementation::ReadbackImagePixelsINTERNAL(
    const gpu::Mailbox& source_mailbox,
    const SkImageInfo& dst_info,
    GLuint dst_row_bytes,
    int src_x,
    int src_y,
    int plane_index,
    base::OnceCallback<void(bool)> readback_done,
    void* dst_pixels) {
  DCHECK_GE(dst_row_bytes, dst_info.minRowBytes());

  // We can't use GetResultAs<>() to store our result because it uses
  // TransferBuffer under the hood and this function is potentially
  // asynchronous. Instead, store the result at the beginning of the shared
  // memory we allocate to transfer pixels.
  GLuint color_space_offset = base::bits::AlignUp(
      sizeof(cmds::ReadbackARGBImagePixelsINTERNALImmediate::Result),
      sizeof(uint64_t));

  // Add the size of the SkColorSpace while maintaining 8-byte alignment.
  GLuint pixels_offset = color_space_offset;
  if (dst_info.colorSpace()) {
    pixels_offset = base::bits::AlignUp(
        color_space_offset + dst_info.colorSpace()->writeToMemory(nullptr),
        sizeof(uint64_t));
  }

  GLuint dst_size = dst_info.computeByteSize(dst_row_bytes);
  GLuint total_size =
      pixels_offset +
      base::bits::AlignUp(dst_size, static_cast<GLuint>(sizeof(uint64_t)));

  std::unique_ptr<ScopedMappedMemoryPtr> scoped_shared_memory =
      std::make_unique<ScopedMappedMemoryPtr>(total_size, helper(),
                                              mapped_memory_.get());

  if (!scoped_shared_memory->valid()) {
    // Note, that this runs callback out of order.
    if (readback_done) {
      std::move(readback_done).Run(/*success=*/false);
    }
    return false;
  }

  GLint shm_id = scoped_shared_memory->shm_id();
  GLuint shm_offset = scoped_shared_memory->offset();
  void* shm_address = scoped_shared_memory->address();

  // Readback success/failure result is stored at the beginning of the shared
  // memory region. Client is responsible for initialization so we do so here.
  auto* readback_result =
      static_cast<cmds::ReadbackARGBImagePixelsINTERNALImmediate::Result*>(
          shm_address);
  *readback_result = 0;

  if (dst_info.colorSpace()) {
    size_t bytes_written = dst_info.colorSpace()->writeToMemory(
        UNSAFE_TODO(static_cast<uint8_t*>(shm_address) + color_space_offset));
    DCHECK_LE(bytes_written + color_space_offset, pixels_offset);
  }

  bool is_async = !!readback_done;

  GLuint query;
  if (is_async) {
    GenQueriesEXT(1, &query);

    // This query is currently sufficient because the readback implementation in
    // RasterDecoder is synchronous. If that call is changed to be asynchronous
    // later we'll need to implement a more sophisticated query.
    BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
  }

  helper_->ReadbackARGBImagePixelsINTERNALImmediate(
      src_x, src_y, plane_index, dst_info.width(), dst_info.height(),
      dst_row_bytes, dst_info.colorType(), dst_info.alphaType(), shm_id,
      shm_offset, color_space_offset, pixels_offset, source_mailbox.name);

  if (is_async) {
    EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);

    auto request = std::make_unique<AsyncARGBReadbackRequest>(
        dst_pixels, dst_info, dst_row_bytes, pixels_offset, query,
        std::move(scoped_shared_memory), std::move(readback_done));
    auto* request_ptr = request.get();
    argb_request_queue_.push(std::move(request));
    SignalQuery(query,
                base::BindOnce(&RasterImplementation::OnAsyncARGBReadbackDone,
                               base::Unretained(this), request_ptr));
  } else {
    WaitForCmd();

    if (!*readback_result) {
      return false;
    }
    auto dst = UNSAFE_TODO(
        base::span<uint8_t>(static_cast<uint8_t*>(dst_pixels), dst_size));
    auto src = UNSAFE_TODO(base::span<uint8_t>(
        static_cast<uint8_t*>(shm_address) + pixels_offset, dst_size));
    RelaxedAtomicWriteMemcpyImageRowsSkippingPadding(
        /*dst=*/dst, /*src=*/src, /*row_bytes=*/dst_info.minRowBytes(),
        /*height=*/dst_info.height(),
        /*stride=*/dst_row_bytes);
  }

  return true;
}

void RasterImplementation::OnAsyncARGBReadbackDone(
    AsyncARGBReadbackRequest* finished_request) {
  TRACE_EVENT0("gpu", "RasterImplementation::OnAsyncARGBReadbackDone");
  finished_request->done = true;

  // Only process requests in the order they were sent, regardless of when they
  // finish.
  while (!argb_request_queue_.empty()) {
    auto& request = argb_request_queue_.front();
    if (!request->done) {
      break;
    }

    // Readback success/failure is stored at the beginning of the shared memory
    // region.
    auto* result =
        static_cast<cmds::ReadbackARGBImagePixelsINTERNALImmediate::Result*>(
            request->shared_memory->address());
    if (*result) {
      size_t dst_size =
          request->dst_info.computeByteSize(request->dst_row_bytes);
      auto dst = UNSAFE_TODO(base::span<uint8_t>(
          static_cast<uint8_t*>(request->dst_pixels.get()), dst_size));
      auto src = UNSAFE_TODO(base::span<uint8_t>(
          static_cast<uint8_t*>(request->shared_memory->address()) +
              request->pixels_offset,
          dst_size));
      RelaxedAtomicWriteMemcpyImageRowsSkippingPadding(
          /*dst=*/dst, /*src=*/src,
          /*row_bytes=*/request->dst_info.minRowBytes(),
          /*height=*/request->dst_info.height(),
          /*stride=*/request->dst_row_bytes);
      request->readback_successful = true;
    }

    if (request->query) {
      DeleteQueriesEXT(1, &request->query);
    }

    argb_request_queue_.pop();
  }
}

void RasterImplementation::CancelRequests() {
  gpu_control_->CancelAllQueries();
  while (!argb_request_queue_.empty()) {
    if (argb_request_queue_.front()->query) {
      DeleteQueriesEXT(1, &argb_request_queue_.front()->query);
    }

    argb_request_queue_.pop();
  }

  while (!yuv_request_queue_.empty()) {
    if (yuv_request_queue_.front()->query) {
      DeleteQueriesEXT(1, &yuv_request_queue_.front()->query);
    }

    yuv_request_queue_.pop();
  }
}

void RasterImplementation::ReadbackARGBPixelsAsync(
    const gpu::Mailbox& source_mailbox,
    GLenum source_target,
    GrSurfaceOrigin source_origin,
    const gfx::Size& source_size,
    const gfx::Point& source_starting_point,
    const SkImageInfo& dst_info,
    GLuint dst_row_bytes,
    base::span<uint8_t> out,
    base::OnceCallback<void(bool)> readback_done) {
  TRACE_EVENT0("gpu", "RasterImplementation::ReadbackARGBPixelsAsync");
  DCHECK(!!readback_done);
  // Note: It's possible the GL implementation supports other readback
  // types. However, as of this writing, no caller of this method will
  // request a different |color_type| (i.e., requiring using some other GL
  // format).
  if (dst_info.colorType() != kRGBA_8888_SkColorType &&
      dst_info.colorType() != kBGRA_8888_SkColorType) {
    std::move(readback_done).Run(/*readback_sucess=*/false);
    return;
  }

  ReadbackImagePixelsINTERNAL(source_mailbox, dst_info, dst_row_bytes,
                              source_starting_point.x(),
                              source_starting_point.y(), /*plane_index=*/0,
                              std::move(readback_done), out.data());
}

bool RasterImplementation::ReadbackImagePixels(
    const gpu::Mailbox& source_mailbox,
    const SkImageInfo& dst_info,
    GLuint dst_row_bytes,
    int src_x,
    int src_y,
    int plane_index,
    void* dst_pixels) {
  TRACE_EVENT0("gpu", "RasterImplementation::ReadbackImagePixels");
  return ReadbackImagePixelsINTERNAL(
             source_mailbox, dst_info, dst_row_bytes, src_x, src_y, plane_index,
             base::OnceCallback<void(bool)>(), dst_pixels) ||
         base::FeatureList::IsEnabled(kDisableErrorHandlingForReadback);
}

void RasterImplementation::ReadbackYUVPixelsAsync(
    const gpu::Mailbox& source_mailbox,
    GLenum source_target,
    const gfx::Rect& source_rect,
    const gfx::Rect& output_rect,
    bool vertically_flip_texture,
    int y_plane_row_stride_bytes,
    base::span<uint8_t> y_plane_data,
    int u_plane_row_stride_bytes,
    base::span<uint8_t> u_plane_data,
    int v_plane_row_stride_bytes,
    base::span<uint8_t> v_plane_data,
    base::OnceCallback<void()> release_mailbox,
    base::OnceCallback<void(bool)> readback_done) {
  TRACE_EVENT0("gpu", "RasterImplementation::ReadbackYUVPixelsAsync");
  DCHECK(!!release_mailbox);
  DCHECK(!!readback_done);

  if (output_rect.width() % 2 != 0 || output_rect.height() % 2 != 0) {
    SetGLError(GL_INVALID_VALUE, "glReadbackYUVPixelsAsync",
               "|output_rect| width and height must be divisible by 2");
    return;
  }

  auto y_offset = static_cast<GLuint>(base::bits::AlignUp(
      sizeof(cmds::ReadbackYUVImagePixelsINTERNALImmediate::Result),
      sizeof(uint64_t)));

  if (y_plane_row_stride_bytes < output_rect.width()) {
    SetGLError(
        GL_INVALID_VALUE, "glReadbackYUVPixelsAsync",
        "|y_plane_row_stride_bytes| must be >= the width of the y plane.");
    return;
  }
  GLuint y_padded_size = output_rect.height() * y_plane_row_stride_bytes;

  constexpr auto kSizeofUint64 = static_cast<GLuint>(sizeof(uint64_t));
  GLuint u_offset =
      base::bits::AlignUp(y_offset + y_padded_size, kSizeofUint64);
  if (u_plane_row_stride_bytes < ((output_rect.width() + 1) / 2)) {
    SetGLError(
        GL_INVALID_VALUE, "glReadbackYUVPixelsAsync",
        "|u_plane_row_stride_bytes| must be >= the width of the u plane.");
    return;
  }
  GLuint u_padded_size =
      ((output_rect.height() + 1) / 2) * u_plane_row_stride_bytes;

  GLuint v_offset =
      base::bits::AlignUp(u_offset + u_padded_size, kSizeofUint64);
  if (v_plane_row_stride_bytes < ((output_rect.width() + 1) / 2)) {
    SetGLError(
        GL_INVALID_VALUE, "glReadbackYUVPixelsAsync",
        "|v_plane_row_stride_bytes| must be >= the width of the v plane.");
    return;
  }
  GLuint v_padded_size =
      ((output_rect.height() + 1) / 2) * v_plane_row_stride_bytes;

  size_t total_size =
      base::bits::AlignUp(v_offset + v_padded_size, kSizeofUint64);

  std::unique_ptr<ScopedMappedMemoryPtr> scoped_shared_memory =
      std::make_unique<ScopedMappedMemoryPtr>(total_size, helper(),
                                              mapped_memory_.get());
  if (!scoped_shared_memory->valid()) {
    SetGLError(GL_INVALID_VALUE, "glReadbackYUVPixelsAsync",
               "couldn't allocate shared memory");
    return;
  }

  GLint shm_id = scoped_shared_memory->shm_id();
  GLuint shm_offset = scoped_shared_memory->offset();
  void* shm_address = scoped_shared_memory->address();

  auto* readback_result =
      static_cast<cmds::ReadbackYUVImagePixelsINTERNALImmediate::Result*>(
          shm_address);
  *readback_result = 0;

  GLuint query;
  GenQueriesEXT(1, &query);
  BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
  helper_->ReadbackYUVImagePixelsINTERNALImmediate(
      source_rect.x(), source_rect.y(), source_rect.width(),
      source_rect.height(), output_rect.width(), output_rect.height(), shm_id,
      shm_offset, y_offset, y_plane_row_stride_bytes, u_offset,
      u_plane_row_stride_bytes, v_offset, v_plane_row_stride_bytes,
      source_mailbox.name);
  EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);

  auto request = std::make_unique<AsyncYUVReadbackRequest>(
      output_rect, query, y_plane_row_stride_bytes, y_offset,
      y_plane_data.data(), u_plane_row_stride_bytes, u_offset,
      u_plane_data.data(), v_plane_row_stride_bytes, v_offset,
      v_plane_data.data(), std::move(scoped_shared_memory),
      std::move(release_mailbox), std::move(readback_done));
  auto* request_ptr = request.get();
  yuv_request_queue_.push(std::move(request));
  SignalQuery(query,
              base::BindOnce(&RasterImplementation::OnAsyncYUVReadbackDone,
                             base::Unretained(this),
                             // This is safe because we own `request` through
                             // `yuv_request_queue_`, and we make certain not to
                             // run this callback when a request has been
                             // destroyed. We remove and destroy requests from
                             // `yuv_request_queue_` in two places:
                             // `OnAsyncYUVReadbackDone` and `CancelRequests`.
                             //
                             // `OnAsyncYUVReadbackDone` is this callback we're
                             // binding. We only destroy requests there if their
                             // callback has run. This is kept track of with
                             // `AsyncYUVReadbackRequest`'s `done` member.
                             //
                             // The latter calls CancelAllQueries before
                             // destroying all requests in `yuv_request_queue_`
                             // which prevents this callback from running.
                             base::Unretained(request_ptr)));
}

void RasterImplementation::OnAsyncYUVReadbackDone(
    AsyncYUVReadbackRequest* finished_request) {
  TRACE_EVENT0("gpu", "RasterImplementation::OnAsyncYUVReadbackDone");
  finished_request->done = true;

  while (!yuv_request_queue_.empty()) {
    auto& request = yuv_request_queue_.front();
    if (!request->done) {
      break;
    }

    request->CopyYUVPlanes();

    if (request->query) {
      DeleteQueriesEXT(1, &request->query);
    }

    yuv_request_queue_.pop();
  }
}

void RasterImplementation::TraceBeginCHROMIUM(const char* category_name,
                                              const char* trace_name) {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
                     << category_name << ", " << trace_name << ")");
  static constexpr size_t kMaxStrLen = 256;
  DCHECK_LE(strlen(category_name), kMaxStrLen);
  DCHECK_LE(strlen(trace_name), kMaxStrLen);
  SetBucketAsCString(kResultBucketId, category_name);
  SetBucketAsCString(kResultBucketId + 1, trace_name);
  helper_->TraceBeginCHROMIUM(kResultBucketId, kResultBucketId + 1);
  helper_->SetBucketSize(kResultBucketId, 0);
  helper_->SetBucketSize(kResultBucketId + 1, 0);
  current_trace_stack_++;
}

void RasterImplementation::TraceEndCHROMIUM() {
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
  if (current_trace_stack_ == 0) {
    SetGLError(GL_INVALID_OPERATION, "glTraceEndCHROMIUM",
               "missing begin trace");
    return;
  }
  helper_->TraceEndCHROMIUM();
  current_trace_stack_--;
}

void RasterImplementation::SetActiveURLCHROMIUM(const char* url) {
  DCHECK(url);
  GPU_CLIENT_SINGLE_THREAD_CHECK();
  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSetActiveURLCHROMIUM(" << url);

  if (last_active_url_ == url) {
    return;
  }

  last_active_url_ = url;
  static constexpr uint32_t kMaxStrLen = 1024;
  size_t len = strlen(url);
  if (len == 0) {
    return;
  }

  SetBucketContents(kResultBucketId, url,
                    base::CheckMin(len, kMaxStrLen).ValueOrDie());
  helper_->SetActiveURLCHROMIUM(kResultBucketId);
  helper_->SetBucketSize(kResultBucketId, 0);
}

cc::ClientPaintCache* RasterImplementation::GetOrCreatePaintCache() {
  if (!paint_cache_) {
    size_t paint_cache_budget = 0u;
    if (base::SysInfo::IsLowEndDevice()) {
      paint_cache_budget = 256 * 1024;
    } else {
      paint_cache_budget = 4 * 1024 * 1024;
    }
    paint_cache_ = std::make_unique<cc::ClientPaintCache>(paint_cache_budget);
  }
  return paint_cache_.get();
}

void RasterImplementation::FlushPaintCachePurgedEntries() {
  if (!paint_cache_) {
    return;
  }

  paint_cache_->Purge(&temp_paint_cache_purged_data_);
  for (uint32_t i = static_cast<uint32_t>(cc::PaintCacheDataType::kPath);
       i < cc::PaintCacheDataTypeCount; ++i) {
    auto& ids = temp_paint_cache_purged_data_[i];
    if (ids.empty()) {
      continue;
    }

    switch (static_cast<cc::PaintCacheDataType>(i)) {
      case cc::PaintCacheDataType::kPath:
        UNSAFE_TODO(
            DEFINE_PAINT_CACHE_DELETION(kMaxImmediateDeletedPaintCachePaths,
                                        DeletePaintCachePathsINTERNALImmediate,
                                        DeletePaintCachePathsINTERNAL));
        break;
      case cc::PaintCacheDataType::kSkRuntimeEffect:
        UNSAFE_TODO(DEFINE_PAINT_CACHE_DELETION(
            kMaxImmediateDeletedPaintCacheEffects,
            DeletePaintCacheEffectsINTERNALImmediate,
            DeletePaintCacheEffectsINTERNAL));
        break;
    }
    ids.clear();
  }
}

void RasterImplementation::ClearPaintCache() {
  if (!paint_cache_ || !paint_cache_->PurgeAll()) {
    return;
  }

  helper_->ClearPaintCacheINTERNAL();
}

std::unique_ptr<cc::TransferCacheSerializeHelper>
RasterImplementation::CreateTransferCacheHelperForTesting() {
  return std::make_unique<TransferCacheSerializeHelperImpl>(this);
}

void RasterImplementation::SetRasterMappedBufferForTesting(
    ScopedTransferBufferPtr buffer) {
  raster_mapped_buffer_.emplace(std::move(buffer));
}

RasterImplementation::RasterProperties::RasterProperties(
    SkColor4f background_color,
    bool can_use_lcd_text,
    sk_sp<SkColorSpace> color_space)
    : background_color(background_color),
      can_use_lcd_text(can_use_lcd_text),
      color_space(std::move(color_space)) {}

RasterImplementation::RasterProperties::~RasterProperties() = default;

}  // namespace raster
}  // namespace gpu
