// Copyright 2013 The Flutter 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 "flutter/flow/raster_cache.h"

#include <vector>

#include "flutter/common/constants.h"
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/paint_utils.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"

namespace flutter {

RasterCacheResult::RasterCacheResult(sk_sp<SkImage> image,
                                     const SkRect& logical_rect,
                                     const char* type)
    : image_(std::move(image)), logical_rect_(logical_rect), flow_(type) {}

void RasterCacheResult::draw(SkCanvas& canvas, const SkPaint* paint) const {
  TRACE_EVENT0("flutter", "RasterCacheResult::draw");
  SkAutoCanvasRestore auto_restore(&canvas, true);
  SkIRect bounds =
      RasterCache::GetDeviceBounds(logical_rect_, canvas.getTotalMatrix());
  FML_DCHECK(
      std::abs(bounds.size().width() - image_->dimensions().width()) <= 1 &&
      std::abs(bounds.size().height() - image_->dimensions().height()) <= 1);
  canvas.resetMatrix();
  flow_.Step();
  canvas.drawImage(image_, bounds.fLeft, bounds.fTop, SkSamplingOptions(),
                   paint);
}

RasterCache::RasterCache(size_t access_threshold,
                         size_t picture_and_display_list_cache_limit_per_frame)
    : access_threshold_(access_threshold),
      picture_and_display_list_cache_limit_per_frame_(
          picture_and_display_list_cache_limit_per_frame),
      checkerboard_images_(false) {}

static bool CanRasterizeRect(const SkRect& cull_rect) {
  if (cull_rect.isEmpty()) {
    // No point in ever rasterizing an empty display list.
    return false;
  }

  if (!cull_rect.isFinite()) {
    // Cannot attempt to rasterize into an infinitely large surface.
    FML_LOG(INFO) << "Attempted to raster cache non-finite display list";
    return false;
  }

  return true;
}

static bool IsPictureWorthRasterizing(SkPicture* picture,
                                      bool will_change,
                                      bool is_complex) {
  if (will_change) {
    // If the picture is going to change in the future, there is no point in
    // doing to extra work to rasterize.
    return false;
  }

  if (picture == nullptr || !CanRasterizeRect(picture->cullRect())) {
    // No point in deciding whether the picture is worth rasterizing if it
    // cannot be rasterized at all.
    return false;
  }

  if (is_complex) {
    // The caller seems to have extra information about the picture and thinks
    // the picture is always worth rasterizing.
    return true;
  }

  // TODO(abarth): We should find a better heuristic here that lets us avoid
  // wasting memory on trivial layers that are easy to re-rasterize every frame.
  return picture->approximateOpCount(true) > 5;
}

static bool IsDisplayListWorthRasterizing(
    DisplayList* display_list,
    bool will_change,
    bool is_complex,
    DisplayListComplexityCalculator* complexity_calculator) {
  if (will_change) {
    // If the display list is going to change in the future, there is no point
    // in doing to extra work to rasterize.
    return false;
  }

  if (display_list == nullptr || !CanRasterizeRect(display_list->bounds())) {
    // No point in deciding whether the display list is worth rasterizing if it
    // cannot be rasterized at all.
    return false;
  }

  if (is_complex) {
    // The caller seems to have extra information about the display list and
    // thinks the display list is always worth rasterizing.
    return true;
  }

  unsigned int complexity_score = complexity_calculator->Compute(display_list);
  return complexity_calculator->ShouldBeCached(complexity_score);
}

/// @note Procedure doesn't copy all closures.
static std::unique_ptr<RasterCacheResult> Rasterize(
    GrDirectContext* context,
    const SkMatrix& ctm,
    SkColorSpace* dst_color_space,
    bool checkerboard,
    const SkRect& logical_rect,
    const char* type,
    const std::function<void(SkCanvas*)>& draw_function) {
  TRACE_EVENT0("flutter", "RasterCachePopulate");
  SkIRect cache_rect = RasterCache::GetDeviceBounds(logical_rect, ctm);

  const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
      cache_rect.width(), cache_rect.height(), sk_ref_sp(dst_color_space));

