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

#include "vulkan_swapchain.h"

#include "flutter/vulkan/procs/vulkan_proc_table.h"

#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"

#include "vulkan_backbuffer.h"
#include "vulkan_device.h"
#include "vulkan_image.h"
#include "vulkan_surface.h"

namespace vulkan {

namespace {
struct FormatInfo {
  VkFormat format_;
  SkColorType color_type_;
  sk_sp<SkColorSpace> color_space_;
};
}  // namespace

static std::vector<FormatInfo> DesiredFormatInfos() {
  return {{VK_FORMAT_R8G8B8A8_SRGB, kRGBA_8888_SkColorType,
           SkColorSpace::MakeSRGB()},
          {VK_FORMAT_B8G8R8A8_SRGB, kRGBA_8888_SkColorType,
           SkColorSpace::MakeSRGB()},
          {VK_FORMAT_R16G16B16A16_SFLOAT, kRGBA_F16_SkColorType,
           SkColorSpace::MakeSRGBLinear()},
          {VK_FORMAT_R8G8B8A8_UNORM, kRGBA_8888_SkColorType,
           SkColorSpace::MakeSRGB()},
          {VK_FORMAT_B8G8R8A8_UNORM, kRGBA_8888_SkColorType,
           SkColorSpace::MakeSRGB()}};
}

VulkanSwapchain::VulkanSwapchain(const VulkanProcTable& p_vk,
                                 const VulkanDevice& device,
                                 const VulkanSurface& surface,
                                 GrDirectContext* skia_context,
                                 std::unique_ptr<VulkanSwapchain> old_swapchain,
                                 uint32_t queue_family_index)
    : vk(p_vk),
      device_(device),
      capabilities_(),
      surface_format_(),
      current_pipeline_stage_(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT),
      current_backbuffer_index_(0),
      current_image_index_(0),
      valid_(false) {
  if (!device_.IsValid() || !surface.IsValid() || skia_context == nullptr) {
    FML_DLOG(INFO) << "Device or surface is invalid.";
    return;
  }

  if (!device_.GetSurfaceCapabilities(surface, &capabilities_)) {
    FML_DLOG(INFO) << "Could not find surface capabilities.";
    return;
  }

  const auto format_infos = DesiredFormatInfos();
  std::vector<VkFormat> desired_formats(format_infos.size());
  for (size_t i = 0; i < format_infos.size(); ++i) {
    if (skia_context->colorTypeSupportedAsSurface(
            format_infos[i].color_type_)) {
      desired_formats[i] = format_infos[i].format_;
    } else {
      desired_formats[i] = VK_FORMAT_UNDEFINED;
    }
  }

  int format_index =
      device_.ChooseSurfaceFormat(surface, desired_formats, &surface_format_);
  if (format_index < 0) {
    FML_DLOG(INFO) << "Could not choose surface format.";
    return;
  }

  VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
  if (!device_.ChoosePresentMode(surface, &present_mode)) {
    FML_DLOG(INFO) << "Could not choose present mode.";
    return;
  }

  // Check if the surface can present.

  VkBool32 supported = VK_FALSE;
  if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceSupportKHR(
          device_.GetPhysicalDeviceHandle(),  // physical device
          queue_family_index,                 // queue family
          surface.Handle(),                   // surface to test
          &supported)) != VK_SUCCESS) {
    FML_DLOG(INFO) << "Could not get physical device surface support.";
    return;
  }

  if (supported != VK_TRUE) {
    FML_DLOG(INFO) << "Surface was not supported by the physical device.";
    return;
  }

  // Construct the Swapchain

  VkSwapchainKHR old_swapchain_handle = VK_NULL_HANDLE;

  if (old_swapchain != nullptr && old_swapchain->IsValid()) {
    old_swapchain_handle = old_swapchain->swapchain_;
    // The unique pointer to the swapchain will go out of scope here
    // and its handle collected after the appropriate device wait.
  }

  VkSurfaceKHR surface_handle = surface.Handle();

  VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                                  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                  VK_IMAGE_USAGE_TRANSFER_DST_BIT;

  const VkSwapchainCreateInfoKHR create_info = {
      .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
      .pNext = nullptr,
      .flags = 0,
      .surface = surface_handle,
      .minImageCount = capabilities_.minImageCount,
      .imageFormat = surface_format_.format,
      .imageColorSpace = surface_format_.colorSpace,
      .imageExtent = capabilities_.currentExtent,
      .imageArrayLayers = 1,
      .imageUsage = usage_flags,
      .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
      .queueFamilyIndexCount = 0,  // Because of the exclusive sharing mode.
      .pQueueFamilyIndices = nullptr,
      .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
      .compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
      .presentMode = present_mode,
      .clipped = VK_FALSE,
      .oldSwapchain = old_swapchain_handle,
  };

  VkSwapchainKHR swapchain = VK_NULL_HANDLE;

  if (VK_CALL_LOG_ERROR(vk.CreateSwapchainKHR(device_.GetHandle(), &create_info,
                                              nullptr, &swapchain)) !=
      VK_SUCCESS) {
    FML_DLOG(INFO) << "Could not create the swapchain.";
    return;
  }

  swapchain_ = VulkanHandle<VkSwapchainKHR>{
      swapchain, [this](VkSwapchainKHR swapchain) {
        FML_ALLOW_UNUSED_LOCAL(device_.WaitIdle());
        vk.DestroySwapchainKHR(device_.GetHandle(), swapchain, nullptr);
      }};

  if (!CreateSwapchainImages(
          skia_context, format_infos[format_index].color_type_,
          format_infos[format_index].color_space_, usage_flags)) {
    FML_DLOG(INFO) << "Could not create swapchain images.";
    return;
  }

  valid_ = true;
}

