// 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 "drm_command_buffer.h"
#include "magma_system.h"
#include "magma_util/dlog.h"
#include "magma_util/macros.h"
#include "magma_util/sleep.h"
// clang-format off
#include "anv_private.h"
// clang-format on

static magma_connection_t* magma_connection(anv_device* device)
{
   DASSERT(device);
   DASSERT(device->connection);
   return device->connection;
}

int anv_gem_connect(anv_device* device)
{
   device->connection =
       magma_open(device->fd, MAGMA_SYSTEM_CAPABILITY_RENDERING | MAGMA_SYSTEM_CAPABILITY_DISPLAY);
   if (!device->connection)
      return DRET_MSG(-1, "magma_system_open failed");

   DLOG("opened a magma system connection");
   return 0;
}

void anv_gem_disconnect(anv_device* device)
{
   magma_close(magma_connection(device));
   DLOG("closed the magma system connection");
}

// Return handle, or 0 on failure. Gem handles are never 0.
anv_buffer_handle_t anv_gem_create(anv_device* device, size_t size)
{
   magma_buffer_t buffer;
   uint64_t magma_size = size;
   if (magma_alloc(magma_connection(device), magma_size, &magma_size, &buffer) != 0) {
      DLOG("magma_system_alloc failed size 0x%zx", magma_size);
      return 0;
   }
   DLOG("magma_system_alloc size 0x%zx returning buffer 0x%lx", magma_size, buffer);

   DASSERT(buffer != 0);
   return buffer;
}

void anv_gem_close(anv_device* device, anv_buffer_handle_t handle)
{
   DLOG("anv_gem_close handle 0x%lx", handle);
   magma_free(magma_connection(device), handle);
}

void* anv_gem_mmap(anv_device* device, anv_buffer_handle_t handle, uint64_t offset, uint64_t size,
                   uint32_t flags)
{
   DASSERT(flags == 0);
   void* addr;
   if (magma_map(magma_connection(device), handle, &addr) != 0)
      return DRETP(nullptr, "magma_system_map failed");
   DLOG("magma_system_map handle 0x%lx size 0x%zx returning %p", handle, size, addr);
   return reinterpret_cast<uint8_t*>(addr) + offset;
}

void anv_gem_munmap(anv_device* device, anv_buffer_handle_t gem_handle, void* addr, uint64_t size)
{
   if (!addr)
      return;

   if (magma_unmap(magma_connection(device), gem_handle) != 0) {
      DLOG("magma_system_unmap failed");
      return;
   }

   DLOG("magma_system_unmap handle 0x%lx", gem_handle);
}

uint32_t anv_gem_userptr(anv_device* device, void* mem, size_t size)
{
   DLOG("anv_gem_userptr - STUB");
   DASSERT(false);
   return 0;
}

int anv_gem_set_caching(anv_device* device, anv_buffer_handle_t gem_handle, uint32_t caching)
{
   DLOG("anv_get_set_caching - STUB");
   return 0;
}

int anv_gem_set_domain(anv_device* device, anv_buffer_handle_t gem_handle, uint32_t read_domains,
                       uint32_t write_domain)
{
   DLOG("anv_gem_set_domain - STUB");
   return 0;
}

/**
 * On error, \a timeout_ns holds the remaining time.
 */
int anv_gem_wait(anv_device* device, anv_buffer_handle_t handle, int64_t* timeout_ns)
{
   magma_wait_rendering(magma_connection(device), handle);
   return 0;
}

