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

#include "cc/tiles/gpu_image_decode_cache.h"

#include <inttypes.h>

#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/debug/alias.h"
#include "base/hash.h"
#include "base/memory/discardable_memory_allocator.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "cc/base/devtools_instrumentation.h"
#include "cc/base/histograms.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "cc/raster/scoped_grcontext_access.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/mipmap_util.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkYUVAIndex.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/GrTexture.h"
#include "ui/gfx/skia_util.h"
#include "ui/gl/trace_util.h"

namespace cc {
namespace {
// The number or entries to keep in the cache, depending on the memory state of
// the system. This limit can be breached by in-use cache items, which cannot
// be deleted.
static const int kNormalMaxItemsInCacheForGpu = 2000;
static const int kSuspendedMaxItemsInCacheForGpu = 0;

// The maximum number of images that we can lock simultaneously in our working
// set. This is separate from the memory limit, as keeping very large numbers
// of small images simultaneously locked can lead to performance issues and
// memory spikes.
static const int kMaxItemsInWorkingSet = 256;

// lock_count │ used  │ result state
// ═══════════╪═══════╪══════════════════
//  1         │ false │ WASTED_ONCE
//  1         │ true  │ USED_ONCE
//  >1        │ false │ WASTED_RELOCKED
//  >1        │ true  │ USED_RELOCKED
// Note that it's important not to reorder the following enum, since the
// numerical values are used in the histogram code.
enum ImageUsageState : int {
  IMAGE_USAGE_STATE_WASTED_ONCE,
  IMAGE_USAGE_STATE_USED_ONCE,
  IMAGE_USAGE_STATE_WASTED_RELOCKED,
  IMAGE_USAGE_STATE_USED_RELOCKED,
  IMAGE_USAGE_STATE_COUNT
};

// Returns true if an image would not be drawn and should therefore be
// skipped rather than decoded.
bool SkipImage(const DrawImage& draw_image) {
  if (!SkIRect::Intersects(
          draw_image.src_rect(),
          SkIRect::MakeWH(draw_image.paint_image().width(),
                          draw_image.paint_image().height()))) {
    return true;
  }
  if (std::abs(draw_image.scale().width()) <
          std::numeric_limits<float>::epsilon() ||
      std::abs(draw_image.scale().height()) <
          std::numeric_limits<float>::epsilon()) {
    return true;
  }
  return false;
}

// Returns the filter quality to use for scaling the image to upload scale as
// well as for using when passing the decoded image to skia. Due to parity with
// SW and power impliciation, limit the filter quality to medium.
SkFilterQuality CalculateDesiredFilterQuality(const DrawImage& draw_image) {
  return std::min(kMedium_SkFilterQuality, draw_image.filter_quality());
}

// Calculate the mip level to upload-scale the image to before uploading. We use
// mip levels rather than exact scales to increase re-use of scaled images.
int CalculateUploadScaleMipLevel(const DrawImage& draw_image) {
  // Images which are being clipped will have color-bleeding if scaled.
  // TODO(ericrk): Investigate uploading clipped images to handle this case and
  // provide further optimization. crbug.com/620899
  if (draw_image.src_rect() !=
      SkIRect::MakeWH(draw_image.paint_image().width(),
                      draw_image.paint_image().height())) {
    return 0;
  }

  gfx::Size base_size(draw_image.paint_image().width(),
                      draw_image.paint_image().height());
  // Ceil our scaled size so that the mip map generated is guaranteed to be
  // larger. Take the abs of the scale, as mipmap functions don't handle
  // (and aren't impacted by) negative image dimensions.
  gfx::Size scaled_size =
      gfx::ScaleToCeiledSize(base_size, std::abs(draw_image.scale().width()),
                             std::abs(draw_image.scale().height()));

  return MipMapUtil::GetLevelForSize(base_size, scaled_size);
}

// Calculates the scale factor which can be used to scale an image to a given
// mip level.
SkSize CalculateScaleFactorForMipLevel(const DrawImage& draw_image,
                                       int upload_scale_mip_level) {
  gfx::Size base_size(draw_image.paint_image().width(),
                      draw_image.paint_image().height());
  return MipMapUtil::GetScaleAdjustmentForLevel(base_size,
                                                upload_scale_mip_level);
}

// Calculates the size of a given mip level.
gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image,
                                   int upload_scale_mip_level) {
  gfx::Size base_size(draw_image.paint_image().width(),
                      draw_image.paint_image().height());
  return MipMapUtil::GetSizeForLevel(base_size, upload_scale_mip_level);
}

// Determines whether a draw image requires mips.
bool ShouldGenerateMips(const DrawImage& draw_image,
                        int upload_scale_mip_level) {
  // If filter quality is less than medium, don't generate mips.
  if (draw_image.filter_quality() < kMedium_SkFilterQuality)
    return false;

  gfx::Size base_size(draw_image.paint_image().width(),
                      draw_image.paint_image().height());
  // Take the abs of the scale, as mipmap functions don't handle (and aren't
  // impacted by) negative image dimensions.
  gfx::SizeF scaled_size = gfx::ScaleSize(
      gfx::SizeF(base_size), std::abs(draw_image.scale().width()),
      std::abs(draw_image.scale().height()));

  // If our target size is smaller than our scaled size in both dimension, we
  // need to generate mips.
  gfx::SizeF target_size =
      gfx::SizeF(CalculateSizeForMipLevel(draw_image, upload_scale_mip_level));
  if (scaled_size.width() < target_size.width() &&
      scaled_size.height() < target_size.height()) {
    return true;
  }

  return false;
}

void SetYuvPixmapsFromSizeInfo(SkPixmap* pixmap_y,
                               SkPixmap* pixmap_u,
                               SkPixmap* pixmap_v,
                               const SkYUVASizeInfo& yuva_size_info,
                               void* planes[SkYUVASizeInfo::kMaxCount],
                               const SkImageInfo& info,
                               void* memory_ptr) {
  DCHECK(pixmap_y);
  DCHECK(pixmap_u);
  DCHECK(pixmap_v);
  const size_t y_width = yuva_size_info.fWidthBytes[SkYUVAIndex::kY_Index];
  const size_t y_height = yuva_size_info.fSizes[SkYUVAIndex::kY_Index].height();
  const size_t u_width = yuva_size_info.fWidthBytes[SkYUVAIndex::kU_Index];
  const size_t u_height = yuva_size_info.fSizes[SkYUVAIndex::kU_Index].height();
  const size_t v_width = yuva_size_info.fWidthBytes[SkYUVAIndex::kV_Index];
  const size_t v_height = yuva_size_info.fSizes[SkYUVAIndex::kV_Index].height();
  const SkImageInfo y_decode_info =
      info.makeColorType(kGray_8_SkColorType).makeWH(y_width, y_height);
  const SkImageInfo u_decode_info = y_decode_info.makeWH(u_width, u_height);
  const SkImageInfo v_decode_info = y_decode_info.makeWH(v_width, v_height);
  yuva_size_info.computePlanes(memory_ptr, planes);
  pixmap_y->reset(y_decode_info, planes[SkYUVAIndex::kY_Index],
                  y_decode_info.minRowBytes());
  pixmap_u->reset(u_decode_info, planes[SkYUVAIndex::kU_Index],
                  u_decode_info.minRowBytes());
  pixmap_v->reset(v_decode_info, planes[SkYUVAIndex::kV_Index],
                  v_decode_info.minRowBytes());
}

// Draws and scales the provided |draw_image| into the |target_pixmap|. If the
// draw/scale can be done directly, calls directly into PaintImage::Decode.
// if not, decodes to a compatible temporary pixmap and then converts that into
// the |target_pixmap|.
//
// For RGBX decoding, the default, the parameters |pixmap_y|,
// |pixmap_u|, and |pixmap_v| are NULL. Otherwise, the pixmaps share a
// contiguous block of allocated backing memory. If scaling needs to happen,
// it is done individually for each plane.
//
// The |do_yuv_decode| parameter indicates whether YUV decoding can and should
// be done, which is a combination of the underlying data requesting YUV and the
// cache mode (i.e. OOP-R or not) supporting it.
bool DrawAndScaleImage(const DrawImage& draw_image,
                       SkPixmap* target_pixmap,
                       PaintImage::GeneratorClientId client_id,
                       const bool do_yuv_decode,
                       SkPixmap* pixmap_y = nullptr,
                       SkPixmap* pixmap_u = nullptr,
                       SkPixmap* pixmap_v = nullptr) {
  // We will pass color_space explicitly to PaintImage::Decode, so pull it out
  // of the pixmap and populate a stand-alone value.
  // Note: To pull colorspace out of the pixmap, we create a new pixmap with
  // null colorspace but the same memory pointer.
  // The backing memory for |pixmap| has been allocated based on
  // image_data->size, so it is correct for YUV even if the other parameters
  // for |pixmap| do not quite make sense for YUV (e.g. rowBytes).
  SkPixmap pixmap(target_pixmap->info().makeColorSpace(nullptr),
                  target_pixmap->writable_addr(), target_pixmap->rowBytes());
  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(pixmap.writable_addr());
  sk_sp<SkColorSpace> color_space = target_pixmap->info().refColorSpace();

  const PaintImage& paint_image = draw_image.paint_image();
  const bool is_original_decode =
      SkISize::Make(paint_image.width(), paint_image.height()) ==
      pixmap.bounds().size();
  const bool is_nearest_neighbor =
      draw_image.filter_quality() == kNone_SkFilterQuality;
  SkImageInfo info = pixmap.info();
  SkYUVASizeInfo yuva_size_info;
  if (do_yuv_decode) {
    const bool yuva_info_initialized = paint_image.IsYuv(&yuva_size_info);
    DCHECK(yuva_info_initialized);
  }
  SkISize supported_size =
      paint_image.GetSupportedDecodeSize(pixmap.bounds().size());
  // We can directly decode into target pixmap if we are doing an original
  // decode or we are decoding to scale without nearest neighbor filtering.
  // TODO(crbug.com/927437): Although the JPEG decoder supports decoding to
  // scale, we have not yet implemented YUV + decoding to scale, so we skip it.
  const bool can_directly_decode =
      is_original_decode || (!is_nearest_neighbor && !do_yuv_decode);
  if (supported_size == pixmap.bounds().size() && can_directly_decode) {
    if (do_yuv_decode) {
      void* planes[SkYUVASizeInfo::kMaxCount];
      SetYuvPixmapsFromSizeInfo(pixmap_y, pixmap_u, pixmap_v, yuva_size_info,
                                planes, info, pixmap.writable_addr());
      return paint_image.DecodeYuv(planes, draw_image.frame_index(), client_id,
                                   yuva_size_info);
    }
    return paint_image.Decode(pixmap.writable_addr(), &info, color_space,
                              draw_image.frame_index(), client_id);
  }

  // If we can't decode/scale directly, we will handle this in 2 steps.
  // Step 1: Decode at the nearest (larger) directly supported size or the
  // original size if nearest neighbor quality is requested.
  // Step 2: Scale to |pixmap| size. If decoded image is half float backed and
  // the device does not support image resize, decode to N32 color type and
  // convert to F16 afterward. If doing YUV decoding, use an assumption of
  // YUV420 and the dimensions of |pixmap|. Resizing happens on a plane-by-plane
  // basis.
  SkImageInfo decode_info;
  if (do_yuv_decode) {
    const size_t yuva_bytes = yuva_size_info.computeTotalBytes();
    if (SkImageInfo::ByteSizeOverflowed(yuva_bytes)) {
      return false;
    }
    // We temporarily abuse the dimensions of the pixmap to ensure we allocate
    // the proper number of bytes, but the actual plane dimensions are stored in
    // |yuva_size_info| and accessed within PaintImage::DecodeYuv() and below.
    decode_info = info.makeColorType(kGray_8_SkColorType).makeWH(yuva_bytes, 1);
  } else {
    SkISize decode_size =
        is_nearest_neighbor
            ? SkISize::Make(paint_image.width(), paint_image.height())
            : supported_size;
    decode_info = info.makeWH(decode_size.width(), decode_size.height());
  }
  SkFilterQuality filter_quality = CalculateDesiredFilterQuality(draw_image);
  bool decode_to_f16_using_n32_intermediate =
      decode_info.colorType() == kRGBA_F16_SkColorType &&
      !ImageDecodeCacheUtils::CanResizeF16Image(filter_quality);
  if (decode_to_f16_using_n32_intermediate)
    decode_info = decode_info.makeColorType(kN32_SkColorType);

  SkBitmap decode_bitmap;
  if (!decode_bitmap.tryAllocPixels(decode_info))
    return false;

  SkPixmap decode_pixmap = decode_bitmap.pixmap();
  void* planes[SkYUVASizeInfo::kMaxCount];
  if (do_yuv_decode) {
    yuva_size_info.computePlanes(decode_pixmap.writable_addr(), planes);
  }
  bool initial_decode_failed =
      do_yuv_decode ? !paint_image.DecodeYuv(planes, draw_image.frame_index(),
                                             client_id, yuva_size_info)
                    : !paint_image.Decode(decode_pixmap.writable_addr(),
                                          &decode_info, color_space,
                                          draw_image.frame_index(), client_id);
  if (initial_decode_failed)
    return false;

  if (decode_to_f16_using_n32_intermediate) {
    return ImageDecodeCacheUtils::ScaleToHalfFloatPixmapUsingN32Intermediate(
        decode_pixmap, &pixmap, filter_quality);
  }
  if (do_yuv_decode) {
    SkPixmap unscaled_pixmap_y;
    SkPixmap unscaled_pixmap_u;
    SkPixmap unscaled_pixmap_v;
    void* planes[SkYUVASizeInfo::kMaxCount];
    SetYuvPixmapsFromSizeInfo(&unscaled_pixmap_y, &unscaled_pixmap_u,
                              &unscaled_pixmap_v, yuva_size_info, planes,
                              decode_info, decode_pixmap.writable_addr());

    // Assumes YUV420 and splits decode_pixmap into pixmaps for each plane.
    // TODO(crbug.com/915972): Fix this assumption.
    const SkImageInfo y_info_scaled = info.makeColorType(kGray_8_SkColorType);
    const size_t uv_width_scaled = (y_info_scaled.width() + 1) / 2;
    const size_t uv_height_scaled = (y_info_scaled.height() + 1) / 2;
    const SkImageInfo uv_info_scaled =
        y_info_scaled.makeWH(uv_width_scaled, uv_height_scaled);
    const size_t y_plane_bytes = y_info_scaled.computeMinByteSize();
    const size_t u_plane_bytes = uv_info_scaled.computeMinByteSize();
    DCHECK(!SkImageInfo::ByteSizeOverflowed(y_plane_bytes));
    DCHECK(!SkImageInfo::ByteSizeOverflowed(u_plane_bytes));

    pixmap_y->reset(y_info_scaled, data_ptr, y_info_scaled.minRowBytes());
    pixmap_u->reset(uv_info_scaled, data_ptr + y_plane_bytes,
                    uv_info_scaled.minRowBytes());
    pixmap_v->reset(uv_info_scaled, data_ptr + y_plane_bytes + u_plane_bytes,
                    uv_info_scaled.minRowBytes());

    const bool all_planes_scaled_successfully =
        unscaled_pixmap_y.scalePixels(*pixmap_y, filter_quality) &&
        unscaled_pixmap_u.scalePixels(*pixmap_u, filter_quality) &&
        unscaled_pixmap_v.scalePixels(*pixmap_v, filter_quality);
    return all_planes_scaled_successfully;
  }
  return decode_pixmap.scalePixels(pixmap, filter_quality);
}

// Takes ownership of the backing texture of an SkImage. This allows us to
// delete this texture under Skia (via discardable).
sk_sp<SkImage> TakeOwnershipOfSkImageBacking(GrContext* context,
                                             sk_sp<SkImage> image) {
  // If the image is not texture backed, it has no backing, just return it.
  if (!image->isTextureBacked()) {
    return image;
  }

  GrSurfaceOrigin origin;
  image->getBackendTexture(false /* flushPendingGrContextIO */, &origin);
  SkColorType color_type = image->colorType();
  if (color_type == kUnknown_SkColorType) {
    return nullptr;
  }
  sk_sp<SkColorSpace> color_space = image->refColorSpace();
  GrBackendTexture backend_texture;
  SkImage::BackendTextureReleaseProc release_proc;
  SkImage::MakeBackendTextureFromSkImage(context, std::move(image),
                                         &backend_texture, &release_proc);
  return SkImage::MakeFromTexture(context, backend_texture, origin, color_type,
                                  kPremul_SkAlphaType, std::move(color_space));
}

// Immediately deletes an SkImage, preventing caching of that image. Must be
// called while holding the context lock.
void DeleteSkImageAndPreventCaching(viz::RasterContextProvider* context,
                                    sk_sp<SkImage>&& image) {
  // No need to do anything for a non-texture-backed images.
  if (!image->isTextureBacked())
    return;

  sk_sp<SkImage> image_owned =
      TakeOwnershipOfSkImageBacking(context->GrContext(), std::move(image));
  // If context is lost, we may get a null image here.
  if (image_owned) {
    // Delete |original_image_owned| as Skia will not clean it up. We are
    // holding the context lock here, so we can delete immediately.
    uint32_t texture_id =
        GpuImageDecodeCache::GlIdFromSkImage(image_owned.get());
    context->ContextGL()->DeleteTextures(1, &texture_id);
  }
}

// TODO(ericrk): Replace calls to this with calls to SkImage::makeTextureImage,
// once that function handles colorspaces. https://crbug.com/834837
sk_sp<SkImage> MakeTextureImage(viz::RasterContextProvider* context,
                                sk_sp<SkImage> source_image,
                                sk_sp<SkColorSpace> target_color_space,
                                GrMipMapped mip_mapped) {
  // Step 1: Upload image and generate mips if necessary. If we will be applying
  // a color-space conversion, don't generate mips yet, instead do it after
  // conversion, in step 3.
  bool add_mips_after_color_conversion =
      (target_color_space && mip_mapped == GrMipMapped::kYes);
  sk_sp<SkImage> uploaded_image = source_image->makeTextureImage(
      context->GrContext(), nullptr,
      add_mips_after_color_conversion ? GrMipMapped::kNo : mip_mapped);

  // Step 2: Apply a color-space conversion if necessary.
  if (uploaded_image && target_color_space) {
    sk_sp<SkImage> pre_converted_image = uploaded_image;
    uploaded_image = uploaded_image->makeColorSpace(target_color_space);

    if (uploaded_image != pre_converted_image)
      DeleteSkImageAndPreventCaching(context, std::move(pre_converted_image));
  }

  // Step 3: If we had a colorspace conversion, we couldn't mipmap in step 1, so
  // add mips here.
  if (uploaded_image && add_mips_after_color_conversion) {
    sk_sp<SkImage> pre_mipped_image = uploaded_image;
    uploaded_image = uploaded_image->makeTextureImage(
        context->GrContext(), nullptr, GrMipMapped::kYes);
    DCHECK_NE(pre_mipped_image, uploaded_image);
    DeleteSkImageAndPreventCaching(context, std::move(pre_mipped_image));
  }

  return uploaded_image;
}

}  // namespace

