// Copyright 2013 The Flutter 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 "vulkan_surface.h"

#include <lib/async/default.h>
#include <lib/ui/scenic/cpp/commands.h>

#include <algorithm>

#include "flutter/fml/trace_event.h"
#include "runtime/dart/utils/inlines.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"

#define LOG_AND_RETURN(cond, msg) \
  if (cond) {                     \
    FML_LOG(ERROR) << msg;        \
    return false;                 \
  }

namespace flutter_runner {

namespace {

constexpr SkColorType kSkiaColorType = kRGBA_8888_SkColorType;
constexpr VkFormat kVulkanFormat = VK_FORMAT_R8G8B8A8_UNORM;
constexpr VkImageCreateFlags kVulkanImageCreateFlags = 0;
// TODO: We should only keep usages that are actually required by Skia.
constexpr VkImageUsageFlags kVkImageUsage =
    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
    VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

}  // namespace

bool VulkanSurface::CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider,
                                      const SkISize& size,
                                      VulkanImage* out_vulkan_image) {
  TRACE_EVENT0("flutter", "CreateVulkanImage");

  FML_CHECK(!size.isEmpty());
  FML_CHECK(out_vulkan_image != nullptr);

  out_vulkan_image->vk_collection_image_create_info = {
      .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA,
      .pNext = nullptr,
      .collection = collection_,
      .index = 0,
  };

  out_vulkan_image->vk_image_create_info = {
      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
      .pNext = &out_vulkan_image->vk_collection_image_create_info,
      .flags = kVulkanImageCreateFlags,
      .imageType = VK_IMAGE_TYPE_2D,
      .format = kVulkanFormat,
      .extent = VkExtent3D{static_cast<uint32_t>(size.width()),
                           static_cast<uint32_t>(size.height()), 1},
      .mipLevels = 1,
      .arrayLayers = 1,
      .samples = VK_SAMPLE_COUNT_1_BIT,
      .tiling = VK_IMAGE_TILING_OPTIMAL,
      .usage = kVkImageUsage,
      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
      .queueFamilyIndexCount = 0,
      .pQueueFamilyIndices = nullptr,
      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  };

  if (VK_CALL_LOG_ERROR(
          vulkan_provider.vk().SetBufferCollectionConstraintsFUCHSIA(
              vulkan_provider.vk_device(), collection_,
              &out_vulkan_image->vk_image_create_info)) != VK_SUCCESS) {
    return false;
  }

  {
    VkImage vk_image = VK_NULL_HANDLE;
    if (VK_CALL_LOG_ERROR(vulkan_provider.vk().CreateImage(
            vulkan_provider.vk_device(),
            &out_vulkan_image->vk_image_create_info, nullptr, &vk_image)) !=
        VK_SUCCESS) {
      return false;
    }

    out_vulkan_image->vk_image = {
        vk_image, [&vulkan_provider = vulkan_provider](VkImage image) {
          vulkan_provider.vk().DestroyImage(vulkan_provider.vk_device(), image,
                                            NULL);
        }};
  }

  vulkan_provider.vk().GetImageMemoryRequirements(
      vulkan_provider.vk_device(), out_vulkan_image->vk_image,
      &out_vulkan_image->vk_memory_requirements);

  return true;
}

VulkanSurface::VulkanSurface(
    vulkan::VulkanProvider& vulkan_provider,
    fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
    sk_sp<GrDirectContext> context,
    scenic::Session* session,
    const SkISize& size,
    uint32_t buffer_id)
    : vulkan_provider_(vulkan_provider), session_(session), wait_(this) {
  FML_CHECK(session_ != nullptr);
  FML_CHECK(context != nullptr);

  if (!AllocateDeviceMemory(sysmem_allocator, std::move(context), size,
                            buffer_id)) {
    FML_LOG(ERROR) << "VulkanSurface: Could not allocate device memory.";
    return;
  }

  if (!CreateFences()) {
    FML_LOG(ERROR) << "VulkanSurface: Could not create signal fences.";
    return;
  }

  PushSessionImageSetupOps(session);

  std::fill(size_history_.begin(), size_history_.end(), SkISize::MakeEmpty());

  wait_.set_object(release_event_.get());
  wait_.set_trigger(ZX_EVENT_SIGNALED);
  Reset();

  valid_ = true;
}