VulkanSwapchain::~VulkanSwapchain() = default;

bool VulkanSwapchain::IsValid() const {
  return valid_;
}

std::vector<VkImage> VulkanSwapchain::GetImages() const {
  uint32_t count = 0;
  if (VK_CALL_LOG_ERROR(vk.GetSwapchainImagesKHR(
          device_.GetHandle(), swapchain_, &count, nullptr)) != VK_SUCCESS) {
    return {};
  }

  if (count == 0) {
    return {};
  }

  std::vector<VkImage> images;

  images.resize(count);

  if (VK_CALL_LOG_ERROR(vk.GetSwapchainImagesKHR(
          device_.GetHandle(), swapchain_, &count, images.data())) !=
      VK_SUCCESS) {
    return {};
  }

  return images;
}

SkISize VulkanSwapchain::GetSize() const {
  VkExtent2D extents = capabilities_.currentExtent;

  if (extents.width < capabilities_.minImageExtent.width) {
    extents.width = capabilities_.minImageExtent.width;
  } else if (extents.width > capabilities_.maxImageExtent.width) {
    extents.width = capabilities_.maxImageExtent.width;
  }

  if (extents.height < capabilities_.minImageExtent.height) {
    extents.height = capabilities_.minImageExtent.height;
  } else if (extents.height > capabilities_.maxImageExtent.height) {
    extents.height = capabilities_.maxImageExtent.height;
  }

  return SkISize::Make(extents.width, extents.height);
}

sk_sp<SkSurface> VulkanSwapchain::CreateSkiaSurface(
    GrDirectContext* gr_context,
    VkImage image,
    VkImageUsageFlags usage_flags,
    const SkISize& size,
    SkColorType color_type,
    sk_sp<SkColorSpace> color_space) const {
  if (gr_context == nullptr) {
    return nullptr;
  }

  if (color_type == kUnknown_SkColorType) {
    // Unexpected Vulkan format.
    return nullptr;
  }

  GrVkImageInfo image_info;
  image_info.fImage = image;
  image_info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
  image_info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  image_info.fFormat = surface_format_.format;
  image_info.fImageUsageFlags = usage_flags;
  image_info.fSampleCount = 1;
  image_info.fLevelCount = 1;

  // TODO(chinmaygarde): Setup the stencil buffer and the sampleCnt.
  GrBackendRenderTarget backend_render_target(size.fWidth, size.fHeight, 0,
                                              image_info);
  SkSurfaceProps props(0, kUnknown_SkPixelGeometry);

  return SkSurfaces::WrapBackendRenderTarget(
      gr_context,                // context
      backend_render_target,     // backend render target
      kTopLeft_GrSurfaceOrigin,  // origin
      color_type,                // color type
      std::move(color_space),    // color space
      &props                     // surface properties
  );
}

