// Copyright 2016 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 "lib/escher/vk/vulkan_swapchain_helper.h"

#include "lib/escher/impl/vulkan_utils.h"
#include "lib/escher/util/trace_macros.h"
#include "lib/escher/vk/framebuffer.h"

#include <chrono>
#include <thread>

namespace escher {

VulkanSwapchainHelper::VulkanSwapchainHelper(VulkanSwapchain swapchain,
                                             vk::Device device, vk::Queue queue)
    : swapchain_(swapchain), device_(device), queue_(queue) {
  for (size_t i = 0; i < swapchain_.images.size(); ++i) {
    image_available_semaphores_.push_back(Semaphore::New(device_));
    render_finished_semaphores_.push_back(Semaphore::New(device_));
  }
}

VulkanSwapchainHelper::~VulkanSwapchainHelper() {}

void VulkanSwapchainHelper::DrawFrame(DrawFrameCallback draw_callback) {
  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", "escher::VulkanSwapchain::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::eTimeout) {
      int retry_count = 0;
      int timeout = 2;
      while (result.result == vk::Result::eTimeout) {
        TRACE_DURATION("gfx", "escher::VulkanSwapchain::Acquire[retry]");
        if (retry_count++ > 10) {
          FXL_LOG(WARNING) << "failed to acquire next swapchain image"
                           << " : Timeout (giving up after 10 tries)";
          return;
        }

        std::chrono::duration<double, std::milli> chrono_timeout(timeout);
        std::this_thread::sleep_for(chrono_timeout);
        timeout *= 2;

        device_.waitIdle();

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

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

    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.
  auto& color_image_out = swapchain_.images[swapchain_index];
  color_image_out->SetWaitSemaphore(image_available_semaphore);
  draw_callback(color_image_out, render_finished_semaphore);

  // When the image is completely rendered, present it.
  TRACE_DURATION("gfx", "escher::VulkanSwapchain::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;
  ESCHER_LOG_VK_ERROR(queue_.presentKHR(info),
                      "failed to present rendered image");
}

}  // namespace escher
