// Copyright 2017 The Chromium 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 "flutter/content_handler/vulkan_rasterizer.h"

#include <fcntl.h>
#include <magenta/device/vfs.h>
#include <unistd.h>

#include <chrono>
#include <thread>
#include <utility>

#include "lib/ftl/files/unique_fd.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
#include "third_party/skia/src/gpu/vk/GrVkUtil.h"

namespace flutter_runner {
namespace {

constexpr char kDisplayDriverClass[] = "/dev/class/display";

void WaitForFirstDisplayDriver() {
  ftl::UniqueFD fd(open(kDisplayDriverClass, O_DIRECTORY | O_RDONLY));
  if (fd.get() < 0) {
    FTL_DLOG(ERROR) << "Failed to open " << kDisplayDriverClass;
    return;
  }

  // Create the directory watch channel.
  mx_handle_t watcher;
  if (ioctl_vfs_watch_dir(fd.get(), &watcher) < 0) {
    FTL_DLOG(ERROR) << "Failed to create directory watcher for "
                    << kDisplayDriverClass;
    return;
  }

  // Wait for 1 second for the display driver to appear before falling back to
  // software.
  mx_object_wait_one(watcher, MX_CHANNEL_READABLE | MX_CHANNEL_PEER_CLOSED,
                     mx_deadline_after(MX_SEC(1)), nullptr);
  mx_handle_close(watcher);
}

}  // namespace

VulkanRasterizer::VulkanSurfaceProducer::VulkanSurfaceProducer() {
  valid_ = Initialize();
  if (!valid_)
    FTL_LOG(ERROR) << "VulkanSurfaceProducer failed to initialize";
}

VulkanRasterizer::VulkanSurfaceProducer::~VulkanSurfaceProducer() {
  for (auto& surface_info : pending_surfaces_)
    mtl::MessageLoop::GetCurrent()->RemoveHandler(
        surface_info.second.handler_key);
}

std::unique_ptr<VulkanRasterizer::VulkanSurfaceProducer::Surface>
VulkanRasterizer::VulkanSurfaceProducer::CreateSurface(uint32_t width,
                                                       uint32_t height) {
  VkResult vk_result;

  VkImageCreateInfo image_create_info = {
      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
      .pNext = nullptr,
      .flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
      .imageType = VK_IMAGE_TYPE_2D,
      .format = VK_FORMAT_B8G8R8A8_UNORM,
      .extent = VkExtent3D{width, height, 1},
      .mipLevels = 1,
      .arrayLayers = 1,
      .samples = VK_SAMPLE_COUNT_1_BIT,
      .tiling = VK_IMAGE_TILING_OPTIMAL,
      .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
      .queueFamilyIndexCount = 0,
      .pQueueFamilyIndices = nullptr,
      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  };

  VkImage vk_image;
  vk_result = VK_CALL_LOG_ERROR(vkCreateImage(
      backend_context_->fDevice, &image_create_info, nullptr, &vk_image));
  if (vk_result)
    return nullptr;

  VkMemoryRequirements memory_reqs;
  vkGetImageMemoryRequirements(backend_context_->fDevice, vk_image,
                               &memory_reqs);

  uint32_t memory_type = 0;
  for (; memory_type < 32; memory_type++) {
    if ((memory_reqs.memoryTypeBits & (1 << memory_type)))
      break;
  }

  VkMemoryAllocateInfo alloc_info = {
      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
      .pNext = nullptr,
      .allocationSize = memory_reqs.size,
      .memoryTypeIndex = memory_type,
  };

  VkDeviceMemory vk_memory;
  vk_result = VK_CALL_LOG_ERROR(vkAllocateMemory(
      backend_context_->fDevice, &alloc_info, NULL, &vk_memory));
  if (vk_result)
    return nullptr;

  vk_result = VK_CALL_LOG_ERROR(
      vkBindImageMemory(backend_context_->fDevice, vk_image, vk_memory, 0));
  if (vk_result)
    return nullptr;

  const GrVkImageInfo image_info = {
      .fImage = vk_image,
      .fAlloc = {vk_memory, 0, memory_reqs.size, 0},
      .fImageTiling = image_create_info.tiling,
      .fImageLayout = image_create_info.initialLayout,
      .fFormat = image_create_info.format,
      .fLevelCount = image_create_info.mipLevels,
  };

  GrBackendRenderTargetDesc desc;
  desc.fWidth = width;
  desc.fHeight = height;
  desc.fConfig = kSBGRA_8888_GrPixelConfig;
  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
  desc.fSampleCnt = 0;
  desc.fStencilBits = 0;

  desc.fRenderTargetHandle = reinterpret_cast<GrBackendObject>(&image_info);

  SkSurfaceProps props(SkSurfaceProps::InitType::kLegacyFontHost_InitType);

  auto sk_surface = SkSurface::MakeFromBackendRenderTarget(context_.get(), desc,
                                                           nullptr, &props);
  if (!sk_surface) {
    FTL_LOG(ERROR) << "MakeFromBackendRenderTarget Failed";
    return nullptr;
  }

  uint32_t vmo_handle;
  vk_result = VK_CALL_LOG_ERROR(vkExportDeviceMemoryMAGMA(
      backend_context_->fDevice, vk_memory, &vmo_handle));
  if (vk_result)
    return nullptr;

  mx::vmo vmo(vmo_handle);

  size_t vmo_size;
  vmo.get_size(&vmo_size);

  FTL_DCHECK(vmo_size >= memory_reqs.size);

  mx::eventpair retention_events[2];
  auto mx_status =
      mx::eventpair::create(0, &retention_events[0], &retention_events[1]);
  if (mx_status) {
    FTL_LOG(ERROR) << "Failed to create retention eventpair";
    return nullptr;
  }

  if (!sk_surface || sk_surface->getCanvas() == nullptr) {
    FTL_LOG(ERROR) << "surface invalid";
    return nullptr;
  }

  return std::make_unique<Surface>(backend_context_, sk_surface, std::move(vmo),
                                   std::move(retention_events[0]),
                                   std::move(retention_events[1]), vk_image,
                                   vk_memory);
}

sk_sp<SkSurface> VulkanRasterizer::VulkanSurfaceProducer::ProduceSurface(
    SkISize size,
    mozart::ImagePtr* out_image) {
  if (size.isEmpty()) {
    FTL_LOG(ERROR) << "Attempting to create surface with empty size";
    return nullptr;
  }

  // these casts are safe because of the early out on frame_size.isEmpty()
  auto width = static_cast<uint32_t>(size.width());
  auto height = static_cast<uint32_t>(size.height());

  std::unique_ptr<Surface> surface;
  // try and find a Swapchain with surfaces of the right size
  auto it = available_surfaces_.find(MakeSizeKey(width, height));
  if (it == available_surfaces_.end()) {
    // No matching Swapchain exists, create a new surfaces
    surface = CreateSurface(width, height);
  } else {
    auto& swapchain = it->second;
    if (swapchain.queue.size() == 0) {
      // matching Swapchain exists, but does not have any buffers available in
      // it
      surface = CreateSurface(width, height);
    } else {
      surface = std::move(swapchain.queue.front());
      swapchain.queue.pop();
      swapchain.tick_count = 0;

      // Need to do some skia foo here to clear all the canvas state from the
      // last frame
      surface->sk_surface->getCanvas()->restoreToCount(0);
      surface->sk_surface->getCanvas()->save();
      surface->sk_surface->getCanvas()->resetMatrix();
    }
  }

  if (!surface) {
    FTL_LOG(ERROR) << "Failed to produce surface";
    return nullptr;
  }

  mx_status_t status;
  auto buffer = mozart::Buffer::New();
  status = surface->vmo.duplicate(MX_RIGHT_SAME_RIGHTS, &buffer->vmo);
  if (status) {
    FTL_LOG(ERROR) << "failed to duplicate vmo";
    return nullptr;
  }

  buffer->memory_type = mozart::Buffer::MemoryType::VK_DEVICE_MEMORY;

  mx::eventpair fence_event;
  status = mx::eventpair::create(0, &fence_event, &buffer->fence);
  if (status) {
    FTL_LOG(ERROR) << "failed to create fence eventpair";
    return nullptr;
  }

  mtl::MessageLoop::HandlerKey handler_key =
      mtl::MessageLoop::GetCurrent()->AddHandler(this, fence_event.get(),
                                                 MX_EPAIR_PEER_CLOSED);

  status = surface->remote_retention_event.duplicate(MX_RIGHT_SAME_RIGHTS,
                                                     &buffer->retention);
  if (status) {
    FTL_LOG(ERROR) << "failed to duplicate retention eventpair";
    return nullptr;
  }

  auto image = mozart::Image::New();
  image->size = mozart::Size::New();
  image->size->width = width;
  image->size->height = height;
  image->stride = 4 * width;
  image->pixel_format = mozart::Image::PixelFormat::B8G8R8A8;
  image->alpha_format = mozart::Image::AlphaFormat::OPAQUE;
  image->color_space = mozart::Image::ColorSpace::SRGB;
  image->buffer = std::move(buffer);
  *out_image = std::move(image);

  auto sk_surface = surface->sk_surface;
  PendingSurfaceInfo info;
  info.handler_key = handler_key;
  info.surface = std::move(surface);
  info.production_fence = std::move(fence_event);
  outstanding_surfaces_.push_back(std::move(info));

  return sk_surface;
}

bool VulkanRasterizer::VulkanSurfaceProducer::FinishFrame() {
  mx_status_t status;

  // Finish Rendering
  context_->flush();
  VkResult result =
      VK_CALL_LOG_ERROR(vkQueueWaitIdle(backend_context_->fQueue));
  if (result)
    return false;

  for (auto& info : outstanding_surfaces_) {
    // info.surface->sk_surface->prepareForExternalIO();
    // Signal the compositor
    status = info.production_fence.signal_peer(0u, MX_EPAIR_SIGNALED);
    if (status) {
      FTL_LOG(ERROR) << "failed to signal fence event";
      return false;
    }

    pending_surfaces_.insert(
        std::make_pair(info.production_fence.get(), std::move(info)));
  }
  outstanding_surfaces_.clear();
  return true;
}

void VulkanRasterizer::VulkanSurfaceProducer::Tick() {
  for (auto it = available_surfaces_.begin();
       it != available_surfaces_.end();) {
    auto& swapchain = it->second;
    swapchain.tick_count++;
    if (swapchain.tick_count > Swapchain::kMaxTickBeforeDiscard)
      it = available_surfaces_.erase(it);
    else
      it++;
  }
}

void VulkanRasterizer::VulkanSurfaceProducer::OnHandleReady(
    mx_handle_t handle,
    mx_signals_t pending) {
  FTL_DCHECK(pending & MX_EPAIR_PEER_CLOSED);

  auto it = pending_surfaces_.find(handle);
  FTL_DCHECK(it != pending_surfaces_.end());

  // Add the newly available buffer to the swapchain.
  PendingSurfaceInfo& info = it->second;
  mtl::MessageLoop::GetCurrent()->RemoveHandler(info.handler_key);

  // try and find a Swapchain with surfaces of the right size
  size_key_t key = MakeSizeKey(info.surface->sk_surface->width(),
                               info.surface->sk_surface->height());
  auto swapchain_it = available_surfaces_.find(key);
  if (swapchain_it == available_surfaces_.end()) {
    // No matching Swapchain exists, create one
    Swapchain swapchain;
    if (swapchain.queue.size() + 1 <= Swapchain::kMaxSurfaces) {
      swapchain.queue.push(std::move(info.surface));
    }
    available_surfaces_.insert(std::make_pair(key, std::move(swapchain)));
  } else {
    auto& swapchain = swapchain_it->second;
    if (swapchain.queue.size() + 1 <= Swapchain::kMaxSurfaces) {
      swapchain.queue.push(std::move(info.surface));
    }
  }

  pending_surfaces_.erase(it);
}

bool VulkanRasterizer::VulkanSurfaceProducer::Initialize() {
  vk_ = ftl::MakeRefCounted<vulkan::VulkanProcTable>();

  std::vector<std::string> extensions = {VK_KHR_SURFACE_EXTENSION_NAME};
  application_ = std::make_unique<vulkan::VulkanApplication>(
      *vk_, "Flutter", std::move(extensions));

  if (!application_->IsValid() || !vk_->AreInstanceProcsSetup()) {
    // Make certain the application instance was created and it setup the
    // instance proc table entries.
    FTL_LOG(ERROR) << "Instance proc addresses have not been setup.";
    return false;
  }

  // Create the device.

  logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();

  if (logical_device_ == nullptr || !logical_device_->IsValid() ||
      !vk_->AreDeviceProcsSetup()) {
    // Make certain the device was created and it setup the device proc table
    // entries.
    FTL_LOG(ERROR) << "Device proc addresses have not been setup.";
    return false;
  }

  if (!vk_->HasAcquiredMandatoryProcAddresses()) {
    FTL_LOG(ERROR) << "Failed to acquire mandatory proc addresses";
    return false;
  }

  if (!vk_->IsValid()) {
    FTL_LOG(ERROR) << "VulkanProcTable invalid";
    return false;
  }

  auto interface = vk_->CreateSkiaInterface();

  if (interface == nullptr || !interface->validate(0)) {
    FTL_LOG(ERROR) << "interface invalid";
    return false;
  }

  uint32_t skia_features = 0;
  if (!logical_device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
    FTL_LOG(ERROR) << "Failed to get physical device features";

    return false;
  }

  backend_context_ = sk_make_sp<GrVkBackendContext>();
  backend_context_->fInstance = application_->GetInstance();
  backend_context_->fPhysicalDevice =
      logical_device_->GetPhysicalDeviceHandle();
  backend_context_->fDevice = logical_device_->GetHandle();
  backend_context_->fQueue = logical_device_->GetQueueHandle();
  backend_context_->fGraphicsQueueIndex =
      logical_device_->GetGraphicsQueueIndex();
  backend_context_->fMinAPIVersion = application_->GetAPIVersion();
  backend_context_->fFeatures = skia_features;
  backend_context_->fInterface.reset(interface.release());

  logical_device_->ReleaseDeviceOwnership();
  application_->ReleaseInstanceOwnership();

  context_.reset(GrContext::Create(
      kVulkan_GrBackend,
      reinterpret_cast<GrBackendContext>(backend_context_.get())));

  FTL_DLOG(INFO) << "Successfully initialized VulkanRasterizer";
  return true;
}

VulkanRasterizer::VulkanRasterizer() : compositor_context_(nullptr) {
  WaitForFirstDisplayDriver();
  surface_producer_.reset(new VulkanSurfaceProducer());
}

VulkanRasterizer::~VulkanRasterizer() = default;

bool VulkanRasterizer::IsValid() const {
  return surface_producer_ && surface_producer_->IsValid();
}

void VulkanRasterizer::SetScene(fidl::InterfaceHandle<mozart::Scene> scene) {
  scene_.Bind(std::move(scene));
}

void VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree,
                            ftl::Closure callback) {
  Draw(std::move(layer_tree));
  callback();
}

