// 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 "anv_wsi_magma.h"
#include "anv_magma.h"
#include "wsi_common_magma.h"
#include <fcntl.h>

#include "vk_format_info.h"

VkBool32 anv_GetPhysicalDeviceMagmaPresentationSupportKHR(VkPhysicalDevice physicalDevice,
                                                          uint32_t queueFamilyIndex)
{
   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);

   return wsi_get_physical_device_magma_presentation_support(
       &device->wsi_device, &device->instance->alloc, queueFamilyIndex);
}

VkResult anv_CreateMagmaSurfaceKHR(VkInstance _instance,
                                   const VkMagmaSurfaceCreateInfoKHR* pCreateInfo,
                                   const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface)
{
   ANV_FROM_HANDLE(anv_instance, instance, _instance);

   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR);
   assert(pCreateInfo->imagePipeHandle == 0);

   if (!pAllocator)
      pAllocator = &instance->alloc;

   auto surface = reinterpret_cast<VkIcdSurfaceMagma*>(
       vk_alloc(pAllocator, sizeof(VkIcdSurfaceMagma), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
   if (!surface)
      return VK_ERROR_OUT_OF_HOST_MEMORY;

   surface->base.platform = VK_ICD_WSI_PLATFORM_MAGMA;
   surface->fd = open("/dev/class/display/000", O_RDONLY);

   if (surface->fd >= 0)
      surface->connection = magma_create_connection(surface->fd, MAGMA_CAPABILITY_DISPLAY);
   else
      surface->connection = nullptr;

   *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);

   return VK_SUCCESS;
}

void* anv_wsi_magma_get_render_connection(VkDevice device)
{
   return anv_device_from_handle(device)->connection;
}

void anv_wsi_magma_destroy_surface(VkIcdSurfaceBase* icd_surface)
{
   auto surface = reinterpret_cast<VkIcdSurfaceMagma*>(icd_surface);
   if (surface->connection)
      magma_release_connection(reinterpret_cast<magma_connection_t*>(surface->connection));
   if (surface->fd >= 0)
      close(surface->fd);
}

VkResult anv_wsi_magma_image_create(VkDevice device_h, const VkSwapchainCreateInfoKHR* pCreateInfo,
                                    const VkAllocationCallbacks* pAllocator, VkImage* image_p,
                                    VkDeviceMemory* memory_p, uint32_t* size, uint32_t* offset,
                                    uint32_t* row_pitch, uintptr_t* buffer_handle_p)
{
   struct anv_device* device = anv_device_from_handle(device_h);
   VkImage image_h;
   struct anv_image* image;
   int ret;

   VkImageCreateInfo create_info = {
       .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
       .imageType = VK_IMAGE_TYPE_2D,
       .format = pCreateInfo->imageFormat,
       .extent = {.width = pCreateInfo->imageExtent.width,
                  .height = pCreateInfo->imageExtent.height,
                  .depth = 1},
       .mipLevels = 1,
       .arrayLayers = 1,
       .samples = VK_SAMPLE_COUNT_1_BIT,
       .tiling = VK_IMAGE_TILING_OPTIMAL,
       .usage = (pCreateInfo->imageUsage |
          VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
          VK_IMAGE_USAGE_SCANOUT_BIT_GOOGLE),
       .flags = 0,
   };

   anv_image_create_info image_create_info = {
       .isl_tiling_flags = 0, .stride = 0, .vk_info = &create_info};

   VkResult result;
   result = anv_image_create(anv_device_to_handle(device), &image_create_info, NULL, &image_h);

   if (result != VK_SUCCESS)
      return result;

   image = anv_image_from_handle(image_h);
   assert(vk_format_is_color(image->vk_format));

   VkMemoryAllocateInfo allocate_info = {
       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
       .allocationSize = image->size,
       .memoryTypeIndex = 0,
   };

   VkDeviceMemory memory_h;
   struct anv_device_memory* memory;
   result = anv_AllocateMemory(anv_device_to_handle(device), &allocate_info,
                               NULL /* XXX: pAllocator */, &memory_h);
   if (result != VK_SUCCESS) {
      anv_DestroyImage(device_h, image_h, pAllocator);
      return result;
   }

   memory = anv_device_memory_from_handle(memory_h);

   anv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0);
   assert(image->planes[0].offset == 0);

   struct anv_surface *surface = &image->planes[0].surface;

   *row_pitch = surface->isl.row_pitch;
   *image_p = image_h;
   *memory_p = memory_h;
   *buffer_handle_p = image->planes[0].bo->gem_handle;
   *size = image->size;
   *offset = 0;
   return VK_SUCCESS;
}

void anv_wsi_magma_image_free(VkDevice device, const VkAllocationCallbacks* pAllocator,
                              VkImage image_h, VkDeviceMemory memory_h)
{
   anv_DestroyImage(device, image_h, pAllocator);

   anv_FreeMemory(device, memory_h, pAllocator);
}

uintptr_t anv_wsi_magma_get_platform_semaphore(VkDevice vk_device, VkSemaphore vk_semaphore)
{
   anv_device* device = anv_device_from_handle(vk_device);
   ANV_FROM_HANDLE(anv_semaphore, semaphore, vk_semaphore);
   anv_semaphore_impl* impl = semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE
                              ? &semaphore->temporary : &semaphore->permanent;
   return impl->syncobj;
}
