// Copyright 2021 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/fdio/fdio.h>
#include <lib/zx/channel.h>

#include <cstdint>
#include <cstdio>
#include <string>

#include <vulkan/vk_icd.h>
#include <vulkan/vulkan.h>

// This file contains a fake Vulkan ICD that implements everything up to and including
// vkCreateInstance.  It is (mostly) a copy of //src/graphics/tests/libvulkan/libvulkan_fake.cc,
// and will exist only temporarily, see https://fxbug.dev/42075795

VKAPI_ATTR __attribute__((visibility("default"))) VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion) {
  fprintf(stderr, "Got icd Negotiate loader ICD interface version\n");
  // NOTE: modified from //src/graphics/tests/libvulkan/libvulkan_fake.cc, thus allowing this ICD to
  // claim an API version > 1.0
  *pVersion = 5;

  return VK_SUCCESS;
}

namespace {

bool open_in_namespace_callback_initialized = false;
struct Instance {
  Instance() = default;

  // Instance is a dispatchable object, and the loader uses the first 8 bytes as a pointer. See
  // https://github.com/KhronosGroup/Vulkan-Loader/blob/master/loader/LoaderAndLayerInterface.md#icd-dispatchable-object-creation
  uintptr_t loader_magic = ICD_LOADER_MAGIC;
};

VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator,
                                                VkInstance* pInstance) {
  // Check that the open in namespace proc was set and was valid.
  if (!open_in_namespace_callback_initialized)
    return VK_ERROR_INITIALIZATION_FAILED;
  *pInstance = reinterpret_cast<VkInstance>(new Instance);
  return VK_SUCCESS;
}

VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
    const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
  *pPropertyCount = 0;
  return VK_SUCCESS;
}

VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
                                             const VkAllocationCallbacks* pAllocator) {
  delete reinterpret_cast<Instance*>(instance);
}

VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
  *pApiVersion = VK_API_VERSION_1_0;
  return VK_SUCCESS;
}

VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
                                                       VkPhysicalDeviceFeatures* pFeatures) {}

VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
    VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {}

VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(
    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
    VkImageUsageFlags usage, VkImageCreateFlags flags,
    VkImageFormatProperties* pImageFormatProperties) {
  return VK_SUCCESS;
}

VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
                                                         VkPhysicalDeviceProperties* pProperties) {}

VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
    VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount,
    VkQueueFamilyProperties* pQueueFamilyProperties) {}

VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
    VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {}

VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* pName) {
  return nullptr;
}

VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
                                              const VkDeviceCreateInfo* pCreateInfo,
                                              const VkAllocationCallbacks* pAllocator,
                                              VkDevice* pDevice) {
  return VK_ERROR_INITIALIZATION_FAILED;
}

// Only the bare minimum Vulkan 1.0 core entrypoints are implemented. These are just enough for
// vkCreateInstance to succeed.
#define DEF_FUNCTION(name) \
  { #name, reinterpret_cast<PFN_vkVoidFunction>(name) }
struct FunctionTable {
  std::string name;
  PFN_vkVoidFunction function;
} functions[] = {
    DEF_FUNCTION(vkCreateInstance),
    DEF_FUNCTION(vkDestroyInstance),
    DEF_FUNCTION(vkEnumerateInstanceVersion),
    DEF_FUNCTION(vkEnumerateInstanceExtensionProperties),
    DEF_FUNCTION(vkEnumeratePhysicalDevices),
    DEF_FUNCTION(vkGetPhysicalDeviceFeatures),
    DEF_FUNCTION(vkGetPhysicalDeviceFormatProperties),
    DEF_FUNCTION(vkGetPhysicalDeviceImageFormatProperties),
    DEF_FUNCTION(vkGetPhysicalDeviceProperties),
    DEF_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties),
    DEF_FUNCTION(vkGetPhysicalDeviceMemoryProperties),
    DEF_FUNCTION(vkGetDeviceProcAddr),
    DEF_FUNCTION(vkCreateDevice),
    DEF_FUNCTION(vkEnumerateDeviceExtensionProperties),
    DEF_FUNCTION(vkGetPhysicalDeviceSparseImageFormatProperties),
};

#undef DEF_FUNCTION

}  // namespace

VKAPI_ATTR __attribute__((visibility("default"))) PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
  for (auto& function : functions) {
    if (function.name == pName)
      return function.function;
  }
  return nullptr;
}

VKAPI_ATTR __attribute__((visibility("default"))) PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName) {
  return nullptr;
}

extern "C" {
typedef VkResult(VKAPI_PTR* PFN_vkOpenInNamespaceAddr)(const char* pName, uint32_t handle);
VKAPI_ATTR void VKAPI_CALL vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr addr);
}

VKAPI_ATTR __attribute__((visibility("default"))) void VKAPI_CALL
vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr open_in_namespace_addr) {
  zx::channel server_end, client_end;
  zx::channel::create(0, &server_end, &client_end);

  // A hermetic ICD shouldn't try to access to anything from the loader service.
  if (!getenv("HERMETIC_ICD")) {
    // ConnectToDeviceFs in the service provider should connect the device fs to /pkg/data.
    VkResult result =
        open_in_namespace_addr("/loader-gpu-devices/icd.d/lavapipe_icd.json", server_end.release());
    if (result != VK_SUCCESS) {
      fprintf(stderr, "Opening lavapipe_icd.json failed with error %d\n", result);
      return;
    }

    fdio_t* fdio;
    zx_status_t status = fdio_create(client_end.release(), &fdio);
    if (status != ZX_OK) {
      fprintf(stderr, "fdio create failed with status %d\n", status);
      return;
    }

    int fd = fdio_bind_to_fd(fdio, -1, 0);
    if (fd < 0) {
      fprintf(stderr, "fdio_bind_to_fd failed\n");
      return;
    }
  }

  open_in_namespace_callback_initialized = true;
}