bool VulkanSwapchain::CreateSwapchainImages(
    GrDirectContext* skia_context,
    SkColorType color_type,
    const sk_sp<SkColorSpace>& color_space,
    VkImageUsageFlags usage_flags) {
  std::vector<VkImage> images = GetImages();

  if (images.empty()) {
    return false;
  }

  const SkISize surface_size = GetSize();

  for (const VkImage& image : images) {
    // Populate the backbuffer.
    auto backbuffer = std::make_unique<VulkanBackbuffer>(
        vk, device_.GetHandle(), device_.GetCommandPool());

    if (!backbuffer->IsValid()) {
      return false;
    }

    backbuffers_.emplace_back(std::move(backbuffer));

    // Populate the image.
    VulkanHandle<VkImage> image_handle = VulkanHandle<VkImage>{
        image, [this](VkImage image) {
          vk.DestroyImage(device_.GetHandle(), image, nullptr);
        }};
    auto vulkan_image = std::make_unique<VulkanImage>(std::move(image_handle));

    if (!vulkan_image->IsValid()) {
      return false;
    }

    images_.emplace_back(std::move(vulkan_image));

    // Populate the surface.
    auto surface = CreateSkiaSurface(skia_context, image, usage_flags,
                                     surface_size, color_type, color_space);

    if (surface == nullptr) {
      return false;
    }

    surfaces_.emplace_back(std::move(surface));
  }

  FML_DCHECK(backbuffers_.size() == images_.size());
  FML_DCHECK(images_.size() == surfaces_.size());

  return true;
}

VulkanBackbuffer* VulkanSwapchain::GetNextBackbuffer() {
  auto available_backbuffers = backbuffers_.size();

  if (available_backbuffers == 0) {
    return nullptr;
  }

  auto next_backbuffer_index =
      (current_backbuffer_index_ + 1) % backbuffers_.size();

  auto& backbuffer = backbuffers_[next_backbuffer_index];

  if (!backbuffer->IsValid()) {
    return nullptr;
  }

  current_backbuffer_index_ = next_backbuffer_index;
  return backbuffer.get();
}