int anv_gem_execbuffer(anv_device* device, drm_i915_gem_execbuffer2* execbuf,
                       uint32_t wait_semaphore_count, anv_semaphore_t* wait_semaphores,
                       uint32_t signal_semaphore_count, anv_semaphore_t* signal_semaphores)
{
   DLOG("anv_gem_execbuffer");

   if (execbuf->buffer_count == 0)
      return 0;

   uint64_t required_size =
       DrmCommandBuffer::RequiredSize(execbuf, wait_semaphore_count, signal_semaphore_count);

   uint64_t allocated_size;
   uint64_t cmd_buf_id;
   int32_t error;

   error = magma_alloc(magma_connection(device), required_size, &allocated_size, &cmd_buf_id);
   if (error)
      return DRET_MSG(error, "magma_system_alloc failed size 0x%" PRIx64, required_size);

   DASSERT(allocated_size >= required_size);

   void* cmd_buf_data;
   error = magma_map(magma_connection(device), cmd_buf_id, &cmd_buf_data);
   if (error) {
      magma_free(magma_connection(device), cmd_buf_id);
      return DRET_MSG(error, "magma_system_map failed");
   }

   std::vector<uint64_t> wait_semaphore_ids(wait_semaphore_count);
   for (uint32_t i = 0; i < wait_semaphore_count; i++) {
      wait_semaphore_ids[i] = magma_get_semaphore_id(wait_semaphores[i]);
   }

   std::vector<uint64_t> signal_semaphore_ids(signal_semaphore_count);
   for (uint32_t i = 0; i < signal_semaphore_count; i++) {
      signal_semaphore_ids[i] = magma_get_semaphore_id(signal_semaphores[i]);
   }

   if (!DrmCommandBuffer::Translate(execbuf, std::move(wait_semaphore_ids),
                                    std::move(signal_semaphore_ids), cmd_buf_data)) {
      error = magma_unmap(magma_connection(device), cmd_buf_id);
      DASSERT(!error);
      magma_free(magma_connection(device), cmd_buf_id);
      return DRET_MSG(error, "DrmCommandBuffer::Translate failed");
   }

   magma_submit_command_buffer(magma_connection(device), cmd_buf_id, device->context_id);

   error = magma_unmap(magma_connection(device), cmd_buf_id);
   DASSERT(!error);

   magma_free(magma_connection(device), cmd_buf_id);

   return 0;
}

int anv_gem_set_tiling(anv_device* device, anv_buffer_handle_t gem_handle, uint32_t stride,
                       uint32_t tiling)
{
   DLOG("anv_gem_set_tiling - STUB");
   return 0;
}

int anv_gem_get_param(int fd, uint32_t param)
{
   int result = 0;

   switch (param) {
   case I915_PARAM_CHIPSET_ID:
      result = magma_get_device_id(fd);
      break;
   case I915_PARAM_HAS_WAIT_TIMEOUT:
   case I915_PARAM_HAS_EXECBUF2:
      result = 1;
      break;
   }

   DLOG("anv_gem_get_param(0x%x, %u) returning %d", fd, param, result);
   return result;
}

bool anv_gem_get_bit6_swizzle(int fd, uint32_t tiling)
{
   DLOG("anv_gem_get_bit6_swizzle - STUB");
   return 0;
}

int anv_gem_create_context(anv_device* device)
{
   uint32_t context_id;
   magma_create_context(magma_connection(device), &context_id);
   DLOG("magma_system_create_context returned context_id %u", context_id);

   return static_cast<int>(context_id);
}

int anv_gem_destroy_context(anv_device* device, int context_id)
{
   magma_destroy_context(magma_connection(device), context_id);
   return 0;
}

int anv_gem_get_aperture(int fd, uint64_t* size)
{
   DLOG("anv_gem_get_aperture - STUB");
   return 0;
}

int anv_gem_handle_to_fd(anv_device* device, anv_buffer_handle_t gem_handle)
{
   DLOG("anv_gem_handle_to_fd - STUB");
   return 0;
}

anv_buffer_handle_t anv_gem_fd_to_handle(anv_device* device, int fd)
{
   DLOG("anv_gem_fd_to_handle - STUB");
   return 0;
}

VkResult anv_ExportDeviceMemoryMAGMA(VkDevice _device, VkDeviceMemory _memory, uint32_t* pHandle)
{
   DLOG("anv_ExportDeviceMemoryMAGMA");

   ANV_FROM_HANDLE(anv_device, device, _device);
   ANV_FROM_HANDLE(anv_device_memory, mem, _memory);

   auto result = magma_export(magma_connection(device), mem->bo.gem_handle, pHandle);
   DASSERT(result == MAGMA_STATUS_OK);

   return VK_SUCCESS;
}

VkResult anv_ImportDeviceMemoryMAGMA(VkDevice _device, uint32_t handle,
                                     const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMem)
{
   DLOG("anv_ImportDeviceMemoryMAGMA");
   ANV_FROM_HANDLE(anv_device, device, _device);

   struct anv_device_memory* mem = static_cast<struct anv_device_memory*>(
       vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
   if (mem == nullptr)
      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);

   magma_buffer_t magma_buffer;
   auto result = magma_import(magma_connection(device), handle, &magma_buffer);
   DASSERT(result == MAGMA_STATUS_OK);

   anv_bo_init(&mem->bo, magma_buffer, magma_get_buffer_size(magma_buffer));

   *pMem = anv_device_memory_to_handle(mem);

   return VK_SUCCESS;
}
