// 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.

#pragma once

#include <unordered_map>
#include <vector>

#include "flutter/fml/macros.h"
#include "vulkan_surface.h"

namespace flutter_runner {

class VulkanSurfacePool final {
 public:
  // Only keep 12 surfaces at a time.  This value was based on how many
  // surfaces got cached in the old, exact-match-only caching logic.
  static constexpr int kMaxSurfaces = 12;
  // If a surface doesn't get used for 3 or more generations, we discard it.
  static constexpr int kMaxSurfaceAge = 3;

  VulkanSurfacePool(vulkan::VulkanProvider& vulkan_provider,
                    sk_sp<GrContext> context,
                    scenic::Session* scenic_session);

  ~VulkanSurfacePool();

  std::unique_ptr<VulkanSurface> AcquireSurface(const SkISize& size);

  void SubmitSurface(
      std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>
          surface);

  void AgeAndCollectOldBuffers();

  // Shrink all oversized |VulkanSurfaces| in |available_surfaces_| to as
  // small as they can be.
  void ShrinkToFit();

  // For |VulkanSurfaceProducer::HasRetainedNode|.
  bool HasRetainedNode(const flutter::LayerRasterCacheKey& key) const {
    return retained_surfaces_.find(key) != retained_surfaces_.end();
  }
  // For |VulkanSurfaceProducer::GetRetainedNode|.
  scenic::EntityNode* GetRetainedNode(const flutter::LayerRasterCacheKey& key) {
    FML_DCHECK(HasRetainedNode(key));
    return retained_surfaces_[key].vk_surface->GetRetainedNode();
  }

 private:
  // Struct for retained_surfaces_ map.
  struct RetainedSurface {
    // If |is_pending| is true, the |vk_surface| is still under painting
    // (similar to those in |pending_surfaces_|) so we can't recycle the
    // |vk_surface| yet.
    bool is_pending;
    std::unique_ptr<VulkanSurface> vk_surface;
  };

  vulkan::VulkanProvider& vulkan_provider_;
  sk_sp<GrContext> context_;
  scenic::Session* scenic_session_;
  std::vector<std::unique_ptr<VulkanSurface>> available_surfaces_;
  std::unordered_map<uintptr_t, std::unique_ptr<VulkanSurface>>
      pending_surfaces_;

  // Retained surfaces keyed by the layer that created and used the surface.
  flutter::LayerRasterCacheKey::Map<RetainedSurface> retained_surfaces_;

  size_t trace_surfaces_created_ = 0;
  size_t trace_surfaces_reused_ = 0;

  std::unique_ptr<VulkanSurface> GetCachedOrCreateSurface(const SkISize& size);

  std::unique_ptr<VulkanSurface> CreateSurface(const SkISize& size);

  void RecycleSurface(std::unique_ptr<VulkanSurface> surface);

  void RecyclePendingSurface(uintptr_t surface_key);

  // Clear the |is_pending| flag of the retained surface.
  void SignalRetainedReady(flutter::LayerRasterCacheKey key);

  // Remove the corresponding surface from |retained_surfaces| and recycle it.
  // The surface must not be pending.
  void RecycleRetainedSurface(const flutter::LayerRasterCacheKey& key);

  void TraceStats();

  FML_DISALLOW_COPY_AND_ASSIGN(VulkanSurfacePool);
};

}  // namespace flutter_runner
