// 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 "impeller/playground/backend/vulkan/playground_impl_vk.h"

#include "flutter/fml/paths.h"
#include "impeller/renderer/backend/vulkan/vk.h"

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include "flutter/fml/logging.h"
#include "flutter/fml/mapping.h"
#include "impeller/entity/vk/entity_shaders_vk.h"
#include "impeller/entity/vk/modern_shaders_vk.h"
#include "impeller/fixtures/vk/fixtures_shaders_vk.h"
#include "impeller/playground/imgui/vk/imgui_shaders_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
#include "impeller/renderer/backend/vulkan/surface_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/vk/compute_shaders_vk.h"
#include "impeller/scene/shaders/vk/scene_shaders_vk.h"

namespace impeller {

static std::vector<std::shared_ptr<fml::Mapping>>
ShaderLibraryMappingsForPlayground() {
  return {
      std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
                                             impeller_entity_shaders_vk_length),
      std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_vk_data,
                                             impeller_modern_shaders_vk_length),
      std::make_shared<fml::NonOwnedMapping>(
          impeller_fixtures_shaders_vk_data,
          impeller_fixtures_shaders_vk_length),
      std::make_shared<fml::NonOwnedMapping>(impeller_imgui_shaders_vk_data,
                                             impeller_imgui_shaders_vk_length),
      std::make_shared<fml::NonOwnedMapping>(impeller_scene_shaders_vk_data,
                                             impeller_scene_shaders_vk_length),
      std::make_shared<fml::NonOwnedMapping>(
          impeller_compute_shaders_vk_data, impeller_compute_shaders_vk_length),
  };
}

vk::UniqueInstance PlaygroundImplVK::global_instance_;

void PlaygroundImplVK::DestroyWindowHandle(WindowHandle handle) {
  if (!handle) {
    return;
  }
  ::glfwDestroyWindow(reinterpret_cast<GLFWwindow*>(handle));
}

PlaygroundImplVK::PlaygroundImplVK(PlaygroundSwitches switches)
    : PlaygroundImpl(switches), handle_(nullptr, &DestroyWindowHandle) {
  if (!::glfwVulkanSupported()) {
#ifdef TARGET_OS_MAC
    VALIDATION_LOG << "Attempted to initialize a Vulkan playground on macOS "
                      "where Vulkan cannot be found. It can be installed via "
                      "MoltenVK and make sure to install it globally so "
                      "dlopen can find it.";
#else
    VALIDATION_LOG << "Attempted to initialize a Vulkan playground on a system "
                      "that does not support Vulkan.";
#endif
    return;
  }

  InitGlobalVulkanInstance();

  ::glfwDefaultWindowHints();
  ::glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  ::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

  auto window = ::glfwCreateWindow(1, 1, "Test", nullptr, nullptr);
  if (!window) {
    VALIDATION_LOG << "Unable to create glfw window";
    return;
  }

  handle_.reset(window);

  ContextVK::Settings context_settings;
  context_settings.proc_address_callback =
      reinterpret_cast<PFN_vkGetInstanceProcAddr>(
          &::glfwGetInstanceProcAddress);
  context_settings.shader_libraries_data = ShaderLibraryMappingsForPlayground();
  context_settings.cache_directory = fml::paths::GetCachesDirectory();
  context_settings.enable_validation = switches_.enable_vulkan_validation;

  auto context_vk = ContextVK::Create(std::move(context_settings));
  if (!context_vk || !context_vk->IsValid()) {
    VALIDATION_LOG << "Could not create Vulkan context in the playground.";
    return;
  }

  // Without this, the playground will timeout waiting for the presentation.
  // It's better to have some Vulkan validation tests running on CI to catch
  // regressions, but for now this is a workaround.
  //
  // TODO(matanlurey): https://github.com/flutter/flutter/issues/134852.
  //
  // (Note, if you're using MoltenVK, or Linux, you can comment out this line).
  context_vk->SetSyncPresentation(true);

  VkSurfaceKHR vk_surface;
  auto res = vk::Result{::glfwCreateWindowSurface(
      context_vk->GetInstance(),  // instance
      window,                     // window
      nullptr,                    // allocator
      &vk_surface                 // surface
      )};
  if (res != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create surface for GLFW window: "
                   << vk::to_string(res);
    return;
  }

  vk::UniqueSurfaceKHR surface{vk_surface, context_vk->GetInstance()};
  auto context = context_vk->CreateSurfaceContext();
  if (!context->SetWindowSurface(std::move(surface))) {
    VALIDATION_LOG << "Could not set up surface for context.";
    return;
  }

  context_ = std::move(context);
}

PlaygroundImplVK::~PlaygroundImplVK() = default;

// |PlaygroundImpl|
std::shared_ptr<Context> PlaygroundImplVK::GetContext() const {
  return context_;
}

// |PlaygroundImpl|
PlaygroundImpl::WindowHandle PlaygroundImplVK::GetWindowHandle() const {
  return handle_.get();
}

// |PlaygroundImpl|
std::unique_ptr<Surface> PlaygroundImplVK::AcquireSurfaceFrame(
    std::shared_ptr<Context> context) {
  SurfaceContextVK* surface_context_vk =
      reinterpret_cast<SurfaceContextVK*>(context_.get());
  return surface_context_vk->AcquireNextSurface();
}

// Create a global instance of Vulkan in order to prevent unloading of the
// Vulkan library.
// A test suite may repeatedly create and destroy PlaygroundImplVK instances,
// and if the PlaygroundImplVK's Vulkan instance is the only one in the
// process then the Vulkan library will be unloaded when the instance is
// destroyed.  Repeated loading and unloading of SwiftShader was leaking
// resources, so this will work around that leak.
// (see https://github.com/flutter/flutter/issues/138028)
void PlaygroundImplVK::InitGlobalVulkanInstance() {
  if (global_instance_) {
    return;
  }

  VULKAN_HPP_DEFAULT_DISPATCHER.init(::glfwGetInstanceProcAddress);

  vk::ApplicationInfo application_info;
  application_info.setApplicationVersion(VK_API_VERSION_1_0);
  application_info.setApiVersion(VK_API_VERSION_1_1);
  application_info.setEngineVersion(VK_API_VERSION_1_0);
  application_info.setPEngineName("PlaygroundImplVK");
  application_info.setPApplicationName("PlaygroundImplVK");

  auto instance_result =
      vk::createInstanceUnique(vk::InstanceCreateInfo({}, &application_info));
  FML_CHECK(instance_result.result == vk::Result::eSuccess)
      << "Unable to initialize global Vulkan instance";
  global_instance_ = std::move(instance_result.value);
}

}  // namespace impeller
