// 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/common/scratch_surface_cache.h"

#include <limits>

#include "base/debug/trace_event.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace common {

namespace {

// Approximate the memory usage of a given surface size.
size_t ApproximateSurfaceMemory(const math::Size& size) {
  // Here we assume that we use 4 bytes per pixel.
  return size.width() * size.height() * 4;
}

}  // namespace

ScratchSurfaceCache::ScratchSurfaceCache(Delegate* delegate,
                                         int cache_capacity_in_bytes)
    : delegate_(delegate),
      cache_capacity_in_bytes_(cache_capacity_in_bytes),
      surface_memory_(0) {}

ScratchSurfaceCache::~ScratchSurfaceCache() {
  DCHECK(surface_stack_.empty());
  for (std::vector<Surface*>::iterator iter = unused_surfaces_.begin();
       iter != unused_surfaces_.end(); ++iter) {
    delegate_->DestroySurface(*iter);
  }
}

ScratchSurfaceCache::Surface* ScratchSurfaceCache::AcquireScratchSurface(
    const math::Size& size) {
  TRACE_EVENT2("cobalt::renderer",
               "ScratchSurfaceCache::AcquireScratchSurface()", "width",
               size.width(), "height", size.height());
  if (cache_capacity_in_bytes_ == 0) {
    // If scratch surface caching is disabled, just create and immediately
    // return a surface.
    Surface* surface = delegate_->CreateSurface(size);
    if (surface) {
      delegate_->PrepareForUse(surface, size);
      return surface;
    } else {
      return NULL;
    }
  }

  // First check if we can find a suitable surface in our cache that is at
  // least the size requested.
  Surface* surface = FindBestCachedSurface(size);

  // If we didn't have any suitable surfaces in our cache, create a new one.
  if (!surface) {
    // Increase our total memory used on surfaces, and then initiate a purge
    // to reduce memory to below our cache limit, if necessary.
    surface_memory_ += ApproximateSurfaceMemory(size);
    Purge();

    // Create the surface.
    surface = delegate_->CreateSurface(size);

    if (!surface) {
      // We were unable to allocate a scratch surface, either because we are
      // low on memory or because the requested surface has large dimensions.
      // Return null.
      surface_memory_ -= ApproximateSurfaceMemory(size);
      return NULL;
    }
  }

  DCHECK(surface);

  // Track that we have handed out this surface.
  surface_stack_.push_back(surface);

  delegate_->PrepareForUse(surface, size);

  return surface;
}

void ScratchSurfaceCache::ReleaseScratchSurface(Surface* surface) {
  TRACE_EVENT2("cobalt::renderer",
               "ScratchSurfaceCache::ReleaseScratchSurface()", "width",
               surface->GetSize().width(), "height",
               surface->GetSize().height());
  if (cache_capacity_in_bytes_ == 0) {
    // If scratch surface caching is disabled, immediately destroy the surface
    // and return.
    delegate_->DestroySurface(surface);
    return;
  }

  DCHECK_EQ(surface_stack_.back(), surface);
  surface_stack_.pop_back();

  // Add this surface to the end (where most recently used surfaces go) of the
  // unused surfaces list, so that it can be returned by later calls to acquire
  // a surface.
  unused_surfaces_.push_back(surface);
}

namespace {

float GetMatchScoreForSurfaceAndSize(ScratchSurfaceCache::Surface* surface,
                                     const math::Size& size) {
  math::Size surface_size = surface->GetSize();

  // We use the negated sum of the squared differences between the requested
  // width/height and the surface width/height as the score.
  // This promotes returning the smallest surface possible that has a similar
  // ratio.
  int width_diff = surface_size.width() - size.width();
  int height_diff = surface_size.height() - size.height();

  return -width_diff * width_diff - height_diff * height_diff;
}

}  // namespace

ScratchSurfaceCache::Surface* ScratchSurfaceCache::FindBestCachedSurface(
    const math::Size& size) {
  // Iterate through all cached surfaces to find the one that is the best match
  // for the given size.  The function GetMatchScoreForSurfaceAndSize() is
  // responsible for assigning a score to a Surface/math::Size pair.
  float max_surface_score = -std::numeric_limits<float>::infinity();
  std::vector<Surface*>::iterator max_iter = unused_surfaces_.end();
  for (std::vector<Surface*>::iterator iter = unused_surfaces_.begin();
       iter != unused_surfaces_.end(); ++iter) {
    Surface* current_surface = *iter;
    math::Size surface_size = current_surface->GetSize();
    if (surface_size.width() >= size.width() &&
        surface_size.height() >= size.height()) {
      float surface_score =
          GetMatchScoreForSurfaceAndSize(current_surface, size);

      if (surface_score > max_surface_score) {
        max_surface_score = surface_score;
        max_iter = iter;
      }
    }
  }

  // If any of the cached unused surfaces had at least the specified
  // width/height, return the one that had the highest score.
  if (max_iter != unused_surfaces_.end()) {
    Surface* surface = *max_iter;
    // Remove this surface from the list of unused surfaces.
    unused_surfaces_.erase(max_iter);
    // Return the cached surface.
    return surface;
  } else {
    // Otherwise return NULL to indicate that we do not have any suitable cached
    // surfaces.
    return NULL;
  }
}

void ScratchSurfaceCache::Purge() {
  // Delete surfaces from the front (least recently used) of |unused_surfaces_|
  // until we have deleted all surfaces or lowered our memory usage to under
  // |cache_capacity_in_bytes_|.
  while (!unused_surfaces_.empty() &&
         surface_memory_ > cache_capacity_in_bytes_) {
    Surface* to_free = unused_surfaces_.front();
    math::Size surface_size = to_free->GetSize();
    surface_memory_ -= ApproximateSurfaceMemory(
        math::Size(surface_size.width(), surface_size.height()));
    delegate_->DestroySurface(to_free);
    unused_surfaces_.erase(unused_surfaces_.begin());
  }
}

}  // namespace common
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