// static
GpuImageDecodeCache::InUseCacheKey
GpuImageDecodeCache::InUseCacheKey::FromDrawImage(const DrawImage& draw_image) {
  return InUseCacheKey(draw_image);
}

// Extract the information to uniquely identify a DrawImage for the purposes of
// the |in_use_cache_|.
GpuImageDecodeCache::InUseCacheKey::InUseCacheKey(const DrawImage& draw_image)
    : frame_key(draw_image.frame_key()),
      upload_scale_mip_level(CalculateUploadScaleMipLevel(draw_image)),
      filter_quality(CalculateDesiredFilterQuality(draw_image)) {}

bool GpuImageDecodeCache::InUseCacheKey::operator==(
    const InUseCacheKey& other) const {
  return frame_key == other.frame_key &&
         upload_scale_mip_level == other.upload_scale_mip_level &&
         filter_quality == other.filter_quality;
}

size_t GpuImageDecodeCache::InUseCacheKeyHash::operator()(
    const InUseCacheKey& cache_key) const {
  return base::HashInts(cache_key.frame_key.hash(),
                        base::HashInts(cache_key.upload_scale_mip_level,
                                       cache_key.filter_quality));
}

GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry(
    scoped_refptr<ImageData> image_data)
    : image_data(std::move(image_data)) {}
GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry(const InUseCacheEntry&) =
    default;
GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry(InUseCacheEntry&&) =
    default;
GpuImageDecodeCache::InUseCacheEntry::~InUseCacheEntry() = default;

// Task which decodes an image and stores the result in discardable memory.
// This task does not use GPU resources and can be run on any thread.
class GpuImageDecodeTaskImpl : public TileTask {
 public:
  GpuImageDecodeTaskImpl(GpuImageDecodeCache* cache,
                         const DrawImage& draw_image,
                         const ImageDecodeCache::TracingInfo& tracing_info,
                         GpuImageDecodeCache::DecodeTaskType task_type)
      : TileTask(true),
        cache_(cache),
        image_(draw_image),
        tracing_info_(tracing_info),
        task_type_(task_type) {
    DCHECK(!SkipImage(draw_image));
  }

  // Overridden from Task:
  void RunOnWorkerThread() override {
    TRACE_EVENT2("cc", "GpuImageDecodeTaskImpl::RunOnWorkerThread", "mode",
                 "gpu", "source_prepare_tiles_id",
                 tracing_info_.prepare_tiles_id);
    devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
        &image_.paint_image(),
        devtools_instrumentation::ScopedImageDecodeTask::kGpu,
        ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type));
    cache_->DecodeImageInTask(image_, tracing_info_.task_type);
  }

  // Overridden from TileTask:
  void OnTaskCompleted() override {
    cache_->OnImageDecodeTaskCompleted(image_, task_type_);
  }

 protected:
  ~GpuImageDecodeTaskImpl() override = default;

 private:
  GpuImageDecodeCache* cache_;
  DrawImage image_;
  const ImageDecodeCache::TracingInfo tracing_info_;
  const GpuImageDecodeCache::DecodeTaskType task_type_;

  DISALLOW_COPY_AND_ASSIGN(GpuImageDecodeTaskImpl);
};

// Task which creates an image from decoded data. Typically this involves
// uploading data to the GPU, which requires this task be run on the non-
// concurrent thread.
class ImageUploadTaskImpl : public TileTask {
 public:
  ImageUploadTaskImpl(GpuImageDecodeCache* cache,
                      const DrawImage& draw_image,
                      scoped_refptr<TileTask> decode_dependency,
                      const ImageDecodeCache::TracingInfo& tracing_info)
      : TileTask(false),
        cache_(cache),
        image_(draw_image),
        tracing_info_(tracing_info) {
    DCHECK(!SkipImage(draw_image));
    // If an image is already decoded and locked, we will not generate a
    // decode task.
    if (decode_dependency)
      dependencies_.push_back(std::move(decode_dependency));
  }

  // Override from Task:
  void RunOnWorkerThread() override {
    TRACE_EVENT2("cc", "ImageUploadTaskImpl::RunOnWorkerThread", "mode", "gpu",
                 "source_prepare_tiles_id", tracing_info_.prepare_tiles_id);
    cache_->UploadImageInTask(image_);
  }

  // Overridden from TileTask:
  void OnTaskCompleted() override {
    cache_->OnImageUploadTaskCompleted(image_);
  }

 protected:
  ~ImageUploadTaskImpl() override = default;

 private:
  GpuImageDecodeCache* cache_;
  DrawImage image_;
  const ImageDecodeCache::TracingInfo tracing_info_;

  DISALLOW_COPY_AND_ASSIGN(ImageUploadTaskImpl);
};

GpuImageDecodeCache::ImageDataBase::ImageDataBase() = default;
GpuImageDecodeCache::ImageDataBase::~ImageDataBase() = default;

void GpuImageDecodeCache::ImageDataBase::OnSetLockedData(bool out_of_raster) {
  DCHECK_EQ(usage_stats_.lock_count, 1);
  DCHECK(!is_locked_);
  usage_stats_.first_lock_out_of_raster = out_of_raster;
  is_locked_ = true;
}

void GpuImageDecodeCache::ImageDataBase::OnResetData() {
  is_locked_ = false;
  usage_stats_ = UsageStats();
}

void GpuImageDecodeCache::ImageDataBase::OnLock() {
  DCHECK(!is_locked_);
  is_locked_ = true;
  ++usage_stats_.lock_count;
}

void GpuImageDecodeCache::ImageDataBase::OnUnlock() {
  DCHECK(is_locked_);
  is_locked_ = false;
  if (usage_stats_.lock_count == 1)
    usage_stats_.first_lock_wasted = !usage_stats_.used;
}

int GpuImageDecodeCache::ImageDataBase::UsageState() const {
  ImageUsageState state = IMAGE_USAGE_STATE_WASTED_ONCE;
  if (usage_stats_.lock_count == 1) {
    if (usage_stats_.used)
      state = IMAGE_USAGE_STATE_USED_ONCE;
    else
      state = IMAGE_USAGE_STATE_WASTED_ONCE;
  } else {
    if (usage_stats_.used)
      state = IMAGE_USAGE_STATE_USED_RELOCKED;
    else
      state = IMAGE_USAGE_STATE_WASTED_RELOCKED;
  }

  return state;
}

GpuImageDecodeCache::DecodedImageData::DecodedImageData(bool is_bitmap_backed)
    : is_bitmap_backed_(is_bitmap_backed) {}
GpuImageDecodeCache::DecodedImageData::~DecodedImageData() {
  ResetData();
}

bool GpuImageDecodeCache::DecodedImageData::Lock() {
  if (data_->Lock())
    OnLock();
  return is_locked_;
}