  sk_sp<SkSurface> surface =
      context
          ? SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, image_info)
          : SkSurface::MakeRaster(image_info);

  if (!surface) {
    return nullptr;
  }

  SkCanvas* canvas = surface->getCanvas();
  canvas->clear(SK_ColorTRANSPARENT);
  canvas->translate(-cache_rect.left(), -cache_rect.top());
  canvas->concat(ctm);
  draw_function(canvas);

  if (checkerboard) {
    DrawCheckerboard(canvas, logical_rect);
  }

  return std::make_unique<RasterCacheResult>(surface->makeImageSnapshot(),
                                             logical_rect, type);
}

std::unique_ptr<RasterCacheResult> RasterCache::RasterizePicture(
    SkPicture* picture,
    GrDirectContext* context,
    const SkMatrix& ctm,
    SkColorSpace* dst_color_space,
    bool checkerboard) const {
  return Rasterize(context, ctm, dst_color_space, checkerboard,
                   picture->cullRect(), "RasterCacheFlow::SkPicture",
                   [=](SkCanvas* canvas) { canvas->drawPicture(picture); });
}

std::unique_ptr<RasterCacheResult> RasterCache::RasterizeDisplayList(
    DisplayList* display_list,
    GrDirectContext* context,
    const SkMatrix& ctm,
    SkColorSpace* dst_color_space,
    bool checkerboard) const {
  return Rasterize(context, ctm, dst_color_space, checkerboard,
                   display_list->bounds(), "RasterCacheFlow::DisplayList",
                   [=](SkCanvas* canvas) { display_list->RenderTo(canvas); });
}

void RasterCache::Prepare(PrerollContext* context,
                          Layer* layer,
                          const SkMatrix& ctm,
                          RasterCacheLayerStrategy strategy) {
  auto cache_key_optional =
      TryToMakeRasterCacheKeyForLayer(layer, strategy, ctm);
  if (!cache_key_optional) {
    return;
  }
  Entry& entry = cache_[cache_key_optional.value()];
  entry.access_count++;
  entry.used_this_frame = true;
  if (!entry.image) {
    entry.image =
        RasterizeLayer(context, layer, strategy, ctm, checkerboard_images_);
  }
}

std::optional<RasterCacheKey> RasterCache::TryToMakeRasterCacheKeyForLayer(
    const Layer* layer,
    RasterCacheLayerStrategy strategy,
    const SkMatrix& ctm) const {
  switch (strategy) {
    case RasterCacheLayerStrategy::kLayer:
      return RasterCacheKey(layer->unique_id(), RasterCacheKeyType::kLayer,
                            ctm);
    case RasterCacheLayerStrategy::kLayerChildren:
      FML_DCHECK(layer->as_container_layer());
      auto& children_layers = layer->as_container_layer()->layers();
      auto children_count = children_layers.size();
      if (children_count == 0) {
        return std::nullopt;
      }
      std::vector<uint64_t> ids;
      std::transform(children_layers.begin(), children_layers.end(),
                     std::back_inserter(ids), [](auto& layer) -> uint64_t {
                       return layer->unique_id();
                     });
      return RasterCacheKey(RasterCacheKeyID(std::move(ids)),
                            RasterCacheKeyType::kLayerChildren, ctm);
  }
}

