// Copyright 2015 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/paint/discardable_image_map.h"

#include <stddef.h>

#include <algorithm>
#include <limits>

#include "base/auto_reset.h"
#include "base/containers/adapters.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/trace_event/trace_event.h"
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_op_buffer.h"
#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"

namespace cc {
namespace {
const int kMaxRectsSize = 256;

SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
  SkRect dst;
  matrix.mapRect(&dst, src);
  return dst;
}

// This canvas is used only for tracking transform/clip/filter state from the
// non-drawing ops.
class PaintTrackingCanvas final : public SkNoDrawCanvas {
 public:
  PaintTrackingCanvas(int width, int height) : SkNoDrawCanvas(width, height) {}
  ~PaintTrackingCanvas() override = default;

  bool ComputePaintBounds(const SkRect& rect,
                          const SkPaint* current_paint,
                          SkRect* paint_bounds) {
    *paint_bounds = rect;
    if (current_paint) {
      if (!current_paint->canComputeFastBounds())
        return false;
      *paint_bounds =
          current_paint->computeFastBounds(*paint_bounds, paint_bounds);
    }

    for (const auto& paint : base::Reversed(saved_paints_)) {
      if (!paint.canComputeFastBounds())
        return false;
      *paint_bounds = paint.computeFastBounds(*paint_bounds, paint_bounds);
    }

    return true;
  }

 private:
  // SkNoDrawCanvas overrides.
  SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
    saved_paints_.push_back(rec.fPaint ? *rec.fPaint : SkPaint());
    return SkNoDrawCanvas::getSaveLayerStrategy(rec);
  }

  void willSave() override {
    saved_paints_.push_back(SkPaint());
    return SkNoDrawCanvas::willSave();
  }

  void willRestore() override {
    DCHECK_GT(saved_paints_.size(), 0u);
    saved_paints_.pop_back();
    SkNoDrawCanvas::willRestore();
  }

  std::vector<SkPaint> saved_paints_;
};

class DiscardableImageGenerator {
 public:
  DiscardableImageGenerator(int width,
                            int height,
                            const PaintOpBuffer* buffer) {
    PaintTrackingCanvas canvas(width, height);
    GatherDiscardableImages(buffer, nullptr, &canvas);
  }
  ~DiscardableImageGenerator() = default;

  std::vector<std::pair<DrawImage, gfx::Rect>> TakeImages() {
    return std::move(image_set_);
  }
  base::flat_map<PaintImage::Id, DiscardableImageMap::Rects>
  TakeImageIdToRectsMap() {
    return std::move(image_id_to_rects_);
  }
  base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
  TakeDecodingModeMap() {
    return std::move(decoding_mode_map_);
  }
  std::vector<DiscardableImageMap::AnimatedImageMetadata>
  TakeAnimatedImagesMetadata() {
    return std::move(animated_images_metadata_);
  }

  void RecordColorHistograms() const {
    if (color_stats_total_image_count_ > 0) {
      int srgb_image_percent = (100 * color_stats_srgb_image_count_) /
                               color_stats_total_image_count_;
      UMA_HISTOGRAM_PERCENTAGE("Renderer4.ImagesPercentSRGB",
                               srgb_image_percent);
    }

    base::CheckedNumeric<int> srgb_pixel_percent =
        100 * color_stats_srgb_pixel_count_ / color_stats_total_pixel_count_;
    if (srgb_pixel_percent.IsValid()) {
      UMA_HISTOGRAM_PERCENTAGE("Renderer4.ImagePixelsPercentSRGB",
                               srgb_pixel_percent.ValueOrDie());
    }
  }

  bool all_images_are_srgb() const {
    return color_stats_srgb_image_count_ == color_stats_total_image_count_;
  }

 private:
  class ImageGatheringProvider : public ImageProvider {
   public:
    ImageGatheringProvider(DiscardableImageGenerator* generator,
                           const gfx::Rect& op_rect)
        : generator_(generator), op_rect_(op_rect) {}
    ~ImageGatheringProvider() override = default;

    ScopedResult GetRasterContent(const DrawImage& draw_image) override {
      generator_->AddImage(draw_image.paint_image(),
                           SkRect::Make(draw_image.src_rect()), op_rect_,
                           SkMatrix::I(), draw_image.filter_quality());
      return ScopedResult();
    }

   private:
    DiscardableImageGenerator* generator_;
    gfx::Rect op_rect_;
  };

