// Copyright 2017 The Fuchsia 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 "vulkan_surface_pool.h"

#include <algorithm>
#include <string>

#include <trace/event.h>

#include "third_party/skia/include/gpu/GrContext.h"

namespace flutter {

namespace {

std::string ToString(const SkISize& size) {
  return "{width: " + std::to_string(size.width()) +
         ", height: " + std::to_string(size.height()) + "}";
}

}  // namespace

VulkanSurfacePool::VulkanSurfacePool(vulkan::VulkanProvider& vulkan_provider,
                                     sk_sp<GrContext> context,
                                     scenic::Session* scenic_session)
    : vulkan_provider_(vulkan_provider),
      context_(std::move(context)),
      scenic_session_(scenic_session) {}

VulkanSurfacePool::~VulkanSurfacePool() {}

std::unique_ptr<VulkanSurface>
VulkanSurfacePool::AcquireSurface(const SkISize& size) {
  auto surface = GetCachedOrCreateSurface(size);

  if (surface == nullptr) {
    FML_DLOG(ERROR) << "Could not acquire surface";
    return nullptr;
  }

  if (!surface->FlushSessionAcquireAndReleaseEvents()) {
    FML_DLOG(ERROR) << "Could not flush acquire/release events for buffer.";
    return nullptr;
  }

  return surface;
}

std::unique_ptr<VulkanSurface>
VulkanSurfacePool::GetCachedOrCreateSurface(const SkISize& size) {
  // First try to find a surface that exactly matches |size|.
  {
    auto exact_match_it =
        std::find_if(available_surfaces_.begin(), available_surfaces_.end(),
                     [&size](const auto& surface) {
                       return surface->IsValid() && surface->GetSize() == size;
                     });
    if (exact_match_it != available_surfaces_.end()) {
      auto acquired_surface = std::move(*exact_match_it);
      available_surfaces_.erase(exact_match_it);
      return acquired_surface;
    }
  }

  // Then, look for a surface that has enough |VkDeviceMemory| to hold a
  // |VkImage| of size |size|, but is currently holding a |VkImage| of a
  // different size.
  VulkanImage vulkan_image;
  if (!CreateVulkanImage(vulkan_provider_, size, &vulkan_image)) {
    FML_DLOG(ERROR) << "Failed to create a VkImage of size: " << ToString(size);
    return nullptr;
  }

  auto best_it = available_surfaces_.end();
  for (auto it = available_surfaces_.begin(); it != available_surfaces_.end();
       ++it) {
    const auto& surface = *it;
    if (!surface->IsValid() || surface->GetAllocationSize() <
                                   vulkan_image.vk_memory_requirements.size) {
      continue;
    }
    if (best_it == available_surfaces_.end() ||
        surface->GetAllocationSize() < (*best_it)->GetAllocationSize()) {
      best_it = it;
    }
  }

  // If no such surface exists, then create a new one.
  if (best_it == available_surfaces_.end()) {
    return CreateSurface(size);
  }

  auto acquired_surface = std::move(*best_it);
  available_surfaces_.erase(best_it);
  bool swap_succeeded =
      acquired_surface->BindToImage(context_, std::move(vulkan_image));
  if (!swap_succeeded) {
    FML_DLOG(ERROR) << "Failed to swap VulkanSurface to new VkImage of size: "
                    << ToString(size);
    return CreateSurface(size);
  }
  FML_DCHECK(acquired_surface->IsValid());
  trace_surfaces_reused_++;
  return acquired_surface;
}

void VulkanSurfacePool::SubmitSurface(
    std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>
        p_surface) {
  TRACE_DURATION("flutter", "VulkanSurfacePool::SubmitSurface");

  // This cast is safe because |VulkanSurface| is the only implementation of
  // |SurfaceProducerSurface| for Flutter on Fuchsia.  Additionally, it is
  // required, because we need to access |VulkanSurface| specific information
  // of the surface (such as the amount of VkDeviceMemory it contains).
  auto vulkan_surface = std::unique_ptr<VulkanSurface>(
      static_cast<VulkanSurface*>(p_surface.release()));
  if (!vulkan_surface) {
    return;
  }


  const flow::LayerRasterCacheKey& retained_key =
      vulkan_surface->GetRetainedKey();
  if (retained_key.id() != nullptr) {
    // Add the surface to |retained_surfaces_| if its retained key has a non-
    // null layer (|retained_key.id()|).
    //
    // We have to add the entry to |retained_surfaces_| map early when it's
    // still pending (|is_pending| = true). Otherwise (if we add the surface
    // later when |SignalRetainedReady| is called), Flutter would fail to find
    // the retained node before the painting is done (which could take multiple
    // frames). Flutter would then create a new |VulkanSurface| for the layer
    // upon the failed lookup. The new |VulkanSurface| would invalidate this
    // surface, and before the new |VulkanSurface| is done painting, another
    // newer |VulkanSurface| is likely to be created to replace the new
    // |VulkanSurface|. That would make the retained rendering much less useful
    // in improving the performance.
    auto insert_iterator = retained_surfaces_.insert(std::make_pair(
        retained_key,
        RetainedSurface({true, std::move(vulkan_surface)})
    ));
    if (insert_iterator.second) {
      insert_iterator.first->second.vk_surface->SignalWritesFinished(
          std::bind(&VulkanSurfacePool::SignalRetainedReady, this, retained_key));
    }
  } else {
    uintptr_t surface_key = reinterpret_cast<uintptr_t>(vulkan_surface.get());
    auto insert_iterator = pending_surfaces_.insert(std::make_pair(
        surface_key,               // key
        std::move(vulkan_surface)  // value
    ));
    if (insert_iterator.second) {
      insert_iterator.first->second->SignalWritesFinished(
          std::bind(&VulkanSurfacePool::RecyclePendingSurface,
                    this, surface_key));
    }
  }
}

std::unique_ptr<VulkanSurface> VulkanSurfacePool::CreateSurface(
    const SkISize& size) {
  TRACE_DURATION("flutter", "VulkanSurfacePool::CreateSurface", "width",
                 size.width(), "height", size.height());
  auto surface = std::make_unique<VulkanSurface>(vulkan_provider_, context_,
                                                 scenic_session_, size);
  if (!surface->IsValid()) {
    return nullptr;
  }
  trace_surfaces_created_++;
  return surface;
}

void VulkanSurfacePool::RecyclePendingSurface(uintptr_t surface_key) {
  // Before we do anything, we must clear the surface from the collection of
  // pending surfaces.
  auto found_in_pending = pending_surfaces_.find(surface_key);
  if (found_in_pending == pending_surfaces_.end()) {
    return;
  }

  // Grab a hold of the surface to recycle and clear the entry in the pending
  // surfaces collection.
  auto surface_to_recycle = std::move(found_in_pending->second);
  pending_surfaces_.erase(found_in_pending);

  RecycleSurface(std::move(surface_to_recycle));
}

void VulkanSurfacePool::RecycleSurface(std::unique_ptr<VulkanSurface> surface) {
  // The surface may have become invalid (for example it the fences could
  // not be reset).
  if (!surface->IsValid()) {
    return;
  }

  // Recycle the buffer by putting it in the list of available surfaces if we
  // have not reached the maximum amount of cached surfaces.
  if (available_surfaces_.size() < kMaxSurfaces) {
    available_surfaces_.push_back(std::move(surface));
  }
}

void VulkanSurfacePool::RecycleRetainedSurface(
    const flow::LayerRasterCacheKey& key) {
  auto it = retained_surfaces_.find(key);
  if (it == retained_surfaces_.end()) {
    return;
  }

  // The surface should not be pending.
  FML_DCHECK(!it->second.is_pending);

  auto surface_to_recycle = std::move(it->second.vk_surface);
  retained_surfaces_.erase(it);
  RecycleSurface(std::move(surface_to_recycle));
}

void VulkanSurfacePool::SignalRetainedReady(flow::LayerRasterCacheKey key) {
  retained_surfaces_[key].is_pending = false;
}

void VulkanSurfacePool::AgeAndCollectOldBuffers() {
  TRACE_DURATION("flutter", "VulkanSurfacePool::AgeAndCollectOldBuffers");

  // Remove all surfaces that are no longer valid or are too old.
  available_surfaces_.erase(
      std::remove_if(available_surfaces_.begin(), available_surfaces_.end(),
                     [&](auto& surface) {
                       return !surface->IsValid() ||
                              surface->AdvanceAndGetAge() >= kMaxSurfaceAge;
                     }),
      available_surfaces_.end());

  // Look for a surface that has both a larger |VkDeviceMemory| allocation
  // than is necessary for its |VkImage|, and has a stable size history.
  auto surface_to_remove_it = std::find_if(
      available_surfaces_.begin(), available_surfaces_.end(),
      [](const auto& surface) {
        return surface->IsOversized() && surface->HasStableSizeHistory();
      });
  // If we found such a surface, then destroy it and cache a new one that only
  // uses a necessary amount of memory.
  if (surface_to_remove_it != available_surfaces_.end()) {
    auto size = (*surface_to_remove_it)->GetSize();
    available_surfaces_.erase(surface_to_remove_it);
    auto new_surface = CreateSurface(size);
    if (new_surface != nullptr) {
      available_surfaces_.push_back(std::move(new_surface));
    } else {
      FML_DLOG(ERROR) << "Failed to create a new shrunk surface";
    }
  }

  // Recycle retained surfaces that are not used and not pending in this frame.
  //
  // It's safe to recycle any retained surfaces that are not pending no matter
  // whether they're used or not. Hence if there's memory pressure, feel free to
  // recycle all retained surfaces that are not pending.
  std::vector<flow::LayerRasterCacheKey> recycle_keys;
  for (auto&[key, retained_surface] : retained_surfaces_) {
    if (retained_surface.is_pending ||
      retained_surface.vk_surface->IsUsedInRetainedRendering()) {
      // Reset the flag for the next frame
      retained_surface.vk_surface->ResetIsUsedInRetainedRendering();
    } else {
      recycle_keys.push_back(key);
    }
  }
  for (auto& key : recycle_keys) {
    RecycleRetainedSurface(key);
  }

  TraceStats();
}

void VulkanSurfacePool::ShrinkToFit() {
  // Reset all oversized surfaces in |available_surfaces_| so that the old
  // surfaces and new surfaces don't exist at the same time at any point,
  // reducing our peak memory footprint.
  std::vector<SkISize> sizes_to_recreate;
  for (auto& surface : available_surfaces_) {
    if (surface->IsOversized()) {
      sizes_to_recreate.push_back(surface->GetSize());
      surface.reset();
    }
  }
  available_surfaces_.erase(std::remove(available_surfaces_.begin(),
                                        available_surfaces_.end(), nullptr),
                            available_surfaces_.end());
  for (const auto& size : sizes_to_recreate) {
    auto surface = CreateSurface(size);
    if (surface != nullptr) {
      available_surfaces_.push_back(std::move(surface));
    } else {
      FML_DLOG(ERROR) << "Failed to create resized surface";
    }
  }

  TraceStats();
}

void VulkanSurfacePool::TraceStats() {
  // Resources held in cached buffers.
  size_t cached_surfaces = 0;
  size_t cached_surfaces_bytes = 0;

  for (const auto& surface : available_surfaces_) {
    cached_surfaces++;
    cached_surfaces_bytes += surface->GetAllocationSize();
  }

  // Resources held by Skia.
  int skia_resources = 0;
  size_t skia_bytes = 0;
  context_->getResourceCacheUsage(&skia_resources, &skia_bytes);
  const size_t skia_cache_purgeable =
      context_->getResourceCachePurgeableBytes();

  TRACE_COUNTER("flutter", "SurfacePool", 0u,                     //
                "CachedCount", cached_surfaces,                   //
                "CachedBytes", cached_surfaces_bytes,             //
                "Created", trace_surfaces_created_,               //
                "Reused", trace_surfaces_reused_,                 //
                "PendingInCompositor", pending_surfaces_.size(),  //
                "Retained", retained_surfaces_.size(),            //
                "SkiaCacheResources", skia_resources,             //
                "SkiaCacheBytes", skia_bytes,                     //
                "SkiaCachePurgeable", skia_cache_purgeable        //
  );

  // Reset per present/frame stats.
  trace_surfaces_created_ = 0;
  trace_surfaces_reused_ = 0;
}

}  // namespace flutter