std::unique_ptr<RasterCacheResult> RasterCache::RasterizeLayer(
    PrerollContext* context,
    Layer* layer,
    RasterCacheLayerStrategy strategy,
    const SkMatrix& ctm,
    bool checkerboard) const {
  const SkRect& paint_bounds = GetPaintBoundsFromLayer(layer, strategy);

  return Rasterize(
      context->gr_context, ctm, context->dst_color_space, checkerboard,
      paint_bounds, "RasterCacheFlow::Layer",
      [layer, context, strategy](SkCanvas* canvas) {
        SkISize canvas_size = canvas->getBaseLayerSize();
        SkNWayCanvas internal_nodes_canvas(canvas_size.width(),
                                           canvas_size.height());
        internal_nodes_canvas.setMatrix(canvas->getTotalMatrix());
        internal_nodes_canvas.addCanvas(canvas);
        Layer::PaintContext paintContext = {
            /* internal_nodes_canvas= */ static_cast<SkCanvas*>(
                &internal_nodes_canvas),
            /* leaf_nodes_canvas= */ canvas,
            /* gr_context= */ context->gr_context,
            /* view_embedder= */ nullptr,
            context->raster_time,
            context->ui_time,
            context->texture_registry,
            context->has_platform_view ? nullptr : context->raster_cache,
            context->checkerboard_offscreen_layers,
            context->frame_device_pixel_ratio};
        switch (strategy) {
          case RasterCacheLayerStrategy::kLayer:
            if (layer->needs_painting(paintContext)) {
              layer->Paint(paintContext);
            }
            break;
          case RasterCacheLayerStrategy::kLayerChildren:
            FML_DCHECK(layer->as_container_layer());
            layer->as_container_layer()->PaintChildren(paintContext);
            break;
        }
      });
}

const SkRect& RasterCache::GetPaintBoundsFromLayer(
    Layer* layer,
    RasterCacheLayerStrategy strategy) const {
  switch (strategy) {
    case RasterCacheLayerStrategy::kLayer:
      return layer->paint_bounds();
    case RasterCacheLayerStrategy::kLayerChildren:
      FML_DCHECK(layer->as_container_layer());
      return layer->as_container_layer()->child_paint_bounds();
  }
}

bool RasterCache::Prepare(PrerollContext* context,
                          SkPicture* picture,
                          bool is_complex,
                          bool will_change,
                          const SkMatrix& untranslated_matrix,
                          const SkPoint& offset) {
  if (!GenerateNewCacheInThisFrame()) {
    return false;
  }

  if (!IsPictureWorthRasterizing(picture, will_change, is_complex)) {
    // We only deal with pictures that are worthy of rasterization.
    return false;
  }

  SkMatrix transformation_matrix = untranslated_matrix;
  transformation_matrix.preTranslate(offset.x(), offset.y());

  if (!transformation_matrix.invert(nullptr)) {
    // The matrix was singular. No point in going further.
    return false;
  }

  RasterCacheKey cache_key(picture->uniqueID(), RasterCacheKeyType::kPicture,
                           transformation_matrix);

  // Creates an entry, if not present prior.
  Entry& entry = cache_[cache_key];
  if (entry.access_count < access_threshold_) {
    // Frame threshold has not yet been reached.
    return false;
  }

  if (!entry.image) {
    // GetIntegralTransCTM effect for matrix which only contains scale,
    // translate, so it won't affect result of matrix decomposition and cache
    // key.
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
    transformation_matrix = GetIntegralTransCTM(transformation_matrix);
#endif
    entry.image =
        RasterizePicture(picture, context->gr_context, transformation_matrix,
                         context->dst_color_space, checkerboard_images_);
    picture_cached_this_frame_++;
  }
  return true;
}

bool RasterCache::Prepare(PrerollContext* context,
                          DisplayList* display_list,
                          bool is_complex,
                          bool will_change,
                          const SkMatrix& untranslated_matrix,
                          const SkPoint& offset) {
  if (!GenerateNewCacheInThisFrame()) {
    return false;
  }

  DisplayListComplexityCalculator* complexity_calculator =
      context->gr_context ? DisplayListComplexityCalculator::GetForBackend(
                                context->gr_context->backend())
                          : DisplayListComplexityCalculator::GetForSoftware();

  if (!IsDisplayListWorthRasterizing(display_list, will_change, is_complex,
                                     complexity_calculator)) {
    // We only deal with display lists that are worthy of rasterization.
    return false;
  }

  SkMatrix transformation_matrix = untranslated_matrix;
  transformation_matrix.preTranslate(offset.x(), offset.y());

  if (!transformation_matrix.invert(nullptr)) {
    // The matrix was singular. No point in going further.
    return false;
  }

  RasterCacheKey cache_key(display_list->unique_id(),
                           RasterCacheKeyType::kDisplayList,
                           transformation_matrix);

  // Creates an entry, if not present prior.
  Entry& entry = cache_[cache_key];
  if (entry.access_count < access_threshold_) {
    // Frame threshold has not yet been reached.
    return false;
  }

  if (!entry.image) {
    // GetIntegralTransCTM effect for matrix which only contains scale,
    // translate, so it won't affect result of matrix decomposition and cache
    // key.
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
    transformation_matrix = GetIntegralTransCTM(transformation_matrix);
#endif
    entry.image = RasterizeDisplayList(
        display_list, context->gr_context, transformation_matrix,
        context->dst_color_space, checkerboard_images_);
    display_list_cached_this_frame_++;
  }
  return true;
}

