/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h"

#include <utility>

#include "cobalt/math/vector2d_f.h"
#include "cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"

#if SB_HAS(BLITTER)

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {

size_t CachedSoftwareRasterizer::Surface::GetEstimatedMemoryUsage() const {
  // We assume 4-bytes-per-pixel.
  return coord_mapping.output_bounds.size().GetArea() * 4;
}

CachedSoftwareRasterizer::CachedSoftwareRasterizer(SbBlitterDevice device,
                                                   SbBlitterContext context,
                                                   int cache_capacity)
    : cache_capacity_(cache_capacity),
      device_(device),
      context_(context),
      software_rasterizer_(0),
      cache_memory_usage_(
          "Memory.CachedSoftwareRasterizer.CacheUsage", 0,
          "Total memory occupied by cached software-rasterized surfaces."),
      cache_frame_usage_(
          "Memory.CachedSoftwareRasterizer.FrameCacheUsage", 0,
          "Total memory occupied by cache software-rasterizer surfaces that "
          "were referenced this frame.") {}

CachedSoftwareRasterizer::~CachedSoftwareRasterizer() {
  // Clean up any leftover surfaces.
  for (CacheMap::iterator iter = surface_map_.begin();
       iter != surface_map_.end(); ++iter) {
    DCHECK(iter->second.cached);
    SbBlitterDestroySurface(iter->second.surface);
  }
}

void CachedSoftwareRasterizer::OnStartNewFrame() {
  for (CacheMap::iterator iter = surface_map_.begin();
       iter != surface_map_.end();) {
    CacheMap::iterator current = iter;
    ++iter;

    // If the surface was referenced mark it as being unreferenced for the next
    // frame.
    if (current->second.referenced) {
#if defined(ENABLE_DEBUG_CONSOLE)
      current->second.created = false;
#endif  // defined(ENABLE_DEBUG_CONSOLE)
      current->second.referenced = false;
    }
  }

  // Reset our current frame cache usage to 0 since this is the start of a new
  // frame.
  cache_frame_usage_ = 0;
}

void CachedSoftwareRasterizer::PurgeUntilSpaceAvailable(int space_needed) {
  while (space_needed + cache_memory_usage_.value() > cache_capacity_) {
    CacheMap::iterator next_item = surface_map_.begin();

    // We shouldn't call this function if it means we would have to purge
    // elements that were referenced this frame.  This is to avoid thrashing
    // the cache, we would prefer to cache as much as we can in a frame, and
    // then just not cache whatever we can't without cycling what's in the cache
    // already.
    DCHECK(!next_item->second.referenced);
    cache_memory_usage_ -= next_item->second.GetEstimatedMemoryUsage();
    SbBlitterDestroySurface(next_item->second.surface);
    surface_map_.erase(next_item);
  }
}

CachedSoftwareRasterizer::Surface CachedSoftwareRasterizer::GetSurface(
    render_tree::Node* node, const Transform& transform) {
  CacheMap::iterator found = surface_map_.find(node);
  if (found != surface_map_.end()) {
#if SB_HAS(BILINEAR_FILTERING_SUPPORT)
    if (found->second.scale.x() >= transform.scale().x() &&
        found->second.scale.y() >= transform.scale().y()) {
#else  // SB_HAS(BILINEAR_FILTERING_SUPPORT)
    if (found->second.scale.x() == transform.scale().x() &&
        found->second.scale.y() == transform.scale().y()) {
#endif
      std::pair<render_tree::Node*, Surface> to_insert =
          std::make_pair(node, found->second);

      // Move this surface's position in the queue to the front, since it was
      // referenced.
      to_insert.second.referenced = true;
      surface_map_.erase(found);
      surface_map_.insert(to_insert);

      cache_frame_usage_ += to_insert.second.GetEstimatedMemoryUsage();

      return to_insert.second;
    }
  }

  Surface software_surface;
  software_surface.referenced = true;
#if defined(ENABLE_DEBUG_CONSOLE)
  software_surface.created = true;
#endif  // defined(ENABLE_DEBUG_CONSOLE)
  software_surface.node = node;
  software_surface.surface = kSbBlitterInvalidSurface;
  software_surface.cached = false;

  // We ensure that scale is at least 1. Since it is common to have animating
  // scale between 0 and 1 (e.g. an item animating from 0 to 1 to "grow" into
  // the scene), this ensures that rendered items will not look pixellated as
  // they grow (e.g. if they were cached at scale 0.2, they would be stretched
  // x5 if the scale were to animate to 1.0).
  if (transform.scale().x() == 0.0f || transform.scale().y() == 0.0f) {
    // There won't be anything to render if the transform squishes one dimension
    // to 0.
    return software_surface;
  }
  DCHECK_LT(0, transform.scale().x());
  DCHECK_LT(0, transform.scale().y());
  Transform scaled_transform(transform);
// If bilinear filtering is not supported, do not rely on the rasterizer to
// scale down for us, it results in too many artifacts.
#if SB_HAS(BILINEAR_FILTERING_SUPPORT)
  math::Vector2dF apply_scale(1.0f, 1.0f);
  if (transform.scale().x() < 1.0f) {
    apply_scale.set_x(1.0f / transform.scale().x());
  }
  if (transform.scale().y() < 1.0f) {
    apply_scale.set_y(1.0f / transform.scale().y());
  }
  scaled_transform.ApplyScale(apply_scale);
#endif  // SB_HAS(BILINEAR_FILTERING_SUPPORT)

  software_surface.scale = scaled_transform.scale();

  common::OffscreenRenderCoordinateMapping coord_mapping =
      common::GetOffscreenRenderCoordinateMapping(node->GetBounds(),
                                                  scaled_transform.ToMatrix(),
                                                  base::optional<math::Rect>());

  software_surface.coord_mapping = coord_mapping;

  if (coord_mapping.output_bounds.IsEmpty()) {
    // There's nothing to render if the bounds are 0.
    return software_surface;
  }

  DCHECK_GE(0.001f, std::abs(1.0f -
                             scaled_transform.scale().x() *
                                 coord_mapping.output_post_scale.x()));
  DCHECK_GE(0.001f, std::abs(1.0f -
                             scaled_transform.scale().y() *
                                 coord_mapping.output_post_scale.y()));

  SkImageInfo output_image_info = SkImageInfo::MakeN32(
      coord_mapping.output_bounds.width(), coord_mapping.output_bounds.height(),
      kPremul_SkAlphaType);

  // Allocate the pixels for the output image.
  SbBlitterPixelDataFormat blitter_pixel_data_format =
      SkiaToBlitterPixelFormat(output_image_info.colorType());
  DCHECK(SbBlitterIsPixelFormatSupportedByPixelData(device_,
                                                    blitter_pixel_data_format));
  SbBlitterPixelData pixel_data = SbBlitterCreatePixelData(
      device_, coord_mapping.output_bounds.width(),
      coord_mapping.output_bounds.height(), blitter_pixel_data_format);
  CHECK(SbBlitterIsPixelDataValid(pixel_data));

  SkBitmap bitmap;
  bitmap.installPixels(output_image_info,
                       SbBlitterGetPixelDataPointer(pixel_data),
                       SbBlitterGetPixelDataPitchInBytes(pixel_data));

  // Setup our Skia canvas that we will be using as the target for all CPU Skia
  // output.
  SkCanvas canvas(bitmap);
  canvas.clear(SkColorSetARGB(0, 0, 0, 0));

  Transform sub_render_transform(coord_mapping.sub_render_transform);

  // Now setup our canvas so that the render tree will be rendered to the top
  // left corner instead of at node->GetBounds().origin().
  canvas.translate(sub_render_transform.translate().x(),
                   sub_render_transform.translate().y());
  // And finally set the scale on our target canvas to match that of the current
  // |transform|.
  canvas.scale(sub_render_transform.scale().x(),
               sub_render_transform.scale().y());

  // Use the Skia software rasterizer to render our subtree.
  software_rasterizer_.Submit(node, &canvas);

  // Create a surface out of the now populated pixel data.
  software_surface.surface =
      SbBlitterCreateSurfaceFromPixelData(device_, pixel_data);

  if (software_surface.GetEstimatedMemoryUsage() + cache_frame_usage_.value() <=
      cache_capacity_) {
    software_surface.cached = true;
    cache_frame_usage_ += software_surface.GetEstimatedMemoryUsage();

    if (found != surface_map_.end()) {
      // This surface may have already been in the cache if it was in there
      // with a different scale.  In that case, replace the old one.
      cache_memory_usage_ -= found->second.GetEstimatedMemoryUsage();
      surface_map_.erase(found);
    }

    PurgeUntilSpaceAvailable(software_surface.GetEstimatedMemoryUsage());

    std::pair<CacheMap::iterator, bool> inserted =
        surface_map_.insert(std::make_pair(node, software_surface));
    cache_memory_usage_ += software_surface.GetEstimatedMemoryUsage();
  }

  return software_surface;
}

}  // namespace blitter
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // #if SB_HAS(BLITTER)
