// Copyright 2018 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 "image_pipe_surface_display.h"

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/hardware/display/c/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <zircon/pixelformat.h>
#include <zircon/status.h>

#include <deque>

#include <fbl/unique_fd.h>

#include "src/lib/fsl/handles/object_info.h"
#include "vk_dispatch_table_helper.h"
#include "vulkan/vk_layer.h"

namespace image_pipe_swapchain {

ImagePipeSurfaceDisplay::ImagePipeSurfaceDisplay()
    : loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}

bool ImagePipeSurfaceDisplay::Init() {
  zx_status_t status = fdio_service_connect("/svc/fuchsia.sysmem.Allocator",
                                            sysmem_allocator_.NewRequest().TakeChannel().release());

  if (status != ZX_OK) {
    fprintf(stderr, "Couldn't connect to sysmem service\n");
    return false;
  }

  sysmem_allocator_->SetDebugClientInfo(fsl::GetCurrentProcessName(), fsl::GetCurrentProcessKoid());

  // Probe /dev/class/display-controller/ for a display controller name.
  // When the display driver restarts it comes up with a new one (e.g. '001'
  // instead of '000'). For now, simply take the first file found in the
  // directory.
  const char kDir[] = "/dev/class/display-controller";
  std::string filename;

  {
    DIR* dir = opendir("/dev/class/display-controller");
    if (!dir) {
      fprintf(stderr, "Can't open directory: %s: %s\n", kDir, strerror(errno));
      return false;
    }

    errno = 0;
    for (;;) {
      dirent* entry = readdir(dir);
      if (!entry) {
        if (errno != 0) {
          // An error occured while reading the directory.
          fprintf(stderr, "Warning: error while reading %s: %s\n", kDir, strerror(errno));
        }
        break;
      }
      // Skip over '.' and '..' if present.
      if (entry->d_name[0] == '.' && (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")))
        continue;

      filename = std::string(kDir) + "/" + entry->d_name;
      break;
    }
    closedir(dir);
  }

  if (filename.empty()) {
    fprintf(stderr, "No display controller.\n");
    return false;
  }

  fbl::unique_fd fd(open(filename.c_str(), O_RDWR));
  if (!fd) {
    fprintf(stderr, "Could not open display controller: %s\n", strerror(errno));
    return false;
  }

  zx::channel device_server, device_client;
  status = zx::channel::create(0, &device_server, &device_client);
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to create device channel %d (%s)\n", status,
            zx_status_get_string(status));
    return false;
  }

  zx::channel dc_server, dc_client;
  status = zx::channel::create(0, &dc_server, &dc_client);
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to create controller channel %d (%s)\n", status,
            zx_status_get_string(status));
    return false;
  }

  fdio_cpp::FdioCaller caller(std::move(fd));
  zx_status_t fidl_status = fuchsia_hardware_display_ProviderOpenController(
      caller.borrow_channel(), device_server.release(), dc_server.release(), &status);
  if (fidl_status != ZX_OK) {
    fprintf(stderr, "Failed to call service handle %d (%s)\n", fidl_status,
            zx_status_get_string(fidl_status));
    return false;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to open controller %d (%s)\n", status, zx_status_get_string(status));
    return false;
  }

  dc_device_ = std::move(device_client);

  display_controller_.Bind(std::move(dc_client), loop_.dispatcher());

  display_controller_.set_error_handler(
      fit::bind_member(this, &ImagePipeSurfaceDisplay::ControllerError));

  display_controller_.events().OnDisplaysChanged =
      fit::bind_member(this, &ImagePipeSurfaceDisplay::ControllerOnDisplaysChanged);
  while (!have_display_) {
    loop_.Run(zx::time::infinite(), true);
    if (display_connection_exited_)
      return false;
  }
  return true;
}

void ImagePipeSurfaceDisplay::ControllerError(zx_status_t status) {
  display_connection_exited_ = true;
}

bool ImagePipeSurfaceDisplay::WaitForAsyncMessage() {
  got_message_response_ = false;
  while (!got_message_response_ && !display_connection_exited_) {
    loop_.Run(zx::time::infinite(), true);
  }
  return !display_connection_exited_;
}

