// 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 "garnet/lib/ui/gfx/swapchain/vulkan_display_swapchain.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <trace/event.h>

#include "garnet/lib/ui/gfx/displays/display.h"
#include "garnet/lib/ui/gfx/engine/frame_timings.h"
#include "garnet/lib/ui/gfx/util/time.h"
#include "lib/escher/escher.h"
#include "lib/escher/util/fuchsia_utils.h"
#include "lib/escher/vk/gpu_mem.h"

namespace scenic_impl {
namespace gfx {

namespace {

#define VK_CHECK_RESULT(XXX) FXL_CHECK(XXX.result == vk::Result::eSuccess)

#if SCENIC_IGNORE_VSYNC
// The display will only release the currently-drawing frame on vsync, so
// without at least 3 images this can only render at an even division of the
// vsync rate.
const uint32_t kDesiredSwapchainImageCount = 3;
#else
const uint32_t kDesiredSwapchainImageCount = 2;
#endif

}  // namespace

VulkanDisplaySwapchain::VulkanDisplaySwapchain(Display* display,
                                               EventTimestamper* timestamper,
                                               escher::Escher* escher)
    : display_(display),
      event_timestamper_(timestamper),
      device_(escher->vk_device()),
      queue_(escher->device()->vk_main_queue()) {
  display_->Claim();

  InitializeVulkanSwapchain(display_, escher->device(),
                            escher->resource_recycler());

  image_available_semaphores_.reserve(swapchain_.images.size());
  render_finished_semaphores_.reserve(swapchain_.images.size());
  for (size_t i = 0; i < swapchain_.images.size(); ++i) {
// TODO: Use timestamper to listen for event notifications
#if 1
    image_available_semaphores_.push_back(escher::Semaphore::New(device_));
    render_finished_semaphores_.push_back(escher::Semaphore::New(device_));
#else
    auto pair = NewSemaphoreEventPair(escher);
    image_available_semaphores_.push_back(std::move(pair.first));
    watches_.push_back(
        timestamper, std::move(pair.second), kFenceSignalled,
        [this, i](zx_time_t timestamp) { OnFramePresented(i, timestamp); });
#endif
  }
}

VulkanDisplaySwapchain::~VulkanDisplaySwapchain() {
  swapchain_.images.clear();

  FXL_CHECK(swapchain_.swapchain);
  device_.destroySwapchainKHR(swapchain_.swapchain);
  swapchain_.swapchain = nullptr;

  display_->Unclaim();
}

void VulkanDisplaySwapchain::InitializeVulkanSwapchain(
    Display* display, escher::VulkanDeviceQueues* device_queues,
    escher::ResourceRecycler* recycler) {
  vk::PhysicalDevice physical_device = device_queues->vk_physical_device();
  vk::SurfaceKHR surface = device_queues->vk_surface();
  FXL_CHECK(!swapchain_.swapchain);
  FXL_CHECK(swapchain_.images.empty());
  FXL_CHECK(recycler);

  {
    auto result = physical_device.getSurfaceSupportKHR(
        device_queues->vk_main_queue_family(), surface);
    VK_CHECK_RESULT(result);
    FXL_CHECK(result.value);
  }

  vk::SurfaceCapabilitiesKHR surface_caps;
  {
    auto result = physical_device.getSurfaceCapabilitiesKHR(surface);
    VK_CHECK_RESULT(result);
    surface_caps = std::move(result.value);
  }

  std::vector<vk::PresentModeKHR> present_modes;
  {
    auto result = physical_device.getSurfacePresentModesKHR(surface);
    VK_CHECK_RESULT(result);
    present_modes = std::move(result.value);
  }

  // TODO: handle undefined width/height.
  vk::Extent2D swapchain_extent = surface_caps.currentExtent;
  constexpr uint32_t VK_UNDEFINED_WIDTH_OR_HEIGHT = 0xFFFFFFFF;
  if (swapchain_extent.width == VK_UNDEFINED_WIDTH_OR_HEIGHT) {
    swapchain_extent.width = display->width_in_px();
  }
  if (swapchain_extent.height == VK_UNDEFINED_WIDTH_OR_HEIGHT) {
    swapchain_extent.height = display->height_in_px();
  }
  FXL_CHECK(swapchain_extent.width == display->width_in_px());
  FXL_CHECK(swapchain_extent.height == display->height_in_px());

  // FIFO mode is always available, but we will try to find a more efficient
  // mode.
  vk::PresentModeKHR swapchain_present_mode = vk::PresentModeKHR::eFifo;
// TODO: Find out why these modes are causing lower performance on Skylake
#if 0
  for (auto& mode : present_modes) {
    if (mode == vk::PresentModeKHR::eMailbox) {
      // Best choice: lowest-latency non-tearing mode.
      swapchain_present_mode = vk::PresentModeKHR::eMailbox;
      break;
    }
    if (mode == vk::PresentModeKHR::eImmediate) {
      // Satisfactory choice: fastest, but tears.
      swapchain_present_mode = vk::PresentModeKHR::eImmediate;
    }
  }
#endif

  // Determine number of images in the swapchain.
  swapchain_image_count_ = kDesiredSwapchainImageCount;
  if (surface_caps.minImageCount > swapchain_image_count_) {
    swapchain_image_count_ = surface_caps.minImageCount;
  } else if (surface_caps.maxImageCount < swapchain_image_count_ &&
             surface_caps.maxImageCount != 0) {  // 0 means "no limit"
    swapchain_image_count_ = surface_caps.maxImageCount;
  }

  // TODO: choosing an appropriate pre-transform will probably be important on
  // mobile devices.
  auto pre_transform = vk::SurfaceTransformFlagBitsKHR::eIdentity;

  // Pick a format and color-space for the swap-chain.
  vk::Format format = vk::Format::eUndefined;
  vk::ColorSpaceKHR color_space = vk::ColorSpaceKHR::eSrgbNonlinear;
  {
    auto result = physical_device.getSurfaceFormatsKHR(surface);
    VK_CHECK_RESULT(result);
    for (auto& sf : result.value) {
      if (sf.colorSpace != color_space)
        continue;

      // TODO: remove this once Magma supports SRGB swapchains.
      if (sf.format == vk::Format::eB8G8R8A8Unorm) {
        format = sf.format;
        break;
      }

      if (sf.format == vk::Format::eB8G8R8A8Srgb) {
        // eB8G8R8A8Srgb is our favorite!
        format = sf.format;
        break;
      } else if (format == vk::Format::eUndefined) {
        // Anything is better than eUndefined.
        format = sf.format;
      }
    }
  }
  FXL_CHECK(format != vk::Format::eUndefined);

  // TODO: old_swapchain will come into play (I think) when we support
  // resizing the window.
  vk::SwapchainKHR old_swapchain = nullptr;

  // Create the swapchain.
  vk::SwapchainKHR swapchain;
  {
    vk::SwapchainCreateInfoKHR info;
    info.surface = surface;
    info.minImageCount = swapchain_image_count_;
    info.imageFormat = format;
    info.imageColorSpace = color_space;
    info.imageExtent = swapchain_extent;
    info.imageArrayLayers = 1;  // TODO: what is this?
    // Using eTransferDst allows us to blit debug info onto the surface.
    // Using eSampled allows us to save memory by using the color attachment
    // for intermediate computation.
    info.imageUsage = vk::ImageUsageFlagBits::eColorAttachment |
                      vk::ImageUsageFlagBits::eTransferDst |
                      vk::ImageUsageFlagBits::eSampled;
    info.queueFamilyIndexCount = 1;
    uint32_t queue_family_index = device_queues->vk_main_queue_family();
    info.pQueueFamilyIndices = &queue_family_index;
    info.preTransform = pre_transform;
    info.presentMode = swapchain_present_mode;
    info.oldSwapchain = old_swapchain;
    info.clipped = true;

    auto result = device_.createSwapchainKHR(info);
    VK_CHECK_RESULT(result);
    swapchain = result.value;
  }

  if (old_swapchain) {
    // Note: destroying the swapchain also cleans up all its associated
    // presentable images once the platform is done with them.
    device_.destroySwapchainKHR(old_swapchain);
  }

  // Obtain swapchain images and buffers.
  {
    auto result = device_.getSwapchainImagesKHR(swapchain);
    VK_CHECK_RESULT(result);

    std::vector<vk::Image> images(std::move(result.value));
    std::vector<escher::ImagePtr> escher_images;
    escher_images.reserve(images.size());
    for (auto& im : images) {
      escher::ImageInfo image_info;
      image_info.format = format;
      image_info.width = swapchain_extent.width;
      image_info.height = swapchain_extent.height;
      image_info.usage = vk::ImageUsageFlagBits::eColorAttachment;
      // The swapchain maintains ownership of the vk::Image objects in the
      // images array, so we only wrap them here, instead of adopting them.
      auto escher_image = escher::Image::WrapVkImage(recycler, image_info, im);
      FXL_CHECK(escher_image);
      escher_images.push_back(escher_image);
    }
    swapchain_ = escher::VulkanSwapchain(
        swapchain, escher_images, swapchain_extent.width,
        swapchain_extent.height, format, color_space);
  }
}

bool VulkanDisplaySwapchain::DrawAndPresentFrame(
    const FrameTimingsPtr& frame_timings, const HardwareLayerAssignment& hla,
    DrawCallback draw_callback) {
  FXL_DCHECK(frame_timings);
  FXL_DCHECK(hla.swapchain == this);

  // Vulkan swapchain doesn't have any notion of hardware layers; the caller
  // must be aware of this and pass in an appropriate HardwareLayerAssignment.
  FXL_DCHECK(hla.items.size() == 1 && hla.items[0].hardware_layer_id == 0);
  auto& hla_item = hla.items[0];

  // TODO(MZ-260): replace Vulkan swapchain with Magma C ABI calls, and use
  // EventTimestamper::Wait to notify |frame| when the frame is finished
  // rendering, and when it is presented.
  auto timing_index = frame_timings->AddSwapchain(this);
  if (event_timestamper_ && !event_timestamper_) {
    // Avoid unused-variable error.
    FXL_CHECK(false) << "I don't believe you.";
  }

  auto& image_available_semaphore =
      image_available_semaphores_[next_semaphore_index_];
  auto& render_finished_semaphore =
      render_finished_semaphores_[next_semaphore_index_];

  uint32_t swapchain_index;
  {
    TRACE_DURATION("gfx", "VulkanDisplaySwapchain::DrawAndPresent() acquire");

    auto result = device_.acquireNextImageKHR(
        swapchain_.swapchain, UINT64_MAX,
        image_available_semaphore->vk_semaphore(), nullptr);

    if (result.result == vk::Result::eSuboptimalKHR) {
      FXL_DLOG(WARNING) << "suboptimal swapchain configuration";
    } else if (result.result != vk::Result::eSuccess) {
      FXL_LOG(WARNING) << "failed to acquire next swapchain image"
                       << " : " << to_string(result.result);
      return false;
    }

    swapchain_index = result.value;
    next_semaphore_index_ =
        (next_semaphore_index_ + 1) % swapchain_.images.size();
  }

  // Render the scene.  The Renderer will wait for acquireNextImageKHR() to
  // signal the semaphore.
  draw_callback(frame_timings->target_presentation_time(),
                swapchain_.images[swapchain_index], hla_item,
                image_available_semaphore, render_finished_semaphore);

  // When the image is completely rendered, present it.
  TRACE_DURATION("gfx", "VulkanDisplaySwapchain::DrawAndPresent() present");
  vk::PresentInfoKHR info;
  info.waitSemaphoreCount = 1;
  auto sema = render_finished_semaphore->vk_semaphore();
  info.pWaitSemaphores = &sema;
  info.swapchainCount = 1;
  info.pSwapchains = &swapchain_.swapchain;
  info.pImageIndices = &swapchain_index;

  // TODO(MZ-244): handle this more robustly.
  if (queue_.presentKHR(info) != vk::Result::eSuccess) {
    FXL_DCHECK(false)
        << "VulkanDisplaySwapchain::DrawAndPresentFrame(): failed to "
           "present rendered image.";
  }
  // TODO: Wait for sema before triggering callbacks. This class is only used
  // for debugging, so the precise timestamps don't matter as much.
  async::PostTask(
      async_get_default_dispatcher(), [frame_timings, timing_index] {
        frame_timings->OnFrameRendered(timing_index, dispatcher_clock_now());
        frame_timings->OnFramePresented(timing_index, dispatcher_clock_now());
      });

  return true;
}

}  // namespace gfx
}  // namespace scenic_impl