void RasterCache::Touch(Layer* layer,
                        const SkMatrix& ctm,
                        RasterCacheLayerStrategy strategey) {
  auto cache_key_optional =
      TryToMakeRasterCacheKeyForLayer(layer, strategey, ctm);
  if (!cache_key_optional) {
    return;
  }
  Touch(cache_key_optional.value());
}

void RasterCache::Touch(SkPicture* picture,
                        const SkMatrix& transformation_matrix) {
  RasterCacheKey cache_key(picture->uniqueID(), RasterCacheKeyType::kPicture,
                           transformation_matrix);
  Touch(cache_key);
}

void RasterCache::Touch(DisplayList* display_list,
                        const SkMatrix& transformation_matrix) {
  RasterCacheKey cache_key(display_list->unique_id(),
                           RasterCacheKeyType::kDisplayList,
                           transformation_matrix);
  Touch(cache_key);
}

void RasterCache::Touch(const RasterCacheKey& cache_key) {
  auto it = cache_.find(cache_key);
  if (it != cache_.end()) {
    it->second.used_this_frame = true;
    it->second.access_count++;
  }
}

bool RasterCache::Draw(const SkPicture& picture,
                       SkCanvas& canvas,
                       const SkPaint* paint) const {
  RasterCacheKey cache_key(picture.uniqueID(), RasterCacheKeyType::kPicture,
                           canvas.getTotalMatrix());
  return Draw(cache_key, canvas, paint);
}

bool RasterCache::Draw(const DisplayList& display_list,
                       SkCanvas& canvas,
                       const SkPaint* paint) const {
  RasterCacheKey cache_key(display_list.unique_id(),
                           RasterCacheKeyType::kDisplayList,
                           canvas.getTotalMatrix());
  return Draw(cache_key, canvas, paint);
}

bool RasterCache::Draw(const Layer* layer,
                       SkCanvas& canvas,
                       RasterCacheLayerStrategy strategy,
                       const SkPaint* paint) const {
  auto cache_key_optional =
      TryToMakeRasterCacheKeyForLayer(layer, strategy, canvas.getTotalMatrix());
  if (!cache_key_optional) {
    return false;
  }
  return Draw(cache_key_optional.value(), canvas, paint);
}

bool RasterCache::Draw(const RasterCacheKey& cache_key,
                       SkCanvas& canvas,
                       const SkPaint* paint) const {
  auto it = cache_.find(cache_key);
  if (it == cache_.end()) {
    return false;
  }

  Entry& entry = it->second;
  entry.access_count++;
  entry.used_this_frame = true;

  if (entry.image) {
    entry.image->draw(canvas, paint);
    return true;
  }

  return false;
}

void RasterCache::PrepareNewFrame() {
  picture_cached_this_frame_ = 0;
  display_list_cached_this_frame_ = 0;
}