void ImagePipeSurfaceDisplay::ControllerOnDisplaysChanged(
    std::vector<fuchsia::hardware::display::Info> info, std::vector<uint64_t>) {
  if (info.size() == 0)
    return;
  width_ = info[0].modes[0].horizontal_resolution;
  height_ = info[0].modes[0].vertical_resolution;
  display_id_ = info[0].id;
  std::deque<VkSurfaceFormatKHR> formats;
  auto pixel_format = reinterpret_cast<const int32_t*>(info[0].pixel_format.data());
  for (unsigned i = 0; i < info[0].pixel_format.size(); i++) {
    switch (pixel_format[i]) {
      case ZX_PIXEL_FORMAT_RGB_x888:
        formats.push_back({VK_FORMAT_B8G8R8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR});
        formats.push_back({VK_FORMAT_B8G8R8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR});
        break;
      case ZX_PIXEL_FORMAT_BGR_888x:
        // Push front to prefer R8G8B8A8 formats.
        formats.push_front({VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR});
        formats.push_front({VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR});
        break;
      default:
        // Ignore unknown formats.
        break;
    }
  }
  supported_image_properties_ =
      SupportedImageProperties{.formats = {formats.begin(), formats.end()}};
  have_display_ = true;
}

bool ImagePipeSurfaceDisplay::CreateImage(VkDevice device, VkLayerDispatchTable* pDisp,
                                          VkFormat format, VkImageUsageFlags usage,
                                          VkSwapchainCreateFlagsKHR swapchain_flags,
                                          VkExtent2D extent, uint32_t image_count,
                                          const VkAllocationCallbacks* pAllocator,
                                          std::vector<ImageInfo>* image_info_out) {
  VkResult result;
  fuchsia::sysmem::BufferCollectionTokenSyncPtr local_token;
  zx_status_t status;
  status = sysmem_allocator_->AllocateSharedCollection(local_token.NewRequest());
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: AllocateSharedCollection failed: %d\n", status);
    return false;
  }
  fuchsia::sysmem::BufferCollectionTokenSyncPtr vulkan_token;

  status = local_token->Duplicate(std::numeric_limits<uint32_t>::max(), vulkan_token.NewRequest());
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: Duplicate failed: %d\n", status);
    return false;
  }
  fuchsia::sysmem::BufferCollectionTokenSyncPtr display_token;

  status =
      vulkan_token->Duplicate(std::numeric_limits<uint32_t>::max(), display_token.NewRequest());
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: Duplicate failed: %d\n", status);
    return false;
  }
  status = vulkan_token->Sync();
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: Sync failed: %d\n", status);
    return false;
  }

  constexpr uint32_t kBufferCollectionId = 1;

  display_controller_->ImportBufferCollection(kBufferCollectionId, std::move(display_token),
                                              [this, &status](zx_status_t import_status) {
                                                status = import_status;
                                                got_message_response_ = true;
                                              });
  if (!WaitForAsyncMessage()) {
    fprintf(stderr, "Swapchain: Display Disconnected\n");
    return false;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: ImportBufferCollection failed: %d\n", status);
    return false;
  }

  fuchsia::hardware::display::ImageConfig image_config = {
      .width = extent.width,
      .height = extent.height,
  };
  // Zircon and Vulkan format names use different component orders.
  //
  // Zircon format specifies the order and sizes of the components in a native type on a
  // little-endian system, with the leftmost component stored in the most significant bits,
  // and the rightmost in the least significant bits. For Vulkan, the leftmost component is
  // stored at the lowest address and the rightmost component at the highest address.
  switch (format) {
    case VK_FORMAT_B8G8R8A8_UNORM:
    case VK_FORMAT_B8G8R8A8_SRGB:
      image_config.pixel_format = ZX_PIXEL_FORMAT_RGB_x888;
      break;
    case VK_FORMAT_R8G8B8A8_UNORM:
    case VK_FORMAT_R8G8B8A8_SRGB:
      image_config.pixel_format = ZX_PIXEL_FORMAT_BGR_888x;
      break;
    default:
      // Unsupported format.
      return false;
  }
#if defined(__x86_64__)
  // Must be consistent with intel-gpu-core.h
  const uint32_t kImageTypeXTiled = 1;
  image_config.type = kImageTypeXTiled;
#elif defined(__aarch64__)
  image_config.type = 0;
#else
  // Unsupported display.
  return false;