VulkanSurface::~VulkanSurface() {
  if (image_id_) {
    session_->Enqueue(scenic::NewReleaseResourceCmd(image_id_));
  }
  if (buffer_id_) {
    session_->DeregisterBufferCollection(buffer_id_);
  }
  wait_.Cancel();
  wait_.set_object(ZX_HANDLE_INVALID);
}

bool VulkanSurface::IsValid() const {
  return valid_;
}

SkISize VulkanSurface::GetSize() const {
  if (!valid_) {
    return SkISize::Make(0, 0);
  }

  return SkISize::Make(sk_surface_->width(), sk_surface_->height());
}

vulkan::VulkanHandle<VkSemaphore> VulkanSurface::SemaphoreFromEvent(
    const zx::event& event) const {
  VkResult result;
  VkSemaphore semaphore;

  zx::event semaphore_event;
  zx_status_t status = event.duplicate(ZX_RIGHT_SAME_RIGHTS, &semaphore_event);
  if (status != ZX_OK) {
    FML_LOG(ERROR) << "VulkanSurface: Failed to duplicate semaphore event";
    return vulkan::VulkanHandle<VkSemaphore>();
  }

  VkSemaphoreCreateInfo create_info = {
      .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
      .pNext = nullptr,
      .flags = 0,
  };

  result = VK_CALL_LOG_ERROR(vulkan_provider_.vk().CreateSemaphore(
      vulkan_provider_.vk_device(), &create_info, nullptr, &semaphore));
  if (result != VK_SUCCESS) {
    return vulkan::VulkanHandle<VkSemaphore>();
  }

  VkImportSemaphoreZirconHandleInfoFUCHSIA import_info = {
      .sType =
          VK_STRUCTURE_TYPE_TEMP_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA,
      .pNext = nullptr,
      .semaphore = semaphore,
      .handleType =
          VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA,
      .handle = static_cast<uint32_t>(semaphore_event.release())};

  result = VK_CALL_LOG_ERROR(
      vulkan_provider_.vk().ImportSemaphoreZirconHandleFUCHSIA(
          vulkan_provider_.vk_device(), &import_info));
  if (result != VK_SUCCESS) {
    return vulkan::VulkanHandle<VkSemaphore>();
  }

  return vulkan::VulkanHandle<VkSemaphore>(
      semaphore, [&vulkan_provider = vulkan_provider_](VkSemaphore semaphore) {
        vulkan_provider.vk().DestroySemaphore(vulkan_provider.vk_device(),
                                              semaphore, nullptr);
      });
}

bool VulkanSurface::CreateFences() {
  if (zx::event::create(0, &acquire_event_) != ZX_OK) {
    FML_LOG(ERROR) << "VulkanSurface: Failed to create acquire event";
    return false;
  }

  acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
  if (!acquire_semaphore_) {
    FML_LOG(ERROR) << "VulkanSurface: Failed to create acquire semaphore";
    return false;
  }

  if (zx::event::create(0, &release_event_) != ZX_OK) {
    FML_LOG(ERROR) << "VulkanSurface: Failed to create release event";
    return false;
  }

  command_buffer_fence_ = vulkan_provider_.CreateFence();

  return true;
}