  // Adds discardable images from |buffer| to the set of images tracked by
  // this generator. If |buffer| is being used in a DrawOp that requires
  // rasterization of the buffer as a pre-processing step for execution of the
  // op (for instance, with PaintRecord backed PaintShaders),
  // |top_level_op_rect| is set to the rect for that op. If provided, the
  // |top_level_op_rect| will be used as the rect for tracking the position of
  // this image in the top-level buffer.
  void GatherDiscardableImages(const PaintOpBuffer* buffer,
                               const gfx::Rect* top_level_op_rect,
                               PaintTrackingCanvas* canvas) {
    if (!buffer->HasDiscardableImages())
      return;

    // Prevent PaintOpBuffers from having side effects back into the canvas.
    SkAutoCanvasRestore save_restore(canvas, true);

    PlaybackParams params(nullptr, canvas->getTotalMatrix());
    // TODO(khushalsagar): Optimize out save/restore blocks if there are no
    // images in the draw ops between them.
    for (auto* op : PaintOpBuffer::Iterator(buffer)) {
      // We need to play non-draw ops on the SkCanvas since they can affect the
      // transform/clip state.
      if (!op->IsDrawOp())
        op->Raster(canvas, params);

      if (!PaintOp::OpHasDiscardableImages(op))
        continue;

      gfx::Rect op_rect;
      base::Optional<gfx::Rect> local_op_rect;

      if (top_level_op_rect) {
        op_rect = *top_level_op_rect;
      } else {
        local_op_rect = ComputePaintRect(op, canvas);
        if (local_op_rect.value().IsEmpty())
          continue;

        op_rect = local_op_rect.value();
      }

      const SkMatrix& ctm = canvas->getTotalMatrix();
      if (op->IsPaintOpWithFlags()) {
        AddImageFromFlags(op_rect,
                          static_cast<const PaintOpWithFlags*>(op)->flags, ctm);
      }

      PaintOpType op_type = static_cast<PaintOpType>(op->type);
      if (op_type == PaintOpType::DrawImage) {
        auto* image_op = static_cast<DrawImageOp*>(op);
        AddImage(
            image_op->image,
            SkRect::MakeIWH(image_op->image.width(), image_op->image.height()),
            op_rect, ctm, image_op->flags.getFilterQuality());
      } else if (op_type == PaintOpType::DrawImageRect) {
        auto* image_rect_op = static_cast<DrawImageRectOp*>(op);
        SkMatrix matrix = ctm;
        matrix.postConcat(SkMatrix::MakeRectToRect(image_rect_op->src,
                                                   image_rect_op->dst,
                                                   SkMatrix::kFill_ScaleToFit));
        AddImage(image_rect_op->image, image_rect_op->src, op_rect, matrix,
                 image_rect_op->flags.getFilterQuality());
      } else if (op_type == PaintOpType::DrawRecord) {
        GatherDiscardableImages(
            static_cast<const DrawRecordOp*>(op)->record.get(),
            top_level_op_rect, canvas);
      }
    }
  }

  // Given the |op_rect|, which is the rect for the draw op, returns the
  // transformed rect accounting for the current transform, clip and paint
  // state on |canvas_|.
  gfx::Rect ComputePaintRect(const PaintOp* op, PaintTrackingCanvas* canvas) {
    const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds());
    const SkMatrix& ctm = canvas->getTotalMatrix();

