// Copyright (c) 2016 The Chromium 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 "gpu/vulkan/vulkan_surface.h"

#include <vulkan/vulkan.h>

#include "base/macros.h"
#include "base/stl_util.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_swap_chain.h"

namespace gpu {

namespace {
const VkFormat kPreferredVkFormats32[] = {
    VK_FORMAT_B8G8R8A8_UNORM,  // FORMAT_BGRA8888,
    VK_FORMAT_R8G8B8A8_UNORM,  // FORMAT_RGBA8888,
};

const VkFormat kPreferredVkFormats16[] = {
    VK_FORMAT_R5G6B5_UNORM_PACK16,  // FORMAT_RGB565,
};

}  // namespace

VulkanSurface::~VulkanSurface() {
  DCHECK_EQ(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_);
}

VulkanSurface::VulkanSurface(VkInstance vk_instance, VkSurfaceKHR surface)
    : vk_instance_(vk_instance), surface_(surface) {
  DCHECK_NE(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_);
}

bool VulkanSurface::Initialize(VulkanDeviceQueue* device_queue,
                               VulkanSurface::Format format) {
  DCHECK(format >= 0 && format < NUM_SURFACE_FORMATS);
  DCHECK(device_queue);

  device_queue_ = device_queue;

  VkResult result = VK_SUCCESS;

  VkBool32 present_support;
  if (vkGetPhysicalDeviceSurfaceSupportKHR(
          device_queue_->GetVulkanPhysicalDevice(),
          device_queue_->GetVulkanQueueIndex(), surface_,
          &present_support) != VK_SUCCESS) {
    DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceSupportKHR() failed: " << result;
    return false;
  }
  if (!present_support) {
    DLOG(ERROR) << "Surface not supported by present queue.";
    return false;
  }

  // Get list of supported formats.
  uint32_t format_count = 0;
  result = vkGetPhysicalDeviceSurfaceFormatsKHR(
      device_queue_->GetVulkanPhysicalDevice(), surface_, &format_count,
      nullptr);
  if (VK_SUCCESS != result) {
    DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
    return false;
  }

  std::vector<VkSurfaceFormatKHR> formats(format_count);
  result = vkGetPhysicalDeviceSurfaceFormatsKHR(
      device_queue_->GetVulkanPhysicalDevice(), surface_, &format_count,
      formats.data());
  if (VK_SUCCESS != result) {
    DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
    return false;
  }

  const VkFormat* preferred_formats = (format == FORMAT_RGBA_32)
                                          ? kPreferredVkFormats32
                                          : kPreferredVkFormats16;
  unsigned int size = (format == FORMAT_RGBA_32)
                          ? base::size(kPreferredVkFormats32)
                          : base::size(kPreferredVkFormats16);

  if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) {
    surface_format_.format = preferred_formats[0];
    surface_format_.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
  } else {
    bool format_set = false;
    for (VkSurfaceFormatKHR supported_format : formats) {
      unsigned int counter = 0;
      while (counter < size && format_set == false) {
        if (supported_format.format == preferred_formats[counter]) {
          surface_format_ = supported_format;
          surface_format_.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
          format_set = true;
        }
        counter++;
      }
      if (format_set)
        break;
    }
    if (!format_set) {
      DLOG(ERROR) << "Format not supported.";
      return false;
    }
  }
  // Delay creating SwapChain to when the surface size is specified by Resize().
  return true;
}

void VulkanSurface::Destroy() {
  swap_chain_->Destroy();
  vkDestroySurfaceKHR(vk_instance_, surface_, nullptr);
  surface_ = VK_NULL_HANDLE;
}

gfx::SwapResult VulkanSurface::SwapBuffers() {
  return swap_chain_->SwapBuffers();
}

VulkanSwapChain* VulkanSurface::GetSwapChain() {
  return swap_chain_.get();
}

void VulkanSurface::Finish() {
  vkQueueWaitIdle(device_queue_->GetVulkanQueue());
}

bool VulkanSurface::SetSize(const gfx::Size& size) {
  // Get Surface Information.
  VkSurfaceCapabilitiesKHR surface_caps;
  VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
      device_queue_->GetVulkanPhysicalDevice(), surface_, &surface_caps);
  if (VK_SUCCESS != result) {
    DLOG(ERROR) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: "
                << result;
    return false;
  }

  // If width and height of the surface are 0xFFFFFFFF, it means the surface
  // size will be determined by the extent of a swapchain targeting the surface.
  // In that case, we will use the |size| which is the window size for the
  // swapchain. Otherwise, we just use the current surface size for the
  // swapchian.
  if (surface_caps.currentExtent.width ==
          std::numeric_limits<uint32_t>::max() ||
      surface_caps.currentExtent.height ==
          std::numeric_limits<uint32_t>::max()) {
    DCHECK_EQ(surface_caps.currentExtent.width,
              std::numeric_limits<uint32_t>::max());
    DCHECK_EQ(surface_caps.currentExtent.height,
              std::numeric_limits<uint32_t>::max());
    surface_caps.currentExtent.width = size.width();
    surface_caps.currentExtent.height = size.height();
  }

  DCHECK_GE(surface_caps.currentExtent.width,
            surface_caps.minImageExtent.width);
  DCHECK_GE(surface_caps.currentExtent.height,
            surface_caps.minImageExtent.height);
  DCHECK_LE(surface_caps.currentExtent.width,
            surface_caps.maxImageExtent.width);
  DCHECK_LE(surface_caps.currentExtent.height,
            surface_caps.maxImageExtent.height);
  DCHECK_GT(surface_caps.currentExtent.width, 0u);
  DCHECK_GT(surface_caps.currentExtent.height, 0u);

  gfx::Size new_size(surface_caps.currentExtent.width,
                     surface_caps.currentExtent.height);
  if (size_ == new_size)
    return true;

  size_ = new_size;
  auto swap_chain = std::make_unique<VulkanSwapChain>();
  // Create Swapchain.
  if (!swap_chain->Initialize(device_queue_, surface_, surface_caps,
                              surface_format_, std::move(swap_chain_))) {
    return false;
  }

  swap_chain_ = std::move(swap_chain);
  return true;
}

}  // namespace gpu