void GpuImageDecodeCache::DecodedImageData::Unlock() {
  data_->Unlock();
  OnUnlock();
}

void GpuImageDecodeCache::DecodedImageData::SetLockedData(
    std::unique_ptr<base::DiscardableMemory> data,
    sk_sp<SkImage> image,
    bool out_of_raster) {
  DCHECK(data);
  DCHECK(!data_);
  DCHECK(image);
  DCHECK(!image_);
  data_ = std::move(data);
  image_ = std::move(image);
  OnSetLockedData(out_of_raster);
}

void GpuImageDecodeCache::DecodedImageData::SetLockedData(
    std::unique_ptr<base::DiscardableMemory> data,
    sk_sp<SkImage> image_y,
    sk_sp<SkImage> image_u,
    sk_sp<SkImage> image_v,
    bool out_of_raster) {
  DCHECK(data);
  DCHECK(!data_);
  DCHECK(image_y);
  DCHECK(image_u);
  DCHECK(image_v);
  DCHECK(!image_yuv_planes_);
  data_ = std::move(data);
  image_yuv_planes_ = std::array<sk_sp<SkImage>, SkYUVASizeInfo::kMaxCount>();
  image_yuv_planes_->at(SkYUVAIndex::kY_Index) = std::move(image_y);
  image_yuv_planes_->at(SkYUVAIndex::kU_Index) = std::move(image_u);
  image_yuv_planes_->at(SkYUVAIndex::kV_Index) = std::move(image_v);
  OnSetLockedData(out_of_raster);
}

void GpuImageDecodeCache::DecodedImageData::SetBitmapImage(
    sk_sp<SkImage> image) {
  DCHECK(is_bitmap_backed_);
  image_ = std::move(image);
  OnLock();
}

void GpuImageDecodeCache::DecodedImageData::ResetBitmapImage() {
  DCHECK(is_bitmap_backed_);
  image_ = nullptr;
  image_yuv_planes_.reset();
  OnUnlock();
}

void GpuImageDecodeCache::DecodedImageData::ResetData() {
  if (data_) {
    if (is_yuv()) {
      DCHECK(image_yuv_planes_);
      DCHECK(image_yuv_planes_->at(SkYUVAIndex::kY_Index));
      DCHECK(image_yuv_planes_->at(SkYUVAIndex::kU_Index));
      DCHECK(image_yuv_planes_->at(SkYUVAIndex::kV_Index));
    } else {
      DCHECK(image_);
    }
    ReportUsageStats();
  }
  image_ = nullptr;
  image_yuv_planes_.reset();
  data_ = nullptr;
  OnResetData();
}

void GpuImageDecodeCache::DecodedImageData::ReportUsageStats() const {
  UMA_HISTOGRAM_ENUMERATION("Renderer4.GpuImageDecodeState",
                            static_cast<ImageUsageState>(UsageState()),
                            IMAGE_USAGE_STATE_COUNT);
  UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageDecodeState.FirstLockWasted",
                        usage_stats_.first_lock_wasted);
  if (usage_stats_.first_lock_out_of_raster)
    UMA_HISTOGRAM_BOOLEAN(
        "Renderer4.GpuImageDecodeState.FirstLockWasted.OutOfRaster",
        usage_stats_.first_lock_wasted);
}

GpuImageDecodeCache::UploadedImageData::UploadedImageData() = default;
GpuImageDecodeCache::UploadedImageData::~UploadedImageData() {
  DCHECK(!image());
  DCHECK(!image_yuv_planes_);
  DCHECK(!gl_plane_ids_);
}

void GpuImageDecodeCache::UploadedImageData::SetImage(
    sk_sp<SkImage> image,
    bool represents_yuv_image) {
  DCHECK(mode_ == Mode::kNone);
  DCHECK(!image_);
  DCHECK(!transfer_cache_id_);
  DCHECK(image);

  mode_ = Mode::kSkImage;
  image_ = std::move(image);
  // Calling isTexturedBacked() on the YUV SkImage would flatten it to RGB.
  if (!represents_yuv_image && image_->isTextureBacked()) {
    gl_id_ = GlIdFromSkImage(image_.get());
  } else {
    gl_id_ = 0;
  }
  OnSetLockedData(false /* out_of_raster */);
}

void GpuImageDecodeCache::UploadedImageData::SetYuvImage(
    sk_sp<SkImage> y_image_input,
    sk_sp<SkImage> u_image_input,
    sk_sp<SkImage> v_image_input) {
  DCHECK(!image_yuv_planes_);
  DCHECK(!gl_plane_ids_);
  DCHECK(!transfer_cache_id_);
  DCHECK(y_image_input);
  DCHECK(u_image_input);
  DCHECK(v_image_input);

  mode_ = Mode::kSkImage;
  image_yuv_planes_ = std::array<sk_sp<SkImage>, SkYUVASizeInfo::kMaxCount>();
  image_yuv_planes_->at(SkYUVAIndex::kY_Index) = std::move(y_image_input);
  image_yuv_planes_->at(SkYUVAIndex::kU_Index) = std::move(u_image_input);
  image_yuv_planes_->at(SkYUVAIndex::kV_Index) = std::move(v_image_input);
  if (y_image()->isTextureBacked() && u_image()->isTextureBacked() &&
      v_image()->isTextureBacked()) {
    gl_plane_ids_ = std::array<GrGLuint, SkYUVASizeInfo::kMaxCount>();
    gl_plane_ids_->at(SkYUVAIndex::kY_Index) = GlIdFromSkImage(y_image().get());
    gl_plane_ids_->at(SkYUVAIndex::kU_Index) = GlIdFromSkImage(u_image().get());
    gl_plane_ids_->at(SkYUVAIndex::kV_Index) = GlIdFromSkImage(v_image().get());
  }
}

void GpuImageDecodeCache::UploadedImageData::SetTransferCacheId(uint32_t id) {
  DCHECK(mode_ == Mode::kNone);
  DCHECK(!image_);
  DCHECK(!transfer_cache_id_);

  mode_ = Mode::kTransferCache;
  transfer_cache_id_ = id;
  OnSetLockedData(false /* out_of_raster */);
}

void GpuImageDecodeCache::UploadedImageData::Reset() {
  if (mode_ != Mode::kNone)
    ReportUsageStats();
  mode_ = Mode::kNone;
  image_ = nullptr;
  image_yuv_planes_.reset();
  gl_plane_ids_.reset();
  gl_id_ = 0;
  is_alpha_ = false;
  transfer_cache_id_.reset();
  OnResetData();
}

void GpuImageDecodeCache::UploadedImageData::ReportUsageStats() const {
  UMA_HISTOGRAM_ENUMERATION("Renderer4.GpuImageUploadState",
                            static_cast<ImageUsageState>(UsageState()),
                            IMAGE_USAGE_STATE_COUNT);
  UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageUploadState.FirstLockWasted",
                        usage_stats_.first_lock_wasted);
}

GpuImageDecodeCache::ImageData::ImageData(PaintImage::Id paint_image_id,
                                          DecodedDataMode mode,
                                          size_t size,
                                          SkFilterQuality quality,
                                          int upload_scale_mip_level,
                                          bool needs_mips,
                                          bool is_bitmap_backed,
                                          bool is_yuv_format)
    : paint_image_id(paint_image_id),
      mode(mode),
      size(size),
      quality(quality),
      upload_scale_mip_level(upload_scale_mip_level),
      needs_mips(needs_mips),
      is_bitmap_backed(is_bitmap_backed),
      is_yuv(is_yuv_format),
      decode(is_bitmap_backed) {}

GpuImageDecodeCache::ImageData::~ImageData() {
  // We should never delete ImageData while it is in use or before it has been
  // cleaned up.
  DCHECK_EQ(0u, upload.ref_count);
  DCHECK_EQ(0u, decode.ref_count);
  DCHECK_EQ(false, decode.is_locked());
  // This should always be cleaned up before deleting the image, as it needs to
  // be freed with the GL context lock held.
  DCHECK(!HasUploadedData());
}

bool GpuImageDecodeCache::ImageData::IsGpuOrTransferCache() const {
  return mode == DecodedDataMode::kGpu ||
         mode == DecodedDataMode::kTransferCache;
}

bool GpuImageDecodeCache::ImageData::HasUploadedData() const {
  switch (mode) {
    case DecodedDataMode::kGpu:
      // upload.image() stores the result of MakeFromYUVATextures
      if (upload.image()) {
        // TODO(915968): Be smarter about being able to re-upload planes
        // selectively if only some get deleted from under us.
        DCHECK(!is_yuv || upload.has_yuv_planes());
        return true;
      }
      return false;
    case DecodedDataMode::kTransferCache:
      return !!upload.transfer_cache_id();
    case DecodedDataMode::kCpu:
      return false;
  }
  return false;
}

void GpuImageDecodeCache::ImageData::ValidateBudgeted() const {
  // If the image is budgeted, it must be refed.
  DCHECK(is_budgeted);
  DCHECK_GT(upload.ref_count, 0u);
}

// static
GrGLuint GpuImageDecodeCache::GlIdFromSkImage(const SkImage* image) {
  DCHECK(image->isTextureBacked());
  GrBackendTexture backend_texture =
      image->getBackendTexture(true /* flushPendingGrContextIO */);
  if (!backend_texture.isValid())
    return 0;

  GrGLTextureInfo info;
  if (!backend_texture.getGLTextureInfo(&info))
    return 0;

  return info.fID;
}

GpuImageDecodeCache::GpuImageDecodeCache(
    viz::RasterContextProvider* context,
    bool use_transfer_cache,
    SkColorType color_type,
    size_t max_working_set_bytes,
    int max_texture_size,
    PaintImage::GeneratorClientId generator_client_id,
    sk_sp<SkColorSpace> target_color_space)
    : color_type_(color_type),
      use_transfer_cache_(use_transfer_cache),
      context_(context),
      max_texture_size_(max_texture_size),
      generator_client_id_(generator_client_id),
      persistent_cache_(PersistentCache::NO_AUTO_EVICT),
      max_working_set_bytes_(max_working_set_bytes),
      max_working_set_items_(kMaxItemsInWorkingSet),
      target_color_space_(std::move(target_color_space)) {
  // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
  // Don't register a dump provider in these cases.
  if (base::ThreadTaskRunnerHandle::IsSet()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "cc::GpuImageDecodeCache", base::ThreadTaskRunnerHandle::Get());
  }
  memory_pressure_listener_.reset(
      new base::MemoryPressureListener(base::BindRepeating(
          &GpuImageDecodeCache::OnMemoryPressure, base::Unretained(this))));
}

GpuImageDecodeCache::~GpuImageDecodeCache() {
  // Debugging crbug.com/650234.
  CHECK_EQ(0u, in_use_cache_.size());

  // SetShouldAggressivelyFreeResources will zero our limits and free all
  // outstanding image memory.
  SetShouldAggressivelyFreeResources(true);

  // It is safe to unregister, even if we didn't register in the constructor.
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);

  // TODO(vmpstr): If we don't have a client name, it may cause problems in
  // unittests, since most tests don't set the name but some do. The UMA system
  // expects the name to be always the same. This assertion is violated in the
  // tests that do set the name.
  if (GetClientNameForMetrics()) {
    UMA_HISTOGRAM_CUSTOM_COUNTS(
        base::StringPrintf("Compositing.%s.CachedImagesCount.Gpu",
                           GetClientNameForMetrics()),
        lifetime_max_items_in_cache_, 1, 1000, 20);
  }
}

ImageDecodeCache::TaskResult GpuImageDecodeCache::GetTaskForImageAndRef(
    const DrawImage& draw_image,
    const TracingInfo& tracing_info) {
  DCHECK_EQ(tracing_info.task_type, TaskType::kInRaster);
  return GetTaskForImageAndRefInternal(draw_image, tracing_info,
                                       DecodeTaskType::kPartOfUploadTask);
}

ImageDecodeCache::TaskResult
GpuImageDecodeCache::GetOutOfRasterDecodeTaskForImageAndRef(
    const DrawImage& draw_image) {
  return GetTaskForImageAndRefInternal(
      draw_image, TracingInfo(0, TilePriority::NOW, TaskType::kOutOfRaster),
      DecodeTaskType::kStandAloneDecodeTask);
}