bool VulkanSurface::AllocateDeviceMemory(
    fuchsia::sysmem::AllocatorSyncPtr& sysmem_allocator,
    sk_sp<GrDirectContext> context,
    const SkISize& size,
    uint32_t buffer_id) {
  if (size.isEmpty()) {
    FML_LOG(ERROR)
        << "VulkanSurface: Failed to allocate surface, size is empty";
    return false;
  }

  fuchsia::sysmem::BufferCollectionTokenSyncPtr vulkan_token;
  zx_status_t status =
      sysmem_allocator->AllocateSharedCollection(vulkan_token.NewRequest());
  LOG_AND_RETURN(status != ZX_OK,
                 "VulkanSurface: Failed to allocate collection");
  fuchsia::sysmem::BufferCollectionTokenSyncPtr scenic_token;
  status = vulkan_token->Duplicate(std::numeric_limits<uint32_t>::max(),
                                   scenic_token.NewRequest());
  LOG_AND_RETURN(status != ZX_OK,
                 "VulkanSurface: Failed to duplicate collection token");
  status = vulkan_token->Sync();
  LOG_AND_RETURN(status != ZX_OK,
                 "VulkanSurface: Failed to sync collection token");

  session_->RegisterBufferCollection(buffer_id, std::move(scenic_token));
  buffer_id_ = buffer_id;

  VkBufferCollectionCreateInfoFUCHSIA import_info;
  import_info.collectionToken = vulkan_token.Unbind().TakeChannel().release();
  VkBufferCollectionFUCHSIA collection;
  if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().CreateBufferCollectionFUCHSIA(
          vulkan_provider_.vk_device(), &import_info, nullptr, &collection)) !=
      VK_SUCCESS) {
    return false;
  }

  collection_ = {collection, [&vulkan_provider = vulkan_provider_](
                                 VkBufferCollectionFUCHSIA collection) {
                   vulkan_provider.vk().DestroyBufferCollectionFUCHSIA(
                       vulkan_provider.vk_device(), collection, nullptr);
                 }};

  VulkanImage vulkan_image;
  LOG_AND_RETURN(!CreateVulkanImage(vulkan_provider_, size, &vulkan_image),
                 "VulkanSurface: Failed to create VkImage");

  vulkan_image_ = std::move(vulkan_image);
  const VkMemoryRequirements& memory_requirements =
      vulkan_image_.vk_memory_requirements;
  VkImageCreateInfo& image_create_info = vulkan_image_.vk_image_create_info;

  VkBufferCollectionPropertiesFUCHSIA properties = {
      .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA};
  if (VK_CALL_LOG_ERROR(
          vulkan_provider_.vk().GetBufferCollectionPropertiesFUCHSIA(
              vulkan_provider_.vk_device(), collection_, &properties)) !=
      VK_SUCCESS) {
    return false;
  }

  VkImportMemoryBufferCollectionFUCHSIA import_memory_info = {
      .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA,
      .pNext = nullptr,
      .collection = collection_,
      .index = 0,
  };
  auto bits = memory_requirements.memoryTypeBits & properties.memoryTypeBits;
  FML_DCHECK(bits != 0);
  VkMemoryAllocateInfo allocation_info = {
      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
      .pNext = &import_memory_info,
      .allocationSize = memory_requirements.size,
      .memoryTypeIndex = static_cast<uint32_t>(__builtin_ctz(bits)),
  };

  {
    TRACE_EVENT1("flutter", "vkAllocateMemory", "allocationSize",
                 allocation_info.allocationSize);
    VkDeviceMemory vk_memory = VK_NULL_HANDLE;
    if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().AllocateMemory(
            vulkan_provider_.vk_device(), &allocation_info, NULL,
            &vk_memory)) != VK_SUCCESS) {
      return false;
    }

    vk_memory_ = {vk_memory,
                  [&vulkan_provider = vulkan_provider_](VkDeviceMemory memory) {
                    vulkan_provider.vk().FreeMemory(vulkan_provider.vk_device(),
                                                    memory, NULL);
                  }};

    vk_memory_info_ = allocation_info;
  }

  // Bind image memory.
  if (VK_CALL_LOG_ERROR(vulkan_provider_.vk().BindImageMemory(
          vulkan_provider_.vk_device(), vulkan_image_.vk_image, vk_memory_,
          0)) != VK_SUCCESS) {
    return false;
  }

  return SetupSkiaSurface(std::move(context), size, kSkiaColorType,
                          image_create_info, memory_requirements);
}

