// 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/framebuffer_blend_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_framebuffer_blend_shaders_vk_data,
          impeller_framebuffer_blend_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
