// 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 <fuchsia/sysmem/cpp/fidl.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/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkSurfaceProps.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"
#include "vulkan/vulkan_core.h"
#include "vulkan/vulkan_fuchsia.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;
const VkSysmemColorSpaceFUCHSIA kSrgbColorSpace = {
    .sType = VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA,
    .pNext = nullptr,
    .colorSpace = static_cast<uint32_t>(fuchsia::sysmem::ColorSpaceType::SRGB),
};

}  // 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,
  };

  const VkImageFormatConstraintsInfoFUCHSIA format_constraints = {
      .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA,
      .pNext = nullptr,
      .imageCreateInfo = out_vulkan_image->vk_image_create_info,
      .requiredFormatFeatures = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
      .flags = {},
      .sysmemPixelFormat = {},
      .colorSpaceCount = 1,
      .pColorSpaces = &kSrgbColorSpace,
  };

  const VkImageConstraintsInfoFUCHSIA image_constraints = {
      .sType = VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA,
      .pNext = nullptr,
      .formatConstraintsCount = 1,
      .pFormatConstraints = &format_constraints,
      .bufferCollectionConstraints =
          {
              .sType =
                  VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA,
              .pNext = nullptr,
              .minBufferCount = 1,
              // Using the default value 0 means that we don't have any other
              // constraints except for the minimum buffer count.
              .maxBufferCount = 0,
              .minBufferCountForCamping = 0,
              .minBufferCountForDedicatedSlack = 0,
              .minBufferCountForSharedSlack = 0,
          },
      .flags = {},
  };

  if (VK_CALL_LOG_ERROR(
          vulkan_provider.vk().SetBufferCollectionImageConstraintsFUCHSIA(
              vulkan_provider.vk_device(), collection_, &image_constraints)) !=
      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 = vulkan::VulkanHandle<VkImage_T*>{
        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,
    fuchsia::ui::composition::AllocatorPtr& flatland_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_ || flatland_allocator.is_bound());
  FML_CHECK(context != nullptr);

  if (!AllocateDeviceMemory(sysmem_allocator, flatland_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 (session_) {
    if (image_id_) {
      session_->Enqueue(scenic::NewReleaseResourceCmd(image_id_));
    }
    if (buffer_id_) {
      session_->DeregisterBufferCollection(buffer_id_);
    }
  } else {
    release_image_callback_();
  }
  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_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA,
      .pNext = nullptr,
      .semaphore = semaphore,
      .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA,
      .zirconHandle = 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,
    fuchsia::ui::composition::AllocatorPtr& flatland_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");

  if (session_) {
    session_->RegisterBufferCollection(buffer_id, std::move(scenic_token));
    buffer_id_ = buffer_id;
  } else {
    fuchsia::ui::composition::BufferCollectionExportToken export_token;
    status =
        zx::eventpair::create(0, &export_token.value, &import_token_.value);

    fuchsia::ui::composition::RegisterBufferCollectionArgs args;
    args.set_export_token(std::move(export_token));
    args.set_buffer_collection_token(std::move(scenic_token));
    args.set_usage(
        fuchsia::ui::composition::RegisterBufferCollectionUsage::DEFAULT);
    flatland_allocator->RegisterBufferCollection(
        std::move(args),
        [](fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result
               result) {
          if (result.is_err()) {
            FML_LOG(ERROR)
                << "RegisterBufferCollection call to Scenic Allocator failed";
          }
        });
  }

  VkBufferCollectionCreateInfoFUCHSIA import_info{
      .sType = VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA,
      .pNext = nullptr,
      .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_ = vulkan::VulkanHandle<VkBufferCollectionFUCHSIA_T*>{
      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_ = vulkan::VulkanHandle<VkDeviceMemory_T*>{
        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 (session) {
    if (image_id_ == 0)
      image_id_ = session->AllocResourceId();
    session->Enqueue(scenic::NewCreateImage2Cmd(
        image_id_, sk_surface_->width(), sk_surface_->height(), buffer_id_, 0));
  }
}

void VulkanSurface::SetImageId(uint32_t image_id) {
  FML_CHECK(image_id_ == 0);
  FML_CHECK(!session_);
  image_id_ = image_id;
}

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

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

fuchsia::ui::composition::BufferCollectionImportToken
VulkanSurface::GetBufferCollectionImportToken() {
  FML_CHECK(!session_);
  fuchsia::ui::composition::BufferCollectionImportToken import_dup;
  import_token_.value.duplicate(ZX_RIGHT_SAME_RIGHTS, &import_dup.value);
  return import_dup;
}

zx::event VulkanSurface::GetAcquireFence() {
  FML_CHECK(!session_);
  zx::event fence;
  acquire_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
  return fence;
}

zx::event VulkanSurface::GetReleaseFence() {
  FML_CHECK(!session_);
  zx::event fence;
  release_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &fence);
  return fence;
}
void VulkanSurface::SetReleaseImageCallback(
    ReleaseImageCallback release_image_callback) {
  FML_CHECK(!session_);
  release_image_callback_ = release_image_callback;
}

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

bool VulkanSurface::FlushSessionAcquireAndReleaseEvents() {
  if (session_) {
    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