ImageDecodeCache::TaskResult GpuImageDecodeCache::GetTaskForImageAndRefInternal(
    const DrawImage& draw_image,
    const TracingInfo& tracing_info,
    DecodeTaskType task_type) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::GetTaskForImageAndRef");

  if (SkipImage(draw_image))
    return TaskResult(false);

  base::AutoLock lock(lock_);
  const InUseCacheKey cache_key = InUseCacheKey::FromDrawImage(draw_image);
  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  scoped_refptr<ImageData> new_data;
  if (!image_data) {
    // We need an ImageData, create one now.
    new_data = CreateImageData(draw_image);
    image_data = new_data.get();
  } else if (image_data->decode.decode_failure) {
    // We have already tried and failed to decode this image, so just return.
    return TaskResult(false);
  } else if (task_type == DecodeTaskType::kPartOfUploadTask &&
             image_data->upload.task) {
    // We had an existing upload task, ref the image and return the task.
    image_data->ValidateBudgeted();
    RefImage(draw_image, cache_key);
    return TaskResult(image_data->upload.task);
  } else if (task_type == DecodeTaskType::kStandAloneDecodeTask &&
             image_data->decode.stand_alone_task) {
    // We had an existing out of raster task, ref the image and return the task.
    image_data->ValidateBudgeted();
    RefImage(draw_image, cache_key);
    return TaskResult(image_data->decode.stand_alone_task);
  }

  // Ensure that the image we're about to decode/upload will fit in memory, if
  // not already budgeted.
  if (!image_data->is_budgeted && !EnsureCapacity(image_data->size)) {
    // Image will not fit, do an at-raster decode.
    return TaskResult(false);
  }

  // If we had to create new image data, add it to our map now that we know it
  // will fit.
  if (new_data)
    AddToPersistentCache(draw_image, std::move(new_data));

  // Ref the image before creating a task - this ref is owned by the caller, and
  // it is their responsibility to release it by calling UnrefImage.
  RefImage(draw_image, cache_key);

  // If we already have an image and it is locked (or lock-able), just return
  // that. The image must be budgeted before we attempt to lock it.
  DCHECK(image_data->is_budgeted);
  if (image_data->HasUploadedData() &&
      TryLockImage(HaveContextLock::kNo, draw_image, image_data)) {
    return TaskResult(true);
  }

  scoped_refptr<TileTask> task;
  if (task_type == DecodeTaskType::kPartOfUploadTask) {
    // Ref image and create a upload and decode tasks. We will release this ref
    // in UploadTaskCompleted.
    RefImage(draw_image, cache_key);
    task = base::MakeRefCounted<ImageUploadTaskImpl>(
        this, draw_image,
        GetImageDecodeTaskAndRef(draw_image, tracing_info, task_type),
        tracing_info);
    image_data->upload.task = task;
  } else {
    task = GetImageDecodeTaskAndRef(draw_image, tracing_info, task_type);
  }

  return TaskResult(task);
}

void GpuImageDecodeCache::UnrefImage(const DrawImage& draw_image) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::UnrefImage");
  base::AutoLock lock(lock_);
  UnrefImageInternal(draw_image, InUseCacheKey::FromDrawImage(draw_image));
}

bool GpuImageDecodeCache::UseCacheForDrawImage(
    const DrawImage& draw_image) const {
  if (draw_image.paint_image().GetSkImage()->isTextureBacked())
    return false;

  return true;
}

DecodedDrawImage GpuImageDecodeCache::GetDecodedImageForDraw(
    const DrawImage& draw_image) {
  TRACE_EVENT0("cc", "GpuImageDecodeCache::GetDecodedImageForDraw");

  // We are being called during raster. The context lock must already be
  // acquired by the caller.
  CheckContextLockAcquiredIfNecessary();

  // If we're skipping the image, then the filter quality doesn't matter.
  if (SkipImage(draw_image))
    return DecodedDrawImage();

  base::AutoLock lock(lock_);
  const InUseCacheKey cache_key = InUseCacheKey::FromDrawImage(draw_image);
  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  if (!image_data) {
    // We didn't find the image, create a new entry.
    auto data = CreateImageData(draw_image);
    image_data = data.get();
    AddToPersistentCache(draw_image, std::move(data));
  }

  // Ref the image and decode so that they stay alive while we are
  // decoding/uploading.
  // Note that refing the image will attempt to budget the image, if not already
  // done.
  RefImage(draw_image, cache_key);
  RefImageDecode(draw_image, cache_key);

  // We may or may not need to decode and upload the image we've found, the
  // following functions early-out to if we already decoded.
  DecodeImageIfNecessary(draw_image, image_data, TaskType::kInRaster);
  UploadImageIfNecessary(draw_image, image_data);
  // Unref the image decode, but not the image. The image ref will be released
  // in DrawWithImageFinished.
  UnrefImageDecode(draw_image, cache_key);

  if (image_data->mode == DecodedDataMode::kTransferCache) {
    DCHECK(use_transfer_cache_);
    auto id = image_data->upload.transfer_cache_id();
    if (id)
      image_data->upload.mark_used();
    DCHECK(id || image_data->decode.decode_failure);

    SkSize scale_factor = CalculateScaleFactorForMipLevel(
        draw_image, image_data->upload_scale_mip_level);
    DecodedDrawImage decoded_draw_image(
        id, SkSize(), scale_factor, CalculateDesiredFilterQuality(draw_image),
        image_data->needs_mips, image_data->is_budgeted);
    return decoded_draw_image;
  } else {
    DCHECK(!use_transfer_cache_);
    sk_sp<SkImage> image = image_data->upload.image();
    if (image)
      image_data->upload.mark_used();
    DCHECK(image || image_data->decode.decode_failure);

    SkSize scale_factor = CalculateScaleFactorForMipLevel(
        draw_image, image_data->upload_scale_mip_level);
    DecodedDrawImage decoded_draw_image(
        std::move(image), SkSize(), scale_factor,
        CalculateDesiredFilterQuality(draw_image), image_data->is_budgeted);
    return decoded_draw_image;
  }
}

void GpuImageDecodeCache::DrawWithImageFinished(
    const DrawImage& draw_image,
    const DecodedDrawImage& decoded_draw_image) {
  TRACE_EVENT0("cc", "GpuImageDecodeCache::DrawWithImageFinished");

  // Release decoded_draw_image to ensure the referenced SkImage can be
  // cleaned up below.
  { auto delete_decoded_draw_image = std::move(decoded_draw_image); }

  // We are being called during raster. The context lock must already be
  // acquired by the caller.
  CheckContextLockAcquiredIfNecessary();

  if (SkipImage(draw_image))
    return;

  base::AutoLock lock(lock_);
  UnrefImageInternal(draw_image, InUseCacheKey::FromDrawImage(draw_image));

  // We are mid-draw and holding the context lock, ensure we clean up any
  // textures (especially at-raster), which may have just been marked for
  // deletion by UnrefImage.
  RunPendingContextThreadOperations();
}

void GpuImageDecodeCache::ReduceCacheUsage() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::ReduceCacheUsage");
  base::AutoLock lock(lock_);
  EnsureCapacity(0);

  // This is typically called when no tasks are running (between scheduling
  // tasks). Try to lock and run pending operations if possible, but don't
  // block on it.
  if (context_->GetLock() && !context_->GetLock()->Try())
    return;

  RunPendingContextThreadOperations();
  if (context_->GetLock())
    context_->GetLock()->Release();
}

void GpuImageDecodeCache::SetShouldAggressivelyFreeResources(
    bool aggressively_free_resources) {
  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::SetShouldAggressivelyFreeResources",
               "agressive_free_resources", aggressively_free_resources);
  if (aggressively_free_resources) {
    base::Optional<viz::RasterContextProvider::ScopedRasterContextLock>
        context_lock;
    if (context_->GetLock())
      context_lock.emplace(context_);

    base::AutoLock lock(lock_);
    aggressively_freeing_resources_ = aggressively_free_resources;
    EnsureCapacity(0);

    // We are holding the context lock, so finish cleaning up deleted images
    // now.
    RunPendingContextThreadOperations();
  } else {
    base::AutoLock lock(lock_);
    aggressively_freeing_resources_ = aggressively_free_resources;
  }
}

void GpuImageDecodeCache::ClearCache() {
  base::AutoLock lock(lock_);
  for (auto it = persistent_cache_.begin(); it != persistent_cache_.end();)
    it = RemoveFromPersistentCache(it);
  DCHECK(persistent_cache_.empty());
  paint_image_entries_.clear();
}

void GpuImageDecodeCache::AddToPersistentCache(const DrawImage& draw_image,
                                               scoped_refptr<ImageData> data) {
  lock_.AssertAcquired();

  WillAddCacheEntry(draw_image);
  persistent_cache_.Put(draw_image.frame_key(), std::move(data));
}

template <typename Iterator>
Iterator GpuImageDecodeCache::RemoveFromPersistentCache(Iterator it) {
  lock_.AssertAcquired();

  if (it->second->decode.ref_count != 0 || it->second->upload.ref_count != 0) {
    // Orphan the image and erase it from the |persisent_cache_|. This ensures
    // that the image will be deleted once all refs are removed.
    it->second->is_orphaned = true;
  } else {
    // Current entry has no refs. Ensure it is not locked.
    DCHECK(!it->second->decode.is_locked());
    DCHECK(!it->second->upload.is_locked());

    // Unlocked images must not be budgeted.
    DCHECK(!it->second->is_budgeted);

    // Free the uploaded image if it exists.
    if (it->second->HasUploadedData())
      DeleteImage(it->second.get());
  }

  auto entries_it = paint_image_entries_.find(it->second->paint_image_id);
  DCHECK(entries_it != paint_image_entries_.end());
  DCHECK_GT(entries_it->second.count, 0u);

  // If this is the last entry for this image, remove its tracking.
  --entries_it->second.count;
  if (entries_it->second.count == 0u)
    paint_image_entries_.erase(entries_it);

  return persistent_cache_.Erase(it);
}

size_t GpuImageDecodeCache::GetMaximumMemoryLimitBytes() const {
  return max_working_set_bytes_;
}

bool GpuImageDecodeCache::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  using base::trace_event::MemoryAllocatorDumpGuid;
  using base::trace_event::MemoryDumpLevelOfDetail;

  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::OnMemoryDump");

  if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) {
    std::string dump_name = base::StringPrintf(
        "cc/image_memory/cache_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(this));
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes, working_set_bytes_);

    // Early out, no need for more detail in a BACKGROUND dump.
    return true;
  }

  for (const auto& image_pair : persistent_cache_) {
    const ImageData* image_data = image_pair.second.get();
    int image_id = static_cast<int>(image_pair.first.hash());

    // If we have discardable decoded data, dump this here.
    if (image_data->decode.data()) {
      std::string discardable_dump_name = base::StringPrintf(
          "cc/image_memory/cache_0x%" PRIXPTR "/discardable/image_%d",
          reinterpret_cast<uintptr_t>(this), image_id);
      MemoryAllocatorDump* dump =
          image_data->decode.data()->CreateMemoryAllocatorDump(
              discardable_dump_name.c_str(), pmd);
      // Dump the "locked_size" as an additional column.
      // This lets us see the amount of discardable which is contributing to
      // memory pressure.
      size_t locked_size =
          image_data->decode.is_locked() ? image_data->size : 0u;
      dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes,
                      locked_size);
    }

    // If we have an uploaded image (that is actually on the GPU, not just a
    // CPU wrapper), upload it here.
    if (image_data->HasUploadedData() &&
        image_data->mode == DecodedDataMode::kGpu) {
      size_t discardable_size = image_data->size;
      auto* context_support = context_->ContextSupport();
      // If the discardable system has deleted this out from under us, log a
      // size of 0 to match software discardable.
      if (image_data->is_yuv &&
          context_support->ThreadsafeDiscardableTextureIsDeletedForTracing(
              image_data->upload.gl_y_id()) &&
          context_support->ThreadsafeDiscardableTextureIsDeletedForTracing(
              image_data->upload.gl_u_id()) &&
          context_support->ThreadsafeDiscardableTextureIsDeletedForTracing(
              image_data->upload.gl_v_id())) {
        discardable_size = 0;
      } else if (context_support
                     ->ThreadsafeDiscardableTextureIsDeletedForTracing(
                         image_data->upload.gl_id())) {
        discardable_size = 0;
      }

      std::string gpu_dump_name = base::StringPrintf(
          "cc/image_memory/cache_0x%" PRIXPTR "/gpu/image_%d",
          reinterpret_cast<uintptr_t>(this), image_id);
      MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(gpu_dump_name);
      dump->AddScalar(MemoryAllocatorDump::kNameSize,
                      MemoryAllocatorDump::kUnitsBytes, discardable_size);

      // Dump the "locked_size" as an additional column.
      size_t locked_size =
          image_data->upload.is_locked() ? discardable_size : 0u;
      dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes,
                      locked_size);

      // TODO(crbug.com/919296): Dump additional plane information for YUV.
      // Create globally shared GUID(s) to associate this data with its
      // GPU process counterpart.
      MemoryAllocatorDumpGuid guid;
      if (image_data->is_yuv) {  // Choose luma plane for identifying texture.
        guid = gl::GetGLTextureClientGUIDForTracing(
            context_->ContextSupport()->ShareGroupTracingGUID(),
            image_data->upload.gl_y_id());
      } else {
        guid = gl::GetGLTextureClientGUIDForTracing(
            context_->ContextSupport()->ShareGroupTracingGUID(),
            image_data->upload.gl_id());
      }
      // kImportance is somewhat arbitrary - we chose 3 to be higher than the
      // value used in the GPU process (1), and Skia (2), causing us to appear
      // as the owner in memory traces.
      const int kImportance = 3;
      pmd->CreateSharedGlobalAllocatorDump(guid);
      pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
    }
  }

  return true;
}

