// 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 <lib/async/cpp/wait.h>
#include <lib/zx/event.h>
#include <lib/zx/vmo.h>

#include <array>
#include <memory>

#include "flutter/flow/raster_cache_key.h"
#include "flutter/flow/scene_update_context.h"
#include "flutter/fml/macros.h"
#include "flutter/vulkan/vulkan_command_buffer.h"
#include "flutter/vulkan/vulkan_handle.h"
#include "flutter/vulkan/vulkan_proc_table.h"
#include "flutter/vulkan/vulkan_provider.h"
#include "lib/ui/scenic/cpp/resources.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter_runner {

// A |VkImage| and its relevant metadata.
struct VulkanImage {
  VulkanImage() = default;
  VulkanImage(VulkanImage&&) = default;
  VulkanImage& operator=(VulkanImage&&) = default;

  VkExternalMemoryImageCreateInfo vk_external_image_create_info;
  VkImageCreateInfo vk_image_create_info;
  VkMemoryRequirements vk_memory_requirements;
  vulkan::VulkanHandle<VkImage> vk_image;

  FML_DISALLOW_COPY_AND_ASSIGN(VulkanImage);
};

// Create a new |VulkanImage| of size |size|, stored in
// |out_vulkan_image|.  Returns whether creation of the |VkImage| was
// successful.
bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider,
                       const SkISize& size,
                       VulkanImage* out_vulkan_image);