    gfx::Rect transformed_rect;
    SkRect op_rect;
    if (!op->IsDrawOp() || !PaintOp::GetBounds(op, &op_rect)) {
      // If we can't provide a conservative bounding rect for the op, assume it
      // covers the complete current clip.
      // TODO(khushalsagar): See if we can do something better for non-draw ops.
      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(clip_rect));
    } else {
      const PaintFlags* flags =
          op->IsPaintOpWithFlags()
              ? &static_cast<const PaintOpWithFlags*>(op)->flags
              : nullptr;
      SkPaint paint;
      if (flags)
        paint = flags->ToSkPaint();

      SkRect paint_rect = MapRect(ctm, op_rect);
      bool computed_paint_bounds =
          canvas->ComputePaintBounds(paint_rect, &paint, &paint_rect);
      if (!computed_paint_bounds) {
        // TODO(vmpstr): UMA this case.
        paint_rect = clip_rect;
      }

      // Clamp the image rect by the current clip rect.
      if (!paint_rect.intersect(clip_rect))
        return gfx::Rect();

      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect));
    }

    // During raster, we use the device clip bounds on the canvas, which outsets
    // the actual clip by 1 due to the possibility of antialiasing. Account for
    // this here by outsetting the image rect by 1. Note that this only affects
    // queries into the rtree, which will now return images that only touch the
    // bounds of the query rect.
    //
    // Note that it's not sufficient for us to inset the device clip bounds at
    // raster time, since we might be sending a larger-than-one-item display
    // item to skia, which means that skia will internally determine whether to
    // raster the picture (using device clip bounds that are outset).
    transformed_rect.Inset(-1, -1);
    return transformed_rect;
  }

  void AddImageFromFlags(const gfx::Rect& op_rect,
                         const PaintFlags& flags,
                         const SkMatrix& ctm) {
    AddImageFromShader(op_rect, flags.getShader(), ctm,
                       flags.getFilterQuality());
    AddImageFromFilter(op_rect, flags.getImageFilter().get());
  }

  void AddImageFromShader(const gfx::Rect& op_rect,
                          const PaintShader* shader,
                          const SkMatrix& ctm,
                          SkFilterQuality filter_quality) {
    if (!shader || !shader->has_discardable_images())
      return;

    if (shader->shader_type() == PaintShader::Type::kImage) {
      const PaintImage& paint_image = shader->paint_image();
      SkMatrix matrix = ctm;
      matrix.postConcat(shader->GetLocalMatrix());
      AddImage(paint_image,
               SkRect::MakeWH(paint_image.width(), paint_image.height()),
               op_rect, matrix, filter_quality);
      return;
    }

    if (shader->shader_type() == PaintShader::Type::kPaintRecord) {
      // For record backed shaders, only analyze them if they have animated
      // images.
      if (shader->image_analysis_state() ==
          ImageAnalysisState::kNoAnimatedImages) {
        return;
      }

      SkRect scaled_tile_rect;
      if (!shader->GetRasterizationTileRect(ctm, &scaled_tile_rect)) {
        return;
      }

      PaintTrackingCanvas canvas(scaled_tile_rect.width(),
                                 scaled_tile_rect.height());
      canvas.setMatrix(SkMatrix::MakeRectToRect(
          shader->tile(), scaled_tile_rect, SkMatrix::kFill_ScaleToFit));
      base::AutoReset<bool> auto_reset(&only_gather_animated_images_, true);
      size_t prev_image_set_size = image_set_.size();
      GatherDiscardableImages(shader->paint_record().get(), &op_rect, &canvas);

      // We only track animated images for PaintShaders. If we added any entry
      // to the |image_set_|, this shader any has animated images.
      // Note that it is thread-safe to set the |has_animated_images| bit on
      // PaintShader here since the analysis is done on the main thread, before
      // the PaintOpBuffer is used for rasterization.
      DCHECK_GE(image_set_.size(), prev_image_set_size);
      const bool has_animated_images = image_set_.size() > prev_image_set_size;
      const_cast<PaintShader*>(shader)->set_has_animated_images(
          has_animated_images);
    }
  }

  void AddImageFromFilter(const gfx::Rect& op_rect, const PaintFilter* filter) {
    // Only analyze filters if they have animated images.
    if (!filter || !filter->has_discardable_images() ||
        filter->image_analysis_state() ==
            ImageAnalysisState::kNoAnimatedImages) {
      return;
    }

    base::AutoReset<bool> auto_reset(&only_gather_animated_images_, true);
    size_t prev_image_set_size = image_set_.size();
    ImageGatheringProvider image_provider(this, op_rect);
    filter->SnapshotWithImages(&image_provider);

    DCHECK_GE(image_set_.size(), prev_image_set_size);
    const bool has_animated_images = image_set_.size() > prev_image_set_size;
    const_cast<PaintFilter*>(filter)->set_has_animated_images(
        has_animated_images);
  }

  void AddImage(PaintImage paint_image,
                const SkRect& src_rect,
                const gfx::Rect& image_rect,
                const SkMatrix& matrix,
                SkFilterQuality filter_quality) {
    if (paint_image.IsTextureBacked())
      return;

    SkIRect src_irect;
    src_rect.roundOut(&src_irect);

    if (!paint_image.IsPaintWorklet()) {
      // Make a note if any image was originally specified in a non-sRGB color
      // space.
      SkColorSpace* source_color_space = paint_image.color_space();
      color_stats_total_pixel_count_ += image_rect.size().GetCheckedArea();
      color_stats_total_image_count_++;
      if (!source_color_space || source_color_space->isSRGB()) {
        color_stats_srgb_pixel_count_ += image_rect.size().GetCheckedArea();
        color_stats_srgb_image_count_++;
      }
    }

    auto& rects = image_id_to_rects_[paint_image.stable_id()];
    if (rects->size() >= kMaxRectsSize)
      rects->back().Union(image_rect);
    else
      rects->push_back(image_rect);

    auto decoding_mode_it = decoding_mode_map_.find(paint_image.stable_id());
    // Use the decoding mode if we don't have one yet, otherwise use the more
    // conservative one of the two existing ones.
    if (decoding_mode_it == decoding_mode_map_.end()) {
      decoding_mode_map_[paint_image.stable_id()] = paint_image.decoding_mode();
    } else {
      decoding_mode_it->second = PaintImage::GetConservative(
          decoding_mode_it->second, paint_image.decoding_mode());
    }

    if (paint_image.ShouldAnimate()) {
      animated_images_metadata_.emplace_back(
          paint_image.stable_id(), paint_image.completion_state(),
          paint_image.GetFrameMetadata(), paint_image.repetition_count(),
          paint_image.reset_animation_sequence_id());
    }

    // If we are iterating images in a record shader, only track them if they
    // are animated. We defer decoding of images in record shaders to skia, but
    // we still need to track animated images to invalidate and advance the
    // animation in cc.
    bool add_image =
        !only_gather_animated_images_ || paint_image.ShouldAnimate();
    if (add_image) {
      image_set_.emplace_back(
          DrawImage(std::move(paint_image), src_irect, filter_quality, matrix),
          image_rect);
    }
  }

  std::vector<std::pair<DrawImage, gfx::Rect>> image_set_;
  base::flat_map<PaintImage::Id, DiscardableImageMap::Rects> image_id_to_rects_;
  std::vector<DiscardableImageMap::AnimatedImageMetadata>
      animated_images_metadata_;
  base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_;
  bool only_gather_animated_images_ = false;

  // Statistics about the number of images and pixels that will require color
  // conversion if the target color space is not sRGB.
  int color_stats_srgb_image_count_ = 0;
  int color_stats_total_image_count_ = 0;
  base::CheckedNumeric<int64_t> color_stats_srgb_pixel_count_ = 0;
  base::CheckedNumeric<int64_t> color_stats_total_pixel_count_ = 0;
};

}  // namespace