void GpuImageDecodeCache::DecodeImageInTask(const DrawImage& draw_image,
                                            TaskType task_type) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::DecodeImage");
  base::AutoLock lock(lock_);
  ImageData* image_data = GetImageDataForDrawImage(
      draw_image, InUseCacheKey::FromDrawImage(draw_image));
  DCHECK(image_data);
  DCHECK(image_data->is_budgeted) << "Must budget an image for pre-decoding";
  DecodeImageIfNecessary(draw_image, image_data, task_type);
}

void GpuImageDecodeCache::UploadImageInTask(const DrawImage& draw_image) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::UploadImage");
  base::Optional<viz::RasterContextProvider::ScopedRasterContextLock>
      context_lock;
  if (context_->GetLock())
    context_lock.emplace(context_);

  base::Optional<ScopedGrContextAccess> gr_context_access;
  if (!use_transfer_cache_)
    gr_context_access.emplace(context_);
  base::AutoLock lock(lock_);

  auto cache_key = InUseCacheKey::FromDrawImage(draw_image);
  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  DCHECK(image_data);
  DCHECK(image_data->is_budgeted) << "Must budget an image for pre-decoding";

  if (image_data->is_bitmap_backed)
    DecodeImageIfNecessary(draw_image, image_data, TaskType::kInRaster);
  UploadImageIfNecessary(draw_image, image_data);
}

void GpuImageDecodeCache::OnImageDecodeTaskCompleted(
    const DrawImage& draw_image,
    DecodeTaskType task_type) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::OnImageDecodeTaskCompleted");
  base::AutoLock lock(lock_);
  auto cache_key = InUseCacheKey::FromDrawImage(draw_image);
  // Decode task is complete, remove our reference to it.
  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  DCHECK(image_data);
  if (task_type == DecodeTaskType::kPartOfUploadTask) {
    DCHECK(image_data->decode.task);
    image_data->decode.task = nullptr;
  } else {
    DCHECK(task_type == DecodeTaskType::kStandAloneDecodeTask);
    DCHECK(image_data->decode.stand_alone_task);
    image_data->decode.stand_alone_task = nullptr;
  }

  // While the decode task is active, we keep a ref on the decoded data.
  // Release that ref now.
  UnrefImageDecode(draw_image, cache_key);
}

void GpuImageDecodeCache::OnImageUploadTaskCompleted(
    const DrawImage& draw_image) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::OnImageUploadTaskCompleted");
  base::AutoLock lock(lock_);
  // Upload task is complete, remove our reference to it.
  InUseCacheKey cache_key = InUseCacheKey::FromDrawImage(draw_image);
  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  DCHECK(image_data);
  DCHECK(image_data->upload.task);
  image_data->upload.task = nullptr;

  // While the upload task is active, we keep a ref on both the image it will be
  // populating, as well as the decode it needs to populate it. Release these
  // refs now.
  UnrefImageDecode(draw_image, cache_key);
  UnrefImageInternal(draw_image, cache_key);
}

// Checks if an existing image decode exists. If not, returns a task to produce
// the requested decode.
scoped_refptr<TileTask> GpuImageDecodeCache::GetImageDecodeTaskAndRef(
    const DrawImage& draw_image,
    const TracingInfo& tracing_info,
    DecodeTaskType task_type) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::GetImageDecodeTaskAndRef");
  lock_.AssertAcquired();

  auto cache_key = InUseCacheKey::FromDrawImage(draw_image);

  // This ref is kept alive while an upload task may need this decode. We
  // release this ref in UploadTaskCompleted.
  if (task_type == DecodeTaskType::kPartOfUploadTask)
    RefImageDecode(draw_image, cache_key);

  ImageData* image_data = GetImageDataForDrawImage(draw_image, cache_key);
  DCHECK(image_data);
  // No decode is necessary for bitmap backed images.
  if (image_data->decode.is_locked() || image_data->is_bitmap_backed) {
    // We should never be creating a decode task for a not budgeted image.
    DCHECK(image_data->is_budgeted);
    // We should never be creating a decode for an already-uploaded image.
    DCHECK(!image_data->HasUploadedData());
    return nullptr;
  }

  // We didn't have an existing locked image, create a task to lock or decode.
  scoped_refptr<TileTask>& existing_task =
      (task_type == DecodeTaskType::kPartOfUploadTask)
          ? image_data->decode.task
          : image_data->decode.stand_alone_task;
  if (!existing_task) {
    // Ref image decode and create a decode task. This ref will be released in
    // DecodeTaskCompleted.
    RefImageDecode(draw_image, cache_key);
    existing_task = base::MakeRefCounted<GpuImageDecodeTaskImpl>(
        this, draw_image, tracing_info, task_type);
  }
  return existing_task;
}

void GpuImageDecodeCache::RefImageDecode(const DrawImage& draw_image,
                                         const InUseCacheKey& cache_key) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::RefImageDecode");
  lock_.AssertAcquired();
  auto found = in_use_cache_.find(cache_key);
  DCHECK(found != in_use_cache_.end());
  ++found->second.ref_count;
  ++found->second.image_data->decode.ref_count;
  OwnershipChanged(draw_image, found->second.image_data.get());
}

void GpuImageDecodeCache::UnrefImageDecode(const DrawImage& draw_image,
                                           const InUseCacheKey& cache_key) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::UnrefImageDecode");
  lock_.AssertAcquired();
  auto found = in_use_cache_.find(cache_key);
  DCHECK(found != in_use_cache_.end());
  DCHECK_GT(found->second.image_data->decode.ref_count, 0u);
  DCHECK_GT(found->second.ref_count, 0u);
  --found->second.ref_count;
  --found->second.image_data->decode.ref_count;
  OwnershipChanged(draw_image, found->second.image_data.get());
  if (found->second.ref_count == 0u) {
    in_use_cache_.erase(found);
  }
}

void GpuImageDecodeCache::RefImage(const DrawImage& draw_image,
                                   const InUseCacheKey& cache_key) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::RefImage");
  lock_.AssertAcquired();
  auto found = in_use_cache_.find(cache_key);

  // If no secondary cache entry was found for the given |draw_image|, then
  // the draw_image only exists in the |persistent_cache_|. Create an in-use
  // cache entry now.
  if (found == in_use_cache_.end()) {
    auto found_image = persistent_cache_.Peek(draw_image.frame_key());
    DCHECK(found_image != persistent_cache_.end());
    DCHECK(IsCompatible(found_image->second.get(), draw_image));
    found = in_use_cache_
                .insert(InUseCache::value_type(
                    cache_key, InUseCacheEntry(found_image->second)))
                .first;
  }

  DCHECK(found != in_use_cache_.end());
  ++found->second.ref_count;
  ++found->second.image_data->upload.ref_count;
  OwnershipChanged(draw_image, found->second.image_data.get());
}

void GpuImageDecodeCache::UnrefImageInternal(const DrawImage& draw_image,
                                             const InUseCacheKey& cache_key) {
  lock_.AssertAcquired();
  auto found = in_use_cache_.find(cache_key);
  DCHECK(found != in_use_cache_.end());
  DCHECK_GT(found->second.image_data->upload.ref_count, 0u);
  DCHECK_GT(found->second.ref_count, 0u);
  --found->second.ref_count;
  --found->second.image_data->upload.ref_count;
  OwnershipChanged(draw_image, found->second.image_data.get());
  if (found->second.ref_count == 0u) {
    in_use_cache_.erase(found);
  }
}

// Called any time an image or decode ref count changes. Takes care of any
// necessary memory budget book-keeping and cleanup.
void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image,
                                           ImageData* image_data) {
  lock_.AssertAcquired();

  bool has_any_refs =
      image_data->upload.ref_count > 0 || image_data->decode.ref_count > 0;
  // If we have no image refs on an image, we should unbudget it.
  if (!has_any_refs && image_data->is_budgeted) {
    DCHECK_GE(working_set_bytes_, image_data->size);
    DCHECK_GE(working_set_items_, 1u);
    working_set_bytes_ -= image_data->size;
    working_set_items_ -= 1;
    image_data->is_budgeted = false;
  }

  // Don't keep around completely empty images. This can happen if an image's
  // decode/upload tasks were both cancelled before completing.
  const bool has_cpu_data =
      image_data->decode.data() ||
      (image_data->is_bitmap_backed && image_data->decode.image());
  if (!has_any_refs && !image_data->HasUploadedData() && !has_cpu_data &&
      !image_data->is_orphaned) {
    auto found_persistent = persistent_cache_.Peek(draw_image.frame_key());
    if (found_persistent != persistent_cache_.end())
      RemoveFromPersistentCache(found_persistent);
  }

  // If we have no refs on an uploaded image, it should be unlocked. Do this
  // before any attempts to delete the image.
  if (image_data->IsGpuOrTransferCache() && image_data->upload.ref_count == 0 &&
      image_data->upload.is_locked()) {
    UnlockImage(image_data);
  }

  // Don't keep around orphaned images.
  if (image_data->is_orphaned && !has_any_refs) {
    DeleteImage(image_data);
  }

  // Don't keep CPU images if they are unused, these images can be recreated by
  // re-locking discardable (rather than requiring a full upload like GPU
  // images).
  if (image_data->mode == DecodedDataMode::kCpu && !has_any_refs) {
    DeleteImage(image_data);
  }

  // If we have image that could be budgeted, but isn't, budget it now.
  if (has_any_refs && !image_data->is_budgeted &&
      CanFitInWorkingSet(image_data->size)) {
    working_set_bytes_ += image_data->size;
    working_set_items_ += 1;
    image_data->is_budgeted = true;
  }

  // We should unlock the decoded image memory for the image in two cases:
  // 1) The image is no longer being used (no decode or upload refs).
  // 2) This is a non-CPU image that has already been uploaded and we have
  //    no remaining decode refs.
  bool should_unlock_decode = !has_any_refs || (image_data->HasUploadedData() &&
                                                !image_data->decode.ref_count);

  if (should_unlock_decode && image_data->decode.is_locked()) {
    if (image_data->is_bitmap_backed) {
      DCHECK(!image_data->decode.data());
      image_data->decode.ResetBitmapImage();
    } else {
      DCHECK(image_data->decode.data());
      image_data->decode.Unlock();
    }
  }

  // EnsureCapacity to make sure we are under our cache limits.
  EnsureCapacity(0);

#if DCHECK_IS_ON()
  // Sanity check the above logic.
  if (image_data->HasUploadedData()) {
    if (image_data->mode == DecodedDataMode::kCpu)
      DCHECK(image_data->decode.is_locked());
  } else {
    DCHECK(!image_data->is_budgeted || has_any_refs);
  }
#endif
}

// Checks whether we can fit a new image of size |required_size| in our
// working set. Also frees unreferenced entries to keep us below our preferred
// items limit.
bool GpuImageDecodeCache::EnsureCapacity(size_t required_size) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::EnsureCapacity");
  lock_.AssertAcquired();

  lifetime_max_items_in_cache_ =
      std::max(lifetime_max_items_in_cache_, persistent_cache_.size());

  // While we are over preferred item capacity, we iterate through our set of
  // cached image data in LRU order, removing unreferenced images.
  for (auto it = persistent_cache_.rbegin();
       it != persistent_cache_.rend() && ExceedsPreferredCount();) {
    if (it->second->decode.ref_count != 0 ||
        it->second->upload.ref_count != 0) {
      ++it;
      continue;
    }

    it = RemoveFromPersistentCache(it);
  }

  return CanFitInWorkingSet(required_size);
}

bool GpuImageDecodeCache::CanFitInWorkingSet(size_t size) const {
  lock_.AssertAcquired();

  if (working_set_items_ >= max_working_set_items_)
    return false;

  base::CheckedNumeric<uint32_t> new_size(working_set_bytes_);
  new_size += size;
  if (!new_size.IsValid() || new_size.ValueOrDie() > max_working_set_bytes_)
    return false;

  return true;
}

bool GpuImageDecodeCache::ExceedsPreferredCount() const {
  lock_.AssertAcquired();

  size_t items_limit;
  if (aggressively_freeing_resources_) {
    items_limit = kSuspendedMaxItemsInCacheForGpu;
  } else {
    items_limit = kNormalMaxItemsInCacheForGpu;
  }

  return persistent_cache_.size() > items_limit;
}