#endif

  display_controller_->SetBufferCollectionConstraints(
      kBufferCollectionId, image_config, [this, &status](zx_status_t constraint_status) {
        status = constraint_status;
        got_message_response_ = true;
      });
  if (!WaitForAsyncMessage()) {
    fprintf(stderr, "Swapchain: Display Disconnected\n");
    return false;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: SetBufferCollectionConstraints failed: %d\n", status);
    return false;
  }

  uint32_t image_flags = 0;
  if (swapchain_flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
    image_flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
  if (swapchain_flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR)
    image_flags |= VK_IMAGE_CREATE_PROTECTED_BIT;

  VkImageCreateInfo image_create_info = {
      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
      .pNext = nullptr,
      .flags = image_flags,
      .imageType = VK_IMAGE_TYPE_2D,
      .format = format,
      .extent = VkExtent3D{extent.width, extent.height, 1},
      .mipLevels = 1,
      .arrayLayers = 1,
      .samples = VK_SAMPLE_COUNT_1_BIT,
      .tiling = VK_IMAGE_TILING_OPTIMAL,
      .usage = usage,
      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
      .queueFamilyIndexCount = 0,      // not used since not sharing
      .pQueueFamilyIndices = nullptr,  // not used since not sharing
      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  };

  VkBufferCollectionCreateInfoFUCHSIA import_info = {
      .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA,
      .pNext = nullptr,
      .collectionToken = vulkan_token.Unbind().TakeChannel().release(),
  };
  VkBufferCollectionFUCHSIA collection;
  result = pDisp->CreateBufferCollectionFUCHSIA(device, &import_info, pAllocator, &collection);
  if (result != VK_SUCCESS) {
    fprintf(stderr, "Failed to import buffer collection: %d\n", result);
    return false;
  }

  result = pDisp->SetBufferCollectionConstraintsFUCHSIA(device, collection, &image_create_info);

  if (result != VK_SUCCESS) {
    fprintf(stderr, "Failed to import buffer collection: %d\n", result);
    return false;
  }

  fuchsia::sysmem::BufferCollectionSyncPtr sysmem_collection;
  status = sysmem_allocator_->BindSharedCollection(std::move(local_token),
                                                   sysmem_collection.NewRequest());
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: BindSharedCollection failed: %d\n", status);
    return false;
  }
  // 1000 should override the generic Magma name.
  constexpr uint32_t kNamePriority = 1000u;
  const char* kImageName = "ImagePipeSurfaceDisplay";
  sysmem_collection->SetName(kNamePriority, kImageName);
  fuchsia::sysmem::BufferCollectionConstraints constraints{};
  constraints.min_buffer_count = image_count;
  // Used because every constraints need to have a usage.
  constraints.usage.display = fuchsia::sysmem::displayUsageLayer;
  status = sysmem_collection->SetConstraints(true, constraints);
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: SetConstraints failed: %d\n", status);
    return false;
  }

  zx_status_t allocation_status = ZX_OK;
  fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info{};
  status = sysmem_collection->WaitForBuffersAllocated(&allocation_status, &buffer_collection_info);
  if (status != ZX_OK || allocation_status != ZX_OK) {
    fprintf(stderr, "Swapchain: WaitForBuffersAllocated failed: %d %d\n", status,
            allocation_status);
    return false;
  }
  sysmem_collection->Close();

  if (buffer_collection_info.buffer_count != image_count) {
    fprintf(stderr, "Swapchain: incorrect image count %d allocated vs. %d requested\n",
            buffer_collection_info.buffer_count, image_count);
    return false;
  }

  for (uint32_t i = 0; i < image_count; ++i) {
    VkExternalMemoryImageCreateInfo external_image_create_info = {
        .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
        .pNext = nullptr,
        .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA,
    };
    VkBufferCollectionImageCreateInfoFUCHSIA image_format_fuchsia = {
        .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA,
        .pNext = &external_image_create_info,
        .collection = collection,
        .index = i};
    image_create_info.pNext = &image_format_fuchsia;

    VkImage image;
    result = pDisp->CreateImage(device, &image_create_info, pAllocator, &image);
    if (result != VK_SUCCESS) {
      fprintf(stderr, "Swapchain: vkCreateImage failed: %d\n", result);
      return false;
    }

    VkMemoryRequirements memory_requirements;
    pDisp->GetImageMemoryRequirements(device, image, &memory_requirements);

    VkBufferCollectionPropertiesFUCHSIA properties = {
        .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA};
    result = pDisp->GetBufferCollectionPropertiesFUCHSIA(device, collection, &properties);
    if (result != VK_SUCCESS) {
      fprintf(stderr, "Swapchain: GetBufferCollectionPropertiesFUCHSIA failed: %d\n", status);
      return false;
    }

    // Find lowest usable index.
    uint32_t memory_type_index =
        __builtin_ctz(memory_requirements.memoryTypeBits & properties.memoryTypeBits);

    VkMemoryDedicatedAllocateInfoKHR dedicated_info = {
        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
        .image = image,
    };
    VkImportMemoryBufferCollectionFUCHSIA import_info = {
        .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA,
        .pNext = &dedicated_info,
        .collection = collection,
        .index = i,
    };

    VkMemoryAllocateInfo alloc_info{
        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
        .pNext = &import_info,
        .allocationSize = memory_requirements.size,
        .memoryTypeIndex = memory_type_index,
    };
    VkDeviceMemory memory;
    result = pDisp->AllocateMemory(device, &alloc_info, pAllocator, &memory);
    if (result != VK_SUCCESS) {
      fprintf(stderr, "Swapchain: vkAllocateMemory failed: %d\n", result);
      return result;
    }
    result = pDisp->BindImageMemory(device, image, memory, 0);
    if (result != VK_SUCCESS) {
      fprintf(stderr, "Swapchain: vkBindImageMemory failed: %d\n", result);
      return result;
    }

    uint64_t fb_image_id;
    display_controller_->ImportImage(
        image_config, kBufferCollectionId, i,
        [this, &status, &fb_image_id](zx_status_t import_status, uint64_t image_id) {
          status = import_status;
          fb_image_id = image_id;
          got_message_response_ = true;
        });

    if (!WaitForAsyncMessage()) {
      return false;
    }
    if (status != ZX_OK) {
      fprintf(stderr, "Swapchain: ImportVmoImage failed: %d\n", status);
      return false;
    }

    ImageInfo info = {.image = image, .memory = memory, .image_id = next_image_id()};

    image_info_out->push_back(info);

    image_id_map[info.image_id] = fb_image_id;
  }

  pDisp->DestroyBufferCollectionFUCHSIA(device, collection, pAllocator);
  display_controller_->ReleaseBufferCollection(kBufferCollectionId);

  display_controller_->CreateLayer([this, &status](zx_status_t layer_status, uint64_t layer_id) {
    status = layer_status;
    layer_id_ = layer_id;
    got_message_response_ = true;
  });
  if (!WaitForAsyncMessage()) {
    return false;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Swapchain: CreateLayer failed: %d\n", status);
    return false;
  }

  display_controller_->SetDisplayLayers(display_id_, std::vector<uint64_t>{layer_id_});
  display_controller_->SetLayerPrimaryConfig(layer_id_, image_config);

  return true;
}