VulkanSwapchain::AcquireResult VulkanSwapchain::AcquireSurface() {
  AcquireResult error = {AcquireStatus::ErrorSurfaceLost, nullptr};

  if (!IsValid()) {
    FML_DLOG(INFO) << "Swapchain was invalid.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 0:
  // Acquire the next available backbuffer.
  // ---------------------------------------------------------------------------
  auto backbuffer = GetNextBackbuffer();

  if (backbuffer == nullptr) {
    FML_DLOG(INFO) << "Could not get the next backbuffer.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 1:
  // Wait for use readiness.
  // ---------------------------------------------------------------------------
  if (!backbuffer->WaitFences()) {
    FML_DLOG(INFO) << "Failed waiting on fences.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 2:
  // Put fences in an unsignaled state.
  // ---------------------------------------------------------------------------
  if (!backbuffer->ResetFences()) {
    FML_DLOG(INFO) << "Could not reset fences.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 3:
  // Acquire the next image index.
  // ---------------------------------------------------------------------------
  uint32_t next_image_index = 0;

  VkResult acquire_result = VK_CALL_LOG_ERROR(
      vk.AcquireNextImageKHR(device_.GetHandle(),                   //
                             swapchain_,                            //
                             std::numeric_limits<uint64_t>::max(),  //
                             backbuffer->GetUsageSemaphore(),       //
                             VK_NULL_HANDLE,                        //
                             &next_image_index));

  switch (acquire_result) {
    case VK_SUCCESS:
      break;
    case VK_ERROR_OUT_OF_DATE_KHR:
      return {AcquireStatus::ErrorSurfaceOutOfDate, nullptr};
    case VK_ERROR_SURFACE_LOST_KHR:
      return {AcquireStatus::ErrorSurfaceLost, nullptr};
    default:
      FML_LOG(INFO) << "Unexpected result from AcquireNextImageKHR: "
                    << acquire_result;
      return {AcquireStatus::ErrorSurfaceLost, nullptr};
  }

  // Simple sanity checking of image index.
  if (next_image_index >= images_.size()) {
    FML_DLOG(INFO) << "Image index returned was out-of-bounds.";
    return error;
  }

  auto& image = images_[next_image_index];
  if (!image->IsValid()) {
    FML_DLOG(INFO) << "Image at index was invalid.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 4:
  // Start recording to the command buffer.
  // ---------------------------------------------------------------------------
  if (!backbuffer->GetUsageCommandBuffer().Begin()) {
    FML_DLOG(INFO) << "Could not begin recording to the command buffer.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 5:
  // Set image layout to color attachment mode.
  // ---------------------------------------------------------------------------
  VkPipelineStageFlagBits destination_pipeline_stage =
      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  VkImageLayout destination_image_layout =
      VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

  if (!image->InsertImageMemoryBarrier(
          backbuffer->GetUsageCommandBuffer(),   // command buffer
          current_pipeline_stage_,               // src_pipeline_bits
          destination_pipeline_stage,            // dest_pipeline_bits
          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,  // dest_access_flags
          destination_image_layout               // dest_layout
          )) {
    FML_DLOG(INFO) << "Could not insert image memory barrier.";
    return error;
  } else {
    current_pipeline_stage_ = destination_pipeline_stage;
  }

  // ---------------------------------------------------------------------------
  // Step 6:
  // End recording to the command buffer.
  // ---------------------------------------------------------------------------
  if (!backbuffer->GetUsageCommandBuffer().End()) {
    FML_DLOG(INFO) << "Could not end recording to the command buffer.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 7:
  // Submit the command buffer to the device queue.
  // ---------------------------------------------------------------------------
  std::vector<VkSemaphore> wait_semaphores = {backbuffer->GetUsageSemaphore()};
  std::vector<VkSemaphore> signal_semaphores = {};
  std::vector<VkCommandBuffer> command_buffers = {
      backbuffer->GetUsageCommandBuffer().Handle()};

  if (!device_.QueueSubmit(
          {destination_pipeline_stage},  // wait_dest_pipeline_stages
          wait_semaphores,               // wait_semaphores
          signal_semaphores,             // signal_semaphores
          command_buffers,               // command_buffers
          backbuffer->GetUsageFence()    // fence
          )) {
    FML_DLOG(INFO) << "Could not submit to the device queue.";
    return error;
  }

  // ---------------------------------------------------------------------------
  // Step 8:
  // Tell Skia about the updated image layout.
  // ---------------------------------------------------------------------------
  sk_sp<SkSurface> surface = surfaces_[next_image_index];

  if (surface == nullptr) {
    FML_DLOG(INFO) << "Could not access surface at the image index.";
    return error;
  }

  GrBackendRenderTarget backendRT = SkSurfaces::GetBackendRenderTarget(
      surface.get(), SkSurfaces::BackendHandleAccess::kFlushRead);
  if (!backendRT.isValid()) {
    FML_DLOG(INFO) << "Could not get backend render target.";
    return error;
  }
  backendRT.setVkImageLayout(destination_image_layout);

  current_image_index_ = next_image_index;

  return {AcquireStatus::Success, surface};
}

bool VulkanSwapchain::Submit() {
  if (!IsValid()) {
    FML_DLOG(INFO) << "Swapchain was invalid.";
    return false;
  }

  sk_sp<SkSurface> surface = surfaces_[current_image_index_];
  const std::unique_ptr<VulkanImage>& image = images_[current_image_index_];
  auto backbuffer = backbuffers_[current_backbuffer_index_].get();

  // ---------------------------------------------------------------------------
  // Step 0:
  // Make sure Skia has flushed all work for the surface to the gpu.
  // ---------------------------------------------------------------------------
  skgpu::ganesh::FlushAndSubmit(surface);

  // ---------------------------------------------------------------------------
  // Step 1:
  // Start recording to the command buffer.
  // ---------------------------------------------------------------------------
  if (!backbuffer->GetRenderCommandBuffer().Begin()) {
    FML_DLOG(INFO) << "Could not start recording to the command buffer.";
    return false;
  }

  // ---------------------------------------------------------------------------
  // Step 2:
  // Set image layout to present mode.
  // ---------------------------------------------------------------------------
  VkPipelineStageFlagBits destination_pipeline_stage =
      VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  VkImageLayout destination_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

  if (!image->InsertImageMemoryBarrier(
          backbuffer->GetRenderCommandBuffer(),  // command buffer
          current_pipeline_stage_,               // src_pipeline_bits
          destination_pipeline_stage,            // dest_pipeline_bits
          VK_ACCESS_MEMORY_READ_BIT,             // dest_access_flags
          destination_image_layout               // dest_layout
          )) {
    FML_DLOG(INFO) << "Could not insert memory barrier.";
    return false;
  } else {
    current_pipeline_stage_ = destination_pipeline_stage;
  }

  // ---------------------------------------------------------------------------
  // Step 3:
  // End recording to the command buffer.
  // ---------------------------------------------------------------------------
  if (!backbuffer->GetRenderCommandBuffer().End()) {
    FML_DLOG(INFO) << "Could not end recording to the command buffer.";
    return false;
  }

  // ---------------------------------------------------------------------------
  // Step 4:
  // Submit the command buffer to the device queue. Tell it to signal the render
  // semaphore.
  // ---------------------------------------------------------------------------
  std::vector<VkSemaphore> wait_semaphores = {};
  std::vector<VkSemaphore> queue_signal_semaphores = {
      backbuffer->GetRenderSemaphore()};
  std::vector<VkCommandBuffer> command_buffers = {
      backbuffer->GetRenderCommandBuffer().Handle()};

  if (!device_.QueueSubmit(
          {/* Empty. No wait semaphores. */},  // wait_dest_pipeline_stages
          wait_semaphores,                     // wait_semaphores
          queue_signal_semaphores,             // signal_semaphores
          command_buffers,                     // command_buffers
          backbuffer->GetRenderFence()         // fence
          )) {
    FML_DLOG(INFO) << "Could not submit to the device queue.";
    return false;
  }

  // ---------------------------------------------------------------------------
  // Step 5:
  // Submit the present operation and wait on the render semaphore.
  // ---------------------------------------------------------------------------
  VkSwapchainKHR swapchain = swapchain_;
  uint32_t present_image_index = static_cast<uint32_t>(current_image_index_);
  const VkPresentInfoKHR present_info = {
      .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
      .pNext = nullptr,
      .waitSemaphoreCount =
          static_cast<uint32_t>(queue_signal_semaphores.size()),
      .pWaitSemaphores = queue_signal_semaphores.data(),
      .swapchainCount = 1,
      .pSwapchains = &swapchain,
      .pImageIndices = &present_image_index,
      .pResults = nullptr,
  };

  if (VK_CALL_LOG_ERROR(vk.QueuePresentKHR(device_.GetQueueHandle(),
                                           &present_info)) != VK_SUCCESS) {
    FML_DLOG(INFO) << "Could not submit the present operation.";
    return false;
  }

  return true;
}

}  // namespace vulkan