void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image,
                                                 ImageData* image_data,
                                                 TaskType task_type) {
  lock_.AssertAcquired();

  DCHECK_GT(image_data->decode.ref_count, 0u);

  if (image_data->decode.decode_failure) {
    // We have already tried and failed to decode this image. Don't try again.
    return;
  }

  if (image_data->HasUploadedData() &&
      TryLockImage(HaveContextLock::kNo, draw_image, image_data)) {
    // We already have an uploaded image, no reason to decode.
    return;
  }

  if (image_data->is_bitmap_backed) {
    DCHECK(!draw_image.paint_image().IsLazyGenerated());
    if (image_data->is_yuv) {
      DLOG(ERROR) << "YUV + Bitmap is unknown and unimplemented!";
      NOTREACHED();
    } else {
      image_data->decode.SetBitmapImage(draw_image.paint_image().GetSkImage());
    }
    return;
  }

  if (image_data->decode.data() &&
      (image_data->decode.is_locked() || image_data->decode.Lock())) {
    // We already decoded this, or we just needed to lock, early out.
    return;
  }

  TRACE_EVENT0("cc", "GpuImageDecodeCache::DecodeImage");
  RecordImageMipLevelUMA(image_data->upload_scale_mip_level);

  image_data->decode.ResetData();
  std::unique_ptr<base::DiscardableMemory> backing_memory;
  sk_sp<SkImage> image;
  // These are used only for decoding into YUV.
  sk_sp<SkImage> image_y;
  sk_sp<SkImage> image_u;
  sk_sp<SkImage> image_v;
  {
    base::AutoUnlock unlock(lock_);
    backing_memory = base::DiscardableMemoryAllocator::GetInstance()
                         ->AllocateLockedDiscardableMemory(image_data->size);
    sk_sp<SkColorSpace> color_space =
        ColorSpaceForImageDecode(draw_image, image_data->mode);
    auto release_proc = [](const void*, void*) {};
    SkImageInfo image_info = CreateImageInfoForDrawImage(
        draw_image, image_data->upload_scale_mip_level);
    SkPixmap pixmap(image_info, backing_memory->data(),
                    image_info.minRowBytes());

    // Set |pixmap| to the desired colorspace to decode into.
    pixmap.setColorSpace(color_space);

    if (image_data->is_yuv) {
      DVLOG(3) << "GpuImageDecodeCache wants to do YUV decoding/rendering";
      SkPixmap pixmap_y;
      SkPixmap pixmap_u;
      SkPixmap pixmap_v;
      if (!DrawAndScaleImage(draw_image, &pixmap, generator_client_id_,
                             image_data->is_yuv, &pixmap_y, &pixmap_u,
                             &pixmap_v)) {
        DLOG(ERROR) << "DrawAndScaleImage failed.";
        backing_memory->Unlock();
        backing_memory.reset();
      } else {
        image_y = SkImage::MakeFromRaster(pixmap_y, release_proc, nullptr);
        image_u = SkImage::MakeFromRaster(pixmap_u, release_proc, nullptr);
        image_v = SkImage::MakeFromRaster(pixmap_v, release_proc, nullptr);
      }
    } else {  // RGBX decoding is the default path.
      if (!DrawAndScaleImage(draw_image, &pixmap, generator_client_id_,
                             image_data->is_yuv)) {
        DLOG(ERROR) << "DrawAndScaleImage failed.";
        backing_memory->Unlock();
        backing_memory.reset();
      } else {
        image = SkImage::MakeFromRaster(pixmap, release_proc, nullptr);
      }
    }
  }

  if (image_data->decode.data()) {
    // An at-raster task decoded this before us. Ingore our decode.
    if (image_data->is_yuv) {
      DCHECK(image_data->decode.y_image());
      DCHECK(image_data->decode.u_image());
      DCHECK(image_data->decode.v_image());
    } else {
      DCHECK(image_data->decode.image());
    }
    return;
  }

  if (!backing_memory) {
    DCHECK(!image);
    DCHECK(!image_y);
    DCHECK(!image_u);
    DCHECK(!image_v);
    // If |backing_memory| was not populated, we had a non-decodable image.
    image_data->decode.decode_failure = true;
    return;
  }

  if (image_data->is_yuv) {
    image_data->decode.SetLockedData(
        std::move(backing_memory), std::move(image_y), std::move(image_u),
        std::move(image_v), task_type == TaskType::kOutOfRaster);
  } else {
    image_data->decode.SetLockedData(std::move(backing_memory),
                                     std::move(image),
                                     task_type == TaskType::kOutOfRaster);
  }
}

void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image,
                                                 ImageData* image_data) {
  CheckContextLockAcquiredIfNecessary();
  lock_.AssertAcquired();

  // We are about to upload a new image and are holding the context lock.
  // Ensure that any images which have been marked for deletion are actually
  // cleaned up so we don't exceed our memory limit during this upload.
  RunPendingContextThreadOperations();

  if (image_data->decode.decode_failure) {
    // We were unable to decode this image. Don't try to upload.
    return;
  }

  // If an upload already exists, try to lock it. If this fails, it will clear
  // any uploaded data.
  if (image_data->HasUploadedData())
    TryLockImage(HaveContextLock::kYes, draw_image, image_data);

  // Ensure the mip status is correct before returning the locked upload or
  // preparing to upload a new image.
  UpdateMipsIfNeeded(draw_image, image_data);

  // If we have uploaded data at this point, it is locked with correct mips,
  // just return.
  if (image_data->HasUploadedData())
    return;

  TRACE_EVENT0("cc", "GpuImageDecodeCache::UploadImage");
  DCHECK(image_data->decode.is_locked());
  DCHECK_GT(image_data->decode.ref_count, 0u);
  DCHECK_GT(image_data->upload.ref_count, 0u);

  image_data->decode.mark_used();
  sk_sp<SkColorSpace> color_space =
      SupportsColorSpaceConversion() ? target_color_space_ : nullptr;
  // The value of |decoded_target_colorspace| takes into account the fact
  // that we might need to ignore an embedded image color space if |color_type_|
  // does not support color space conversions or that color conversion might
  // have happened at decode time.
  sk_sp<SkColorSpace> decoded_target_colorspace =
      ColorSpaceForImageDecode(draw_image, image_data->mode);
  if (color_space && SkColorSpace::Equals(color_space.get(),
                                          decoded_target_colorspace.get())) {
    color_space = nullptr;
  }

  if (image_data->mode == DecodedDataMode::kTransferCache) {
    DCHECK(use_transfer_cache_);
    SkPixmap pixmap;
    if (!image_data->decode.image()->peekPixels(&pixmap))
      return;

    ClientImageTransferCacheEntry image_entry(&pixmap, color_space.get(),
                                              image_data->needs_mips);
    uint32_t size = image_entry.SerializedSize();
    void* data = context_->ContextSupport()->MapTransferCacheEntry(size);
    if (data) {
      bool succeeded = image_entry.Serialize(
          base::make_span(reinterpret_cast<uint8_t*>(data), size));
      DCHECK(succeeded);
      context_->ContextSupport()->UnmapAndCreateTransferCacheEntry(
          image_entry.UnsafeType(), image_entry.Id());
      image_data->upload.SetTransferCacheId(image_entry.Id());
    } else {
      // Transfer cache entry can fail due to a lost gpu context or failure
      // to allocate shared memory.  Handle this gracefully.  Mark this
      // image as "decode failed" so that we do not try to handle it again.
      // If this was a lost context, we'll recreate this image decode cache.
      image_data->decode.decode_failure = true;
    }

    return;
  }

  // If we reached this point, we are in the CPU/GPU path (not transfer cache).
  DCHECK(!use_transfer_cache_);

  // Grab a reference to our decoded image. For the kCpu path, we will use
  // this directly as our "uploaded" data.
  sk_sp<SkImage> uploaded_image = image_data->decode.image();
  GrMipMapped image_needs_mips =
      image_data->needs_mips ? GrMipMapped::kYes : GrMipMapped::kNo;

  if (image_data->is_yuv) {
    // Grab a reference to our decoded image. For the kCpu path, we will use
    // this directly as our "uploaded" data.
    sk_sp<SkImage> uploaded_y_image = image_data->decode.y_image();
    sk_sp<SkImage> uploaded_u_image = image_data->decode.u_image();
    sk_sp<SkImage> uploaded_v_image = image_data->decode.v_image();

    // For kGpu, we upload and color convert (if necessary).
    if (image_data->mode == DecodedDataMode::kGpu) {
      DCHECK(!use_transfer_cache_);
      base::AutoUnlock unlock(lock_);

      // WebP documentation says to use Rec 601 for converting to RGB.
      // TODO(crbug.com/915707): Change QueryYUVA8 to set the colorspace based
      // on image type.
      SkYUVColorSpace yuva_color_space =
          SkYUVColorSpace::kRec601_SkYUVColorSpace;

      uploaded_y_image = uploaded_y_image->makeTextureImage(
          context_->GrContext(), nullptr /* colorspace */, image_needs_mips);
      uploaded_u_image = uploaded_u_image->makeTextureImage(
          context_->GrContext(), nullptr /* colorspace */, image_needs_mips);
      uploaded_v_image = uploaded_v_image->makeTextureImage(
          context_->GrContext(), nullptr /* colorspace */, image_needs_mips);
      if (!uploaded_y_image || !uploaded_u_image || !uploaded_v_image) {
        DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
        return;
      }

      size_t image_width = uploaded_y_image->width();
      size_t image_height = uploaded_y_image->height();
      uploaded_image = CreateImageFromYUVATexturesInternal(
          uploaded_y_image.get(), uploaded_u_image.get(),
          uploaded_v_image.get(), image_width, image_height, &yuva_color_space,
          decoded_target_colorspace);
    }

    // At-raster may have decoded this while we were unlocked. If so, ignore our
    // result.
    if (image_data->HasUploadedData()) {
      if (uploaded_image) {
        DCHECK(uploaded_y_image);
        DCHECK(uploaded_u_image);
        DCHECK(uploaded_v_image);
        // We do not call DeleteSkImageAndPreventCaching for |uploaded_image|
        // because calls to getBackendTexture will flatten the YUV planes to
        // an RGB texture only to immediately delete it.
        DeleteSkImageAndPreventCaching(context_, std::move(uploaded_y_image));
        DeleteSkImageAndPreventCaching(context_, std::move(uploaded_u_image));
        DeleteSkImageAndPreventCaching(context_, std::move(uploaded_v_image));
      }
      return;
    }

    // TODO(crbug.com/740737): |uploaded_image| is sometimes null in certain
    // context-lost situations, so it is handled with an early out.
    if (!uploaded_image || !uploaded_y_image || !uploaded_u_image ||
        !uploaded_v_image) {
      DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
      return;
    }

    uploaded_y_image = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(uploaded_y_image));
    uploaded_u_image = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(uploaded_u_image));
    uploaded_v_image = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(uploaded_v_image));

    image_data->upload.SetImage(std::move(uploaded_image), image_data->is_yuv);
    image_data->upload.SetYuvImage(std::move(uploaded_y_image),
                                   std::move(uploaded_u_image),
                                   std::move(uploaded_v_image));

    // If we have a new GPU-backed image, initialize it for use in the GPU
    // discardable system.
    if (image_data->mode == DecodedDataMode::kGpu) {
      // Notify the discardable system of the planes so they will count against
      // budgets.
      context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
          image_data->upload.gl_y_id());
      context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
          image_data->upload.gl_u_id());
      context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
          image_data->upload.gl_v_id());
    }
    // YUV decoding ends.
    return;
  }

  // RGBX decoding is below.
  // For kGpu, we upload and color convert (if necessary).
  if (image_data->mode == DecodedDataMode::kGpu) {
    DCHECK(!use_transfer_cache_);
    base::AutoUnlock unlock(lock_);
    uploaded_image = MakeTextureImage(context_, std::move(uploaded_image),
                                      color_space, image_needs_mips);
  }

  // At-raster may have decoded this while we were unlocked. If so, ignore our
  // result.
  if (image_data->upload.image()) {
    if (uploaded_image)
      DeleteSkImageAndPreventCaching(context_, std::move(uploaded_image));
    return;
  }

  // Take ownership of any GL texture backing for the SkImage. This allows
  // us to use the image with the discardable system.
  if (uploaded_image) {
    uploaded_image = TakeOwnershipOfSkImageBacking(context_->GrContext(),
                                                   std::move(uploaded_image));
  }

  // TODO(crbug.com/740737): uploaded_image is sometimes null in certain
  // context-lost situations.
  if (!uploaded_image) {
    DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
    return;
  }

  image_data->upload.SetImage(std::move(uploaded_image));

  // If we have a new GPU-backed image, initialize it for use in the GPU
  // discardable system.
  if (image_data->mode == DecodedDataMode::kGpu) {
    // Notify the discardable system of this image so it will count against
    // budgets.
    context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
        image_data->upload.gl_id());
  }
}