bool ImagePipeSurfaceDisplay::GetSize(uint32_t* width_out, uint32_t* height_out) {
  *width_out = width_;
  *height_out = height_;
  return true;
}

void ImagePipeSurfaceDisplay::RemoveImage(uint32_t image_id) {
  auto iter = image_id_map.find(image_id);
  if (iter != image_id_map.end()) {
    image_id_map.erase(iter);
  }
}

void ImagePipeSurfaceDisplay::PresentImage(
    uint32_t image_id, std::vector<std::unique_ptr<PlatformEvent>> acquire_fences,
    std::vector<std::unique_ptr<PlatformEvent>> release_fences, VkQueue queue) {
  assert(acquire_fences.size() <= 1);
  assert(release_fences.size() <= 1);

  auto iter = image_id_map.find(image_id);
  if (iter == image_id_map.end()) {
    fprintf(stderr, "PresentImage: can't find image_id %u\n", image_id);
    return;
  }

  uint64_t wait_event_id = fuchsia::hardware::display::INVALID_DISP_ID;
  if (acquire_fences.size()) {
    zx::event event = static_cast<FuchsiaEvent*>(acquire_fences[0].get())->Take();

    zx_info_handle_basic_t info;
    zx_status_t status =
        event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    if (status != ZX_OK) {
      fprintf(stderr, "failed to get event id: %d\n", status);
      return;
    }
    wait_event_id = info.koid;
    display_controller_->ImportEvent(std::move(event), wait_event_id);
    if (status != ZX_OK) {
      fprintf(stderr, "fb_import_event failed: %d\n", status);
      return;
    }
  }

  uint64_t signal_event_id = fuchsia::hardware::display::INVALID_DISP_ID;
  if (release_fences.size()) {
    zx::event event = static_cast<FuchsiaEvent*>(release_fences[0].get())->Take();

    zx_info_handle_basic_t info;
    zx_status_t status =
        event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    if (status != ZX_OK) {
      fprintf(stderr, "failed to get event id: %d\n", status);
      return;
    }
    signal_event_id = info.koid;
    display_controller_->ImportEvent(std::move(event), signal_event_id);
    if (status != ZX_OK) {
      fprintf(stderr, "fb_import_event failed: %d\n", status);
      return;
    }
  }

  display_controller_->SetLayerImage(layer_id_, iter->second, wait_event_id, signal_event_id);
  display_controller_->ApplyConfig();

  if (wait_event_id != fuchsia::hardware::display::INVALID_DISP_ID) {
    display_controller_->ReleaseEvent(wait_event_id);
  }

  if (signal_event_id != fuchsia::hardware::display::INVALID_DISP_ID) {
    display_controller_->ReleaseEvent(signal_event_id);
  }
}

SupportedImageProperties& ImagePipeSurfaceDisplay::GetSupportedImageProperties() {
  return supported_image_properties_;
}

}  // namespace image_pipe_swapchain