class VulkanSurface final
    : public flutter::SceneUpdateContext::SurfaceProducerSurface {
 public:
  VulkanSurface(vulkan::VulkanProvider& vulkan_provider,
                sk_sp<GrContext> context,
                scenic::Session* session,
                const SkISize& size);

  ~VulkanSurface() override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  size_t AdvanceAndGetAge() override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  bool FlushSessionAcquireAndReleaseEvents() override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  bool IsValid() const override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  SkISize GetSize() const override;

  // Note: It is safe for the caller to collect the surface in the
  // |on_writes_committed| callback.
  void SignalWritesFinished(
      const std::function<void(void)>& on_writes_committed) override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  scenic::Image* GetImage() override;

  // |flutter::SceneUpdateContext::SurfaceProducerSurface|
  sk_sp<SkSurface> GetSkiaSurface() const override;

  const vulkan::VulkanHandle<VkImage>& GetVkImage() {
    return vulkan_image_.vk_image;
  }

  const vulkan::VulkanHandle<VkSemaphore>& GetAcquireVkSemaphore() {
    return acquire_semaphore_;
  }

  vulkan::VulkanCommandBuffer* GetCommandBuffer(
      const vulkan::VulkanHandle<VkCommandPool>& pool) {
    if (!command_buffer_)
      command_buffer_ = std::make_unique<vulkan::VulkanCommandBuffer>(
          vulkan_provider_.vk(), vulkan_provider_.vk_device(), pool);
    return command_buffer_.get();
  }

  const vulkan::VulkanHandle<VkFence>& GetCommandBufferFence() {
    return command_buffer_fence_;
  }

  size_t GetAllocationSize() const { return vk_memory_info_.allocationSize; }

  size_t GetImageMemoryRequirementsSize() const {
    return vulkan_image_.vk_memory_requirements.size;
  }

  bool IsOversized() const {
    return GetAllocationSize() > GetImageMemoryRequirementsSize();
  }

  bool HasStableSizeHistory() const {
    return std::equal(size_history_.begin() + 1, size_history_.end(),
                      size_history_.begin());
  }

  // Bind |vulkan_image| to |vk_memory_| and create a new skia surface,
  // replacing the previous |vk_image_|.  |vulkan_image| MUST require less
  // than or equal the amount of memory contained in |vk_memory_|. Returns
  // whether the swap was successful.  The |VulkanSurface| will become invalid
  // if the swap was not successful.
  bool BindToImage(sk_sp<GrContext> context, VulkanImage vulkan_image);

  // Flutter may retain a |VulkanSurface| for a |flutter::Layer| subtree to
  // improve the performance. The |retained_key_| identifies which layer subtree
  // this |VulkanSurface| is retained for. The key has two parts. One is the
  // pointer to the root of that layer subtree: |retained_key_.id()|. Another is
  // the transformation matrix: |retained_key_.matrix()|. We need the matrix
  // part because a different matrix would invalidate the pixels (raster cache)
  // in this |VulkanSurface|.
  const flutter::LayerRasterCacheKey& GetRetainedKey() const {
    return retained_key_;
  }

  // For better safety in retained rendering, Flutter uses a retained
  // |EntityNode| associated with the retained surface instead of using the
  // retained surface directly. Hence Flutter can't modify the surface during
  // retained rendering. However, the node itself is modifiable to be able
  // to adjust its position.
  scenic::EntityNode* GetRetainedNode() {
    used_in_retained_rendering_ = true;
    return retained_node_.get();
  }

  // Check whether the retained surface (and its associated |EntityNode|) is
  // used in the current frame or not. If unused, the |VulkanSurfacePool| will
  // try to recycle the surface. This flag is reset after each frame.
  bool IsUsedInRetainedRendering() const { return used_in_retained_rendering_; }
  void ResetIsUsedInRetainedRendering() { used_in_retained_rendering_ = false; }

  // Let this surface own the retained EntityNode associated with it (see
  // |GetRetainedNode|), and set the retained key (see |GetRetainedKey|).
  void SetRetainedInfo(const flutter::LayerRasterCacheKey& key,
                       std::unique_ptr<scenic::EntityNode> node) {
    retained_key_ = key;
    retained_node_ = std::move(node);
  }

 private:
  static constexpr int kSizeHistorySize = 4;

  void OnHandleReady(async_dispatcher_t* dispatcher,
                     async::WaitBase* wait,
                     zx_status_t status,
                     const zx_packet_signal_t* signal);

  bool AllocateDeviceMemory(sk_sp<GrContext> context,
                            const SkISize& size,
                            zx::vmo& exported_vmo);

  bool SetupSkiaSurface(sk_sp<GrContext> context,
                        const SkISize& size,
                        SkColorType color_type,
                        const VkImageCreateInfo& image_create_info,
                        const VkMemoryRequirements& memory_reqs);

  bool CreateFences();

  bool PushSessionImageSetupOps(scenic::Session* session);

  void Reset();

  vulkan::VulkanHandle<VkSemaphore> SemaphoreFromEvent(
      const zx::event& event) const;

  vulkan::VulkanProvider& vulkan_provider_;
  scenic::Session* session_;
  VulkanImage vulkan_image_;
  vulkan::VulkanHandle<VkDeviceMemory> vk_memory_;
  VkMemoryAllocateInfo vk_memory_info_;
  vulkan::VulkanHandle<VkFence> command_buffer_fence_;
  sk_sp<SkSurface> sk_surface_;
  // TODO: Don't heap allocate this once SCN-268 is resolved.
  std::unique_ptr<scenic::Memory> scenic_memory_;
  std::unique_ptr<scenic::Image> session_image_;
  zx::event acquire_event_;
  vulkan::VulkanHandle<VkSemaphore> acquire_semaphore_;
  std::unique_ptr<vulkan::VulkanCommandBuffer> command_buffer_;
  zx::event release_event_;
  async::WaitMethod<VulkanSurface, &VulkanSurface::OnHandleReady> wait_;
  std::function<void()> pending_on_writes_committed_;
  std::array<SkISize, kSizeHistorySize> size_history_;
  int size_history_index_ = 0;
  size_t age_ = 0;
  bool valid_ = false;

  flutter::LayerRasterCacheKey retained_key_ = {0, SkMatrix::MakeScale(1, 1)};
  std::unique_ptr<scenic::EntityNode> retained_node_ = nullptr;

  std::atomic<bool> used_in_retained_rendering_ = {false};

  FML_DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
};

}  // namespace flutter_runner