scoped_refptr<GpuImageDecodeCache::ImageData>
GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::CreateImageData");
  lock_.AssertAcquired();

  int upload_scale_mip_level = CalculateUploadScaleMipLevel(draw_image);
  bool needs_mips = ShouldGenerateMips(draw_image, upload_scale_mip_level);
  SkImageInfo image_info =
      CreateImageInfoForDrawImage(draw_image, upload_scale_mip_level);

  DecodedDataMode mode;
  if (use_transfer_cache_) {
    mode = DecodedDataMode::kTransferCache;
  } else if (image_info.width() > max_texture_size_ ||
             image_info.height() > max_texture_size_) {
    // Image too large to upload. Try to use SW fallback.
    mode = DecodedDataMode::kCpu;
  } else {
    mode = DecodedDataMode::kGpu;
  }

  size_t data_size = image_info.computeMinByteSize();
  DCHECK(!SkImageInfo::ByteSizeOverflowed(data_size));

  // We need to cache the result of color conversion on the cpu if the image
  // will be color converted during the decode.
  auto decode_color_space = ColorSpaceForImageDecode(draw_image, mode);
  const bool cache_color_conversion_on_cpu =
      decode_color_space &&
      !SkColorSpace::Equals(decode_color_space.get(),
                            draw_image.paint_image().color_space());

  // |is_bitmap_backed| specifies whether the image has pixel data which can
  // directly be used for the upload. This will be the case for non-lazy images
  // used at the original scale. In these cases, we don't internally cache any
  // cpu component for the image.
  // However, if the image will be scaled or color converts on the cpu, we
  // consider it a lazy image and cache the scaled result in discardable memory.
  const bool is_bitmap_backed = !draw_image.paint_image().IsLazyGenerated() &&
                                upload_scale_mip_level == 0 &&
                                !cache_color_conversion_on_cpu;
  const bool is_yuv =
      draw_image.paint_image().IsYuv() && mode == DecodedDataMode::kGpu;

  // TODO(crbug.com/910276): Change after alpha support.
  // TODO(crbug.com/915972): Remove YUV420 assumption.
  if (is_yuv) {
    // We can't use |temp_yuva_size_info| because it doesn't know about
    // any scaling based on mip levels that |image_info| does incorporate.
    size_t y_size_bytes = image_info.width() * image_info.height();
    size_t u_size_bytes =
        ((image_info.width() + 1) / 2) * ((image_info.height() + 1) / 2);
    size_t v_size_bytes = u_size_bytes;
    data_size = y_size_bytes + u_size_bytes + v_size_bytes;
  }

  return base::WrapRefCounted(new ImageData(
      draw_image.paint_image().stable_id(), mode, data_size,
      CalculateDesiredFilterQuality(draw_image), upload_scale_mip_level,
      needs_mips, is_bitmap_backed, is_yuv));
}

void GpuImageDecodeCache::WillAddCacheEntry(const DrawImage& draw_image) {
  // Remove any old entries for this image. We keep at-most 2 ContentIds for a
  // PaintImage (pending and active tree).
  auto& cache_entries =
      paint_image_entries_[draw_image.paint_image().stable_id()];
  cache_entries.count++;

  auto& cached_content_ids = cache_entries.content_ids;
  const PaintImage::ContentId new_content_id =
      draw_image.frame_key().content_id();

  if (cached_content_ids[0] == new_content_id ||
      cached_content_ids[1] == new_content_id) {
    return;
  }

  if (cached_content_ids[0] == PaintImage::kInvalidContentId) {
    cached_content_ids[0] = new_content_id;
    return;
  }

  if (cached_content_ids[1] == PaintImage::kInvalidContentId) {
    cached_content_ids[1] = new_content_id;
    return;
  }

  const PaintImage::ContentId content_id_to_remove =
      std::min(cached_content_ids[0], cached_content_ids[1]);
  const PaintImage::ContentId content_id_to_keep =
      std::max(cached_content_ids[0], cached_content_ids[1]);
  DCHECK_NE(content_id_to_remove, content_id_to_keep);

  for (auto it = persistent_cache_.begin(); it != persistent_cache_.end();) {
    if (it->first.content_id() != content_id_to_remove) {
      ++it;
    } else {
      it = RemoveFromPersistentCache(it);
    }
  }

  // Removing entries from the persistent cache should not erase the tracking
  // for the current paint_image, since we have 2 different content ids for it
  // and only one of them was erased above.
  DCHECK_NE(paint_image_entries_.count(draw_image.paint_image().stable_id()),
            0u);

  cached_content_ids[0] = content_id_to_keep;
  cached_content_ids[1] = new_content_id;
}

void GpuImageDecodeCache::DeleteImage(ImageData* image_data) {
  if (image_data->HasUploadedData()) {
    DCHECK(!image_data->upload.is_locked());
    if (image_data->mode == DecodedDataMode::kGpu) {
      if (image_data->is_yuv) {
        images_pending_deletion_.push_back(image_data->upload.y_image());
        images_pending_deletion_.push_back(image_data->upload.u_image());
        images_pending_deletion_.push_back(image_data->upload.v_image());
        yuv_images_pending_deletion_.push_back(image_data->upload.image());
      } else {
        images_pending_deletion_.push_back(image_data->upload.image());
      }
    }
    if (image_data->mode == DecodedDataMode::kTransferCache)
      ids_pending_deletion_.push_back(*image_data->upload.transfer_cache_id());
  }
  image_data->upload.Reset();
}

void GpuImageDecodeCache::UnlockImage(ImageData* image_data) {
  DCHECK(image_data->HasUploadedData());
  if (image_data->mode == DecodedDataMode::kGpu) {
    if (image_data->is_yuv) {
      images_pending_unlock_.push_back(image_data->upload.y_image().get());
      images_pending_unlock_.push_back(image_data->upload.u_image().get());
      images_pending_unlock_.push_back(image_data->upload.v_image().get());
    } else {
      images_pending_unlock_.push_back(image_data->upload.image().get());
    }
  } else {
    DCHECK(image_data->mode == DecodedDataMode::kTransferCache);
    ids_pending_unlock_.push_back(*image_data->upload.transfer_cache_id());
  }
  image_data->upload.OnUnlock();

  // If we were holding onto an unmipped image for defering deletion, do it now
  // it is guarenteed to have no-refs.
  auto unmipped_image = image_data->upload.take_unmipped_image();
  if (unmipped_image) {
    if (image_data->is_yuv) {
      auto unmipped_y_image = image_data->upload.take_unmipped_y_image();
      auto unmipped_u_image = image_data->upload.take_unmipped_u_image();
      auto unmipped_v_image = image_data->upload.take_unmipped_v_image();
      DCHECK(unmipped_y_image);
      DCHECK(unmipped_u_image);
      DCHECK(unmipped_v_image);
      images_pending_deletion_.push_back(std::move(unmipped_y_image));
      images_pending_deletion_.push_back(std::move(unmipped_u_image));
      images_pending_deletion_.push_back(std::move(unmipped_v_image));
      yuv_images_pending_deletion_.push_back(std::move(unmipped_image));
    } else {
      images_pending_deletion_.push_back(std::move(unmipped_image));
    }
  }
}

// We always run pending operations in the following order:
//   Lock > Unlock > Delete
// This ensures that:
//   a) We never fully unlock an image that's pending lock (lock before unlock)
//   b) We never delete an image that has pending locks/unlocks.
// As this can be run at-raster, to unlock/delete an image that was just used,
// we need to call GlIdFromSkImage, which flushes pending IO on the image,
// rather than just using a cached GL ID.
// YUV images are handled slightly differently because they are backed by
// texture images but are not themselves registered with the discardable memory
// system. We wait to delete the pointer to a YUV image until we have a context
// lock and its textures have been deleted.
void GpuImageDecodeCache::RunPendingContextThreadOperations() {
  CheckContextLockAcquiredIfNecessary();
  lock_.AssertAcquired();

  for (auto* image : images_pending_complete_lock_) {
    context_->ContextSupport()->CompleteLockDiscardableTexureOnContextThread(
        GlIdFromSkImage(image));
  }
  images_pending_complete_lock_.clear();

  for (auto* image : images_pending_unlock_) {
    context_->ContextGL()->UnlockDiscardableTextureCHROMIUM(
        GlIdFromSkImage(image));
  }
  images_pending_unlock_.clear();

  for (auto id : ids_pending_unlock_) {
    context_->ContextSupport()->UnlockTransferCacheEntries({std::make_pair(
        static_cast<uint32_t>(TransferCacheEntryType::kImage), id)});
  }
  ids_pending_unlock_.clear();

  yuv_images_pending_deletion_.clear();

  for (auto& image : images_pending_deletion_) {
    uint32_t texture_id = GlIdFromSkImage(image.get());
    if (context_->ContextGL()->LockDiscardableTextureCHROMIUM(texture_id)) {
      context_->ContextGL()->DeleteTextures(1, &texture_id);
    }
  }
  images_pending_deletion_.clear();

  for (auto id : ids_pending_deletion_) {
    if (context_->ContextSupport()->ThreadsafeLockTransferCacheEntry(
            static_cast<uint32_t>(TransferCacheEntryType::kImage), id)) {
      context_->ContextSupport()->DeleteTransferCacheEntry(
          static_cast<uint32_t>(TransferCacheEntryType::kImage), id);
    }
  }
  ids_pending_deletion_.clear();
}

SkImageInfo GpuImageDecodeCache::CreateImageInfoForDrawImage(
    const DrawImage& draw_image,
    int upload_scale_mip_level) const {
  gfx::Size mip_size =
      CalculateSizeForMipLevel(draw_image, upload_scale_mip_level);
  return SkImageInfo::Make(mip_size.width(), mip_size.height(), color_type_,
                           kPremul_SkAlphaType);
}

bool GpuImageDecodeCache::TryLockImage(HaveContextLock have_context_lock,
                                       const DrawImage& draw_image,
                                       ImageData* data) {
  DCHECK(data->HasUploadedData());

  if (data->upload.is_locked())
    return true;

  if (data->mode == DecodedDataMode::kTransferCache) {
    DCHECK(use_transfer_cache_);
    DCHECK(data->upload.transfer_cache_id());
    if (context_->ContextSupport()->ThreadsafeLockTransferCacheEntry(
            static_cast<uint32_t>(TransferCacheEntryType::kImage),
            *data->upload.transfer_cache_id())) {
      data->upload.OnLock();
      return true;
    }
  } else if (have_context_lock == HaveContextLock::kYes) {
    auto* gl_context = context_->ContextGL();
    // If |have_context_lock|, we can immediately lock the image and send
    // the lock command to the GPU process.
    // TODO(crbug.com/914622): Add Chrome GL extension to upload texture array.
    if (data->is_yuv &&
        gl_context->LockDiscardableTextureCHROMIUM(data->upload.gl_y_id()) &&
        gl_context->LockDiscardableTextureCHROMIUM(data->upload.gl_u_id()) &&
        gl_context->LockDiscardableTextureCHROMIUM(data->upload.gl_v_id())) {
      DCHECK(!use_transfer_cache_);
      DCHECK(data->mode == DecodedDataMode::kGpu);
      data->upload.OnLock();
      return true;
    } else if (!(data->is_yuv) && gl_context->LockDiscardableTextureCHROMIUM(
                                      data->upload.gl_id())) {
      DCHECK(!use_transfer_cache_);
      DCHECK(data->mode == DecodedDataMode::kGpu);
      data->upload.OnLock();
      return true;
    }
  } else {
    // If !|have_context_lock|, we use
    // ThreadsafeShallowLockDiscardableTexture. This takes a reference to the
    // image, ensuring that it can't be deleted by the service, but delays
    // sending a lock command over the command buffer. This command must be
    // sent before the image is used, but is now guaranteed to succeed. We
    // will send this command via
    // CompleteLockDiscardableTextureOnContextThread in
    // UploadImageIfNecessary, which is guaranteed to run before the texture
    // is used.
    auto* context_support = context_->ContextSupport();
    if (data->is_yuv &&
        context_support->ThreadSafeShallowLockDiscardableTexture(
            data->upload.gl_y_id()) &&
        context_support->ThreadSafeShallowLockDiscardableTexture(
            data->upload.gl_u_id()) &&
        context_support->ThreadSafeShallowLockDiscardableTexture(
            data->upload.gl_v_id())) {
      DCHECK(!use_transfer_cache_);
      DCHECK(data->mode == DecodedDataMode::kGpu);
      data->upload.OnLock();
      images_pending_complete_lock_.push_back(data->upload.y_image().get());
      images_pending_complete_lock_.push_back(data->upload.u_image().get());
      images_pending_complete_lock_.push_back(data->upload.v_image().get());
      return true;
    } else if (!(data->is_yuv) &&
               context_support->ThreadSafeShallowLockDiscardableTexture(
                   data->upload.gl_id())) {
      DCHECK(!use_transfer_cache_);
      DCHECK(data->mode == DecodedDataMode::kGpu);
      data->upload.OnLock();
      images_pending_complete_lock_.push_back(data->upload.image().get());
      return true;
    }
  }

  // Couldn't lock, abandon the image.
  DeleteImage(data);
  return false;
}