bool VulkanSurface::SetupSkiaSurface(sk_sp<GrDirectContext> context,
                                     const SkISize& size,
                                     SkColorType color_type,
                                     const VkImageCreateInfo& image_create_info,
                                     const VkMemoryRequirements& memory_reqs) {
  FML_CHECK(context != nullptr);

  GrVkAlloc alloc;
  alloc.fMemory = vk_memory_;
  alloc.fOffset = 0;
  alloc.fSize = memory_reqs.size;
  alloc.fFlags = 0;

  GrVkImageInfo image_info;
  image_info.fImage = vulkan_image_.vk_image;
  image_info.fAlloc = alloc;
  image_info.fImageTiling = image_create_info.tiling;
  image_info.fImageLayout = image_create_info.initialLayout;
  image_info.fFormat = image_create_info.format;
  image_info.fImageUsageFlags = image_create_info.usage;
  image_info.fSampleCount = 1;
  image_info.fLevelCount = image_create_info.mipLevels;

  GrBackendRenderTarget sk_render_target(size.width(), size.height(), 0,
                                         image_info);

  SkSurfaceProps sk_surface_props(0, kUnknown_SkPixelGeometry);

  auto sk_surface =
      SkSurface::MakeFromBackendRenderTarget(context.get(),             //
                                             sk_render_target,          //
                                             kTopLeft_GrSurfaceOrigin,  //
                                             color_type,                //
                                             SkColorSpace::MakeSRGB(),  //
                                             &sk_surface_props          //
      );

  if (!sk_surface || sk_surface->getCanvas() == nullptr) {
    FML_LOG(ERROR)
        << "VulkanSurface: SkSurface::MakeFromBackendRenderTarget failed";
    return false;
  }
  sk_surface_ = std::move(sk_surface);

  return true;
}

void VulkanSurface::PushSessionImageSetupOps(scenic::Session* session) {
  if (image_id_ == 0)
    image_id_ = session->AllocResourceId();
  session->Enqueue(scenic::NewCreateImage2Cmd(
      image_id_, sk_surface_->width(), sk_surface_->height(), buffer_id_, 0));
}

uint32_t VulkanSurface::GetImageId() {
  return image_id_;
}

sk_sp<SkSurface> VulkanSurface::GetSkiaSurface() const {
  return valid_ ? sk_surface_ : nullptr;
}

size_t VulkanSurface::AdvanceAndGetAge() {
  size_history_[size_history_index_] = GetSize();
  size_history_index_ = (size_history_index_ + 1) % kSizeHistorySize;
  age_++;
  return age_;
}

bool VulkanSurface::FlushSessionAcquireAndReleaseEvents() {
  zx::event acquire, release;

  if (acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &acquire) != ZX_OK ||
      release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &release) != ZX_OK) {
    return false;
  }

  session_->EnqueueAcquireFence(std::move(acquire));
  session_->EnqueueReleaseFence(std::move(release));
  age_ = 0;
  return true;
}

void VulkanSurface::SignalWritesFinished(
    const std::function<void(void)>& on_writes_committed) {
  FML_CHECK(on_writes_committed);

  if (!valid_) {
    on_writes_committed();
    return;
  }

  dart_utils::Check(pending_on_writes_committed_ == nullptr,
                    "Attempted to signal a write on the surface when the "
                    "previous write has not yet been acknowledged by the "
                    "compositor.");

  pending_on_writes_committed_ = on_writes_committed;
}

void VulkanSurface::Reset() {
  if (acquire_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK ||
      release_event_.signal(ZX_EVENT_SIGNALED, 0u) != ZX_OK) {
    valid_ = false;
    FML_LOG(ERROR) << "Could not reset fences. The surface is no longer valid.";
  }

  VkFence fence = command_buffer_fence_;

  if (command_buffer_) {
    VK_CALL_LOG_ERROR(vulkan_provider_.vk().WaitForFences(
        vulkan_provider_.vk_device(), 1, &fence, VK_TRUE, UINT64_MAX));
    command_buffer_.reset();
  }

  VK_CALL_LOG_ERROR(vulkan_provider_.vk().ResetFences(
      vulkan_provider_.vk_device(), 1, &fence));

  // Need to make a new  acquire semaphore every frame or else validation layers
  // get confused about why no one is waiting on it in this VkInstance
  acquire_semaphore_.Reset();
  acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
  if (!acquire_semaphore_) {
    FML_LOG(ERROR) << "failed to create acquire semaphore";
  }

  wait_.Begin(async_get_default_dispatcher());

  // It is safe for the caller to collect the surface in the callback.
  auto callback = pending_on_writes_committed_;
  pending_on_writes_committed_ = nullptr;
  if (callback) {
    callback();
  }
}

void VulkanSurface::OnHandleReady(async_dispatcher_t* dispatcher,
                                  async::WaitBase* wait,
                                  zx_status_t status,
                                  const zx_packet_signal_t* signal) {
  if (status != ZX_OK)
    return;
  FML_DCHECK(signal->observed & ZX_EVENT_SIGNALED);
  Reset();
}

}  // namespace flutter_runner