DiscardableImageMap::DiscardableImageMap() = default;
DiscardableImageMap::~DiscardableImageMap() = default;

void DiscardableImageMap::Generate(const PaintOpBuffer* paint_op_buffer,
                                   const gfx::Rect& bounds) {
  TRACE_EVENT0("cc", "DiscardableImageMap::Generate");

  if (!paint_op_buffer->HasDiscardableImages())
    return;

  DiscardableImageGenerator generator(bounds.right(), bounds.bottom(),
                                      paint_op_buffer);
  generator.RecordColorHistograms();
  image_id_to_rects_ = generator.TakeImageIdToRectsMap();
  animated_images_metadata_ = generator.TakeAnimatedImagesMetadata();
  decoding_mode_map_ = generator.TakeDecodingModeMap();
  all_images_are_srgb_ = generator.all_images_are_srgb();
  auto images = generator.TakeImages();
  images_rtree_.Build(
      images,
      [](const std::vector<std::pair<DrawImage, gfx::Rect>>& items,
         size_t index) { return items[index].second; },
      [](const std::vector<std::pair<DrawImage, gfx::Rect>>& items,
         size_t index) { return items[index].first; });
}

base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
DiscardableImageMap::TakeDecodingModeMap() {
  return std::move(decoding_mode_map_);
}

void DiscardableImageMap::GetDiscardableImagesInRect(
    const gfx::Rect& rect,
    std::vector<const DrawImage*>* images) const {
  images_rtree_.SearchRefs(rect, images);
}

const DiscardableImageMap::Rects& DiscardableImageMap::GetRectsForImage(
    PaintImage::Id image_id) const {
  static const base::NoDestructor<Rects> kEmptyRects;
  auto it = image_id_to_rects_.find(image_id);
  return it == image_id_to_rects_.end() ? *kEmptyRects : it->second;
}

void DiscardableImageMap::Reset() {
  image_id_to_rects_.clear();
  image_id_to_rects_.shrink_to_fit();
  images_rtree_.Reset();
}

DiscardableImageMap::AnimatedImageMetadata::AnimatedImageMetadata(
    PaintImage::Id paint_image_id,
    PaintImage::CompletionState completion_state,
    std::vector<FrameMetadata> frames,
    int repetition_count,
    PaintImage::AnimationSequenceId reset_animation_sequence_id)
    : paint_image_id(paint_image_id),
      completion_state(completion_state),
      frames(std::move(frames)),
      repetition_count(repetition_count),
      reset_animation_sequence_id(reset_animation_sequence_id) {}

DiscardableImageMap::AnimatedImageMetadata::~AnimatedImageMetadata() = default;

DiscardableImageMap::AnimatedImageMetadata::AnimatedImageMetadata(
    const AnimatedImageMetadata& other) = default;

}  // namespace cc