// Tries to find an ImageData that can be used to draw the provided
// |draw_image|. First looks for an exact entry in our |in_use_cache_|. If one
// cannot be found, it looks for a compatible entry in our |persistent_cache_|.
GpuImageDecodeCache::ImageData* GpuImageDecodeCache::GetImageDataForDrawImage(
    const DrawImage& draw_image,
    const InUseCacheKey& key) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "GpuImageDecodeCache::GetImageDataForDrawImage");
  lock_.AssertAcquired();
  DCHECK(UseCacheForDrawImage(draw_image));

  auto found_in_use = in_use_cache_.find(key);
  if (found_in_use != in_use_cache_.end())
    return found_in_use->second.image_data.get();

  auto found_persistent = persistent_cache_.Get(draw_image.frame_key());
  if (found_persistent != persistent_cache_.end()) {
    ImageData* image_data = found_persistent->second.get();
    if (IsCompatible(image_data, draw_image)) {
      return image_data;
    } else {
      RemoveFromPersistentCache(found_persistent);
    }
  }

  return nullptr;
}

// Determines if we can draw the provided |draw_image| using the provided
// |image_data|. This is true if the |image_data| is not scaled, or if it
// is scaled at an equal or larger scale and equal or larger quality to
// the provided |draw_image|.
bool GpuImageDecodeCache::IsCompatible(const ImageData* image_data,
                                       const DrawImage& draw_image) const {
  bool is_scaled = image_data->upload_scale_mip_level != 0;
  bool scale_is_compatible = CalculateUploadScaleMipLevel(draw_image) >=
                             image_data->upload_scale_mip_level;
  bool quality_is_compatible =
      CalculateDesiredFilterQuality(draw_image) <= image_data->quality;
  if (is_scaled && (!scale_is_compatible || !quality_is_compatible))
    return false;
  return true;
}

size_t GpuImageDecodeCache::GetDrawImageSizeForTesting(const DrawImage& image) {
  base::AutoLock lock(lock_);
  scoped_refptr<ImageData> data = CreateImageData(image);
  return data->size;
}

void GpuImageDecodeCache::SetImageDecodingFailedForTesting(
    const DrawImage& image) {
  base::AutoLock lock(lock_);
  auto found = persistent_cache_.Peek(image.frame_key());
  DCHECK(found != persistent_cache_.end());
  ImageData* image_data = found->second.get();
  image_data->decode.decode_failure = true;
}

bool GpuImageDecodeCache::DiscardableIsLockedForTesting(
    const DrawImage& image) {
  base::AutoLock lock(lock_);
  auto found = persistent_cache_.Peek(image.frame_key());
  DCHECK(found != persistent_cache_.end());
  ImageData* image_data = found->second.get();
  return image_data->decode.is_locked();
}

bool GpuImageDecodeCache::IsInInUseCacheForTesting(
    const DrawImage& image) const {
  auto found = in_use_cache_.find(InUseCacheKey::FromDrawImage(image));
  return found != in_use_cache_.end();
}

bool GpuImageDecodeCache::IsInPersistentCacheForTesting(
    const DrawImage& image) const {
  auto found = persistent_cache_.Peek(image.frame_key());
  return found != persistent_cache_.end();
}

sk_sp<SkImage> GpuImageDecodeCache::GetSWImageDecodeForTesting(
    const DrawImage& image) {
  base::AutoLock lock(lock_);
  auto found = persistent_cache_.Peek(image.frame_key());
  DCHECK(found != persistent_cache_.end());
  ImageData* image_data = found->second.get();
  DCHECK(!image_data->is_yuv);
  return image_data->decode.ImageForTesting();
}

sk_sp<SkImage> GpuImageDecodeCache::GetUploadedPlaneForTesting(
    const DrawImage& draw_image,
    size_t index) {
  base::AutoLock lock(lock_);
  ImageData* image_data = GetImageDataForDrawImage(
      draw_image, InUseCacheKey::FromDrawImage(draw_image));
  switch (index) {
    case SkYUVAIndex::kY_Index:
      return image_data->upload.y_image();
    case SkYUVAIndex::kU_Index:
      return image_data->upload.u_image();
    case SkYUVAIndex::kV_Index:
      return image_data->upload.v_image();
    default:
      return nullptr;
  }
}

void GpuImageDecodeCache::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  base::AutoLock lock(lock_);
  switch (level) {
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
      break;
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
      base::AutoReset<bool> reset(&aggressively_freeing_resources_, true);
      EnsureCapacity(0);
      break;
  }
}

bool GpuImageDecodeCache::SupportsColorSpaceConversion() const {
  switch (color_type_) {
    case kRGBA_8888_SkColorType:
    case kBGRA_8888_SkColorType:
    case kRGBA_F16_SkColorType:
      return true;
    default:
      return false;
  }
}

sk_sp<SkColorSpace> GpuImageDecodeCache::ColorSpaceForImageDecode(
    const DrawImage& image,
    DecodedDataMode mode) const {
  if (!SupportsColorSpaceConversion())
    return nullptr;

  if (mode == DecodedDataMode::kCpu)
    return target_color_space_;

  // For kGpu or kTransferCache images color conversion is handled during
  // upload, so keep the original colorspace here.
  return sk_ref_sp(image.paint_image().color_space());
}

void GpuImageDecodeCache::CheckContextLockAcquiredIfNecessary() {
  if (!context_->GetLock())
    return;
  context_->GetLock()->AssertAcquired();
}

sk_sp<SkImage> GpuImageDecodeCache::CreateImageFromYUVATexturesInternal(
    const SkImage* uploaded_y_image,
    const SkImage* uploaded_u_image,
    const SkImage* uploaded_v_image,
    const size_t image_width,
    const size_t image_height,
    const SkYUVColorSpace* yuva_color_space,
    sk_sp<SkColorSpace> decoded_color_space) const {
  DCHECK(uploaded_y_image);
  DCHECK(uploaded_u_image);
  DCHECK(uploaded_v_image);
  DCHECK(yuva_color_space);
  GrSurfaceOrigin origin_temp = kTopLeft_GrSurfaceOrigin;
  GrBackendTexture yuv_textures[3]{};
  yuv_textures[0] = uploaded_y_image->getBackendTexture(false);
  yuv_textures[1] = uploaded_u_image->getBackendTexture(false);
  yuv_textures[2] = uploaded_v_image->getBackendTexture(false);

  SkYUVAIndex indices[SkYUVAIndex::kIndexCount];
  indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR};
  indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR};
  indices[SkYUVAIndex::kV_Index] = {2, SkColorChannel::kR};
  indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR};

  sk_sp<SkColorSpace> target_color_space =
      SupportsColorSpaceConversion() ? target_color_space_ : nullptr;
  if (target_color_space && SkColorSpace::Equals(target_color_space.get(),
                                                 decoded_color_space.get())) {
    target_color_space = nullptr;
  }

  sk_sp<SkImage> yuva_image = SkImage::MakeFromYUVATextures(
      context_->GrContext(), *yuva_color_space, yuv_textures, indices,
      SkISize::Make(image_width, image_height), origin_temp,
      std::move(decoded_color_space));
  if (target_color_space)
    return yuva_image->makeColorSpace(target_color_space);

  return yuva_image;
}

void GpuImageDecodeCache::UpdateMipsIfNeeded(const DrawImage& draw_image,
                                             ImageData* image_data) {
  CheckContextLockAcquiredIfNecessary();
  // If we already have mips, nothing to do.
  if (image_data->needs_mips)
    return;

  bool needs_mips =
      ShouldGenerateMips(draw_image, image_data->upload_scale_mip_level);
  if (!needs_mips)
    return;

  image_data->needs_mips = true;

  // If we have no uploaded image, nothing to do other than update needs_mips.
  // Mips will be generated during later upload.
  if (!image_data->HasUploadedData() ||
      image_data->mode != DecodedDataMode::kGpu)
    return;

  if (image_data->is_yuv) {
    // Need to generate mips. Take a reference on the planes we're about to
    // delete, delaying deletion.
    // TODO(crbug.com/910276): Change after alpha support.
    sk_sp<SkImage> previous_y_image = image_data->upload.y_image();
    sk_sp<SkImage> previous_u_image = image_data->upload.u_image();
    sk_sp<SkImage> previous_v_image = image_data->upload.v_image();

    // Generate a new image from the previous, adding mips.
    sk_sp<SkImage> image_y_with_mips = previous_y_image->makeTextureImage(
        context_->GrContext(), nullptr, GrMipMapped::kYes);
    sk_sp<SkImage> image_u_with_mips = previous_u_image->makeTextureImage(
        context_->GrContext(), nullptr, GrMipMapped::kYes);
    sk_sp<SkImage> image_v_with_mips = previous_v_image->makeTextureImage(
        context_->GrContext(), nullptr, GrMipMapped::kYes);

    // Handle lost context.
    if (!image_y_with_mips || !image_u_with_mips || !image_v_with_mips) {
      DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
      return;
    }

    // No need to do anything if mipping this image results in the same
    // textures. Deleting it below will result in lifetime issues.
    // We expect that if one plane mips the same, the others should as well.
    if (GlIdFromSkImage(image_y_with_mips.get()) ==
            image_data->upload.gl_y_id() &&
        GlIdFromSkImage(image_u_with_mips.get()) ==
            image_data->upload.gl_u_id() &&
        GlIdFromSkImage(image_v_with_mips.get()) ==
            image_data->upload.gl_v_id())
      return;

    // Skia owns our new image planes, take ownership.
    sk_sp<SkImage> image_y_with_mips_owned = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(image_y_with_mips));
    sk_sp<SkImage> image_u_with_mips_owned = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(image_u_with_mips));
    sk_sp<SkImage> image_v_with_mips_owned = TakeOwnershipOfSkImageBacking(
        context_->GrContext(), std::move(image_v_with_mips));

    // Handle lost context
    if (!image_y_with_mips_owned || !image_u_with_mips_owned ||
        !image_v_with_mips_owned) {
      DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
      return;
    }

    // WebP documentation says to use Rec 601 for converting to RGB.
    // TODO(crbug.com/915707): Change QueryYUVA8 to set the colorspace based
    // on image type.
    SkYUVColorSpace yuva_color_space = SkYUVColorSpace::kRec601_SkYUVColorSpace;
    size_t width = image_y_with_mips_owned->width();
    size_t height = image_y_with_mips_owned->height();
    sk_sp<SkColorSpace> decoded_color_space =
        ColorSpaceForImageDecode(draw_image, image_data->mode);
    sk_sp<SkImage> yuv_image_with_mips_owned =
        CreateImageFromYUVATexturesInternal(
            image_y_with_mips_owned.get(), image_u_with_mips_owned.get(),
            image_v_with_mips_owned.get(), width, height, &yuva_color_space,
            decoded_color_space);
    // In case of lost context
    if (!yuv_image_with_mips_owned) {
      DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
      return;
    }

    // The previous images might be in the in-use cache, potentially held
    // externally. We must defer deleting them until the entry is unlocked.
    image_data->upload.set_unmipped_image(image_data->upload.image());
    image_data->upload.set_unmipped_yuv_images(image_data->upload.y_image(),
                                               image_data->upload.u_image(),
                                               image_data->upload.v_image());

    // Set the new image on the cache.
    image_data->upload.Reset();
    image_data->upload.SetImage(std::move(yuv_image_with_mips_owned));
    image_data->upload.SetYuvImage(std::move(image_y_with_mips_owned),
                                   std::move(image_u_with_mips_owned),
                                   std::move(image_v_with_mips_owned));
    context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
        image_data->upload.gl_y_id());
    context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
        image_data->upload.gl_u_id());
    context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
        image_data->upload.gl_v_id());
    return;  // End YUV mip mapping.
  }
  // Begin RGBX mip mapping.
  // Need to generate mips. Take a reference on the image we're about to
  // delete, delaying deletion.
  sk_sp<SkImage> previous_image = image_data->upload.image();

  // Generate a new image from the previous, adding mips.
  sk_sp<SkImage> image_with_mips = previous_image->makeTextureImage(
      context_->GrContext(), nullptr, GrMipMapped::kYes);

  // Handle lost context.
  if (!image_with_mips) {
    DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
    return;
  }

  // No need to do anything if mipping this image results in the same texture.
  // Deleting it below will result in lifetime issues.
  if (GlIdFromSkImage(image_with_mips.get()) == image_data->upload.gl_id())
    return;

  // Skia owns our new image, take ownership.
  sk_sp<SkImage> image_with_mips_owned = TakeOwnershipOfSkImageBacking(
      context_->GrContext(), std::move(image_with_mips));

  // Handle lost context
  if (!image_with_mips_owned) {
    DLOG(WARNING) << "TODO(crbug.com/740737): Context was lost. Early out.";
    return;
  }

  // The previous image might be in the in-use cache, potentially held
  // externally. We must defer deleting it until the entry is unlocked.
  image_data->upload.set_unmipped_image(image_data->upload.image());

  // Set the new image on the cache.
  image_data->upload.Reset();
  image_data->upload.SetImage(std::move(image_with_mips_owned));
  context_->ContextGL()->InitializeDiscardableTextureCHROMIUM(
      image_data->upload.gl_id());
}

}  // namespace cc