void RasterCache::SweepOneCacheAfterFrame(RasterCacheKey::Map<Entry>& cache,
                                          RasterCacheMetrics& picture_metrics,
                                          RasterCacheMetrics& layer_metrics) {
  std::vector<RasterCacheKey::Map<Entry>::iterator> dead;

  for (auto it = cache.begin(); it != cache.end(); ++it) {
    Entry& entry = it->second;

    if (!entry.used_this_frame) {
      dead.push_back(it);
    } else if (entry.image) {
      RasterCacheKeyKind kind = it->first.kind();
      switch (kind) {
        case RasterCacheKeyKind::kPictureMetrics:
          picture_metrics.in_use_count++;
          picture_metrics.in_use_bytes += entry.image->image_bytes();
          break;
        case RasterCacheKeyKind::kLayerMetrics:
          layer_metrics.in_use_count++;
          layer_metrics.in_use_bytes += entry.image->image_bytes();
          break;
      }
    }
    entry.used_this_frame = false;
  }

  for (auto it : dead) {
    if (it->second.image) {
      RasterCacheKeyKind kind = it->first.kind();
      switch (kind) {
        case RasterCacheKeyKind::kPictureMetrics:
          picture_metrics.eviction_count++;
          picture_metrics.eviction_bytes += it->second.image->image_bytes();
          break;
        case RasterCacheKeyKind::kLayerMetrics:
          layer_metrics.eviction_count++;
          layer_metrics.eviction_bytes += it->second.image->image_bytes();
          break;
      }
    }
    cache.erase(it);
  }
}

void RasterCache::CleanupAfterFrame() {
  picture_metrics_ = {};
  layer_metrics_ = {};
  SweepOneCacheAfterFrame(cache_, picture_metrics_, layer_metrics_);
  TraceStatsToTimeline();
}

void RasterCache::Clear() {
  cache_.clear();
  picture_metrics_ = {};
  layer_metrics_ = {};
}

size_t RasterCache::GetCachedEntriesCount() const {
  return cache_.size();
}

size_t RasterCache::GetLayerCachedEntriesCount() const {
  size_t layer_cached_entries_count = 0;
  for (const auto& item : cache_) {
    if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics) {
      layer_cached_entries_count++;
    }
  }
  return layer_cached_entries_count;
}

size_t RasterCache::GetPictureCachedEntriesCount() const {
  size_t picture_cached_entries_count = 0;
  for (const auto& item : cache_) {
    if (item.first.kind() == RasterCacheKeyKind::kPictureMetrics) {
      picture_cached_entries_count++;
    }
  }
  return picture_cached_entries_count;
}

void RasterCache::SetCheckboardCacheImages(bool checkerboard) {
  if (checkerboard_images_ == checkerboard) {
    return;
  }

  checkerboard_images_ = checkerboard;

  // Clear all existing entries so previously rasterized items (with or without
  // a checkerboard) will be refreshed in subsequent passes.
  Clear();
}

void RasterCache::TraceStatsToTimeline() const {
#if !FLUTTER_RELEASE
  FML_TRACE_COUNTER(
      "flutter",                                                           //
      "RasterCache", reinterpret_cast<int64_t>(this),                      //
      "LayerCount", layer_metrics_.total_count(),                          //
      "LayerMBytes", layer_metrics_.total_bytes() / kMegaByteSizeInBytes,  //
      "PictureCount", picture_metrics_.total_count(),                      //
      "PictureMBytes", picture_metrics_.total_bytes() / kMegaByteSizeInBytes);

#endif  // !FLUTTER_RELEASE
}

size_t RasterCache::EstimateLayerCacheByteSize() const {
  size_t layer_cache_bytes = 0;
  for (const auto& item : cache_) {
    if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics &&
        item.second.image) {
      layer_cache_bytes += item.second.image->image_bytes();
    }
  }
  return layer_cache_bytes;
}

size_t RasterCache::EstimatePictureCacheByteSize() const {
  size_t picture_cache_bytes = 0;
  for (const auto& item : cache_) {
    if (item.first.kind() == RasterCacheKeyKind::kPictureMetrics &&
        item.second.image) {
      picture_cache_bytes += item.second.image->image_bytes();
    }
  }
  return picture_cache_bytes;
}

}  // namespace flutter