bool VulkanRasterizer::Draw(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (layer_tree == nullptr) {
    FTL_LOG(ERROR) << "Layer tree was not valid.";
    return false;
  }

  if (!scene_) {
    FTL_LOG(ERROR) << "Scene was not valid.";
    return false;
  }

  compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());

  const SkISize& frame_size = layer_tree->frame_size();

  auto update = mozart::SceneUpdate::New();
  // TODO(abarth): Support incremental updates.
  update->clear_resources = true;
  update->clear_nodes = true;

  if (frame_size.isEmpty()) {
    update->nodes.insert(mozart::kSceneRootNodeId, mozart::Node::New());
    // Publish the updated scene contents.
    // TODO(jeffbrown): We should set the metadata's presentation_time here too.
    scene_->Update(std::move(update));
    auto metadata = mozart::SceneMetadata::New();
    metadata->version = layer_tree->scene_version();
    scene_->Publish(std::move(metadata));
    FTL_LOG(ERROR) << "Publishing empty node";

    return false;
  }

  flow::CompositorContext::ScopedFrame frame = compositor_context_.AcquireFrame(
      nullptr, nullptr, true /* instrumentation enabled */);

  layer_tree->Preroll(frame);

  flow::SceneUpdateContext context(update.get(), surface_producer_.get());
  auto root_node = mozart::Node::New();
  root_node->hit_test_behavior = mozart::HitTestBehavior::New();
  layer_tree->UpdateScene(context, root_node.get());
  update->nodes.insert(mozart::kSceneRootNodeId, std::move(root_node));

  // Publish the updated scene contents.
  // TODO(jeffbrown): We should set the metadata's presentation_time here too.
  scene_->Update(std::move(update));
  auto metadata = mozart::SceneMetadata::New();
  metadata->version = layer_tree->scene_version();
  scene_->Publish(std::move(metadata));

  // Draw the contents of the scene to a surface.
  // We do this after publishing to take advantage of pipelining.
  context.ExecutePaintTasks(frame);
  if (!surface_producer_->FinishFrame()) {
    FTL_LOG(ERROR) << "Failed to Finish Frame";
    return false;
  }
  surface_producer_->Tick();

  return true;
}

}  // namespace flutter_runner
