// 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 "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h"

#include "impeller/renderer/backend/vulkan/allocator_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/texture_source_vk.h"
#include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h"

namespace impeller {

using AHBProperties = vk::StructureChain<
    // For VK_ANDROID_external_memory_android_hardware_buffer
    vk::AndroidHardwareBufferPropertiesANDROID,
    // For VK_ANDROID_external_memory_android_hardware_buffer
    vk::AndroidHardwareBufferFormatPropertiesANDROID>;

static vk::UniqueImage CreateVKImageWrapperForAndroidHarwareBuffer(
    const vk::Device& device,
    const AHBProperties& ahb_props,
    const AHardwareBuffer_Desc& ahb_desc) {
  const auto& ahb_format =
      ahb_props.get<vk::AndroidHardwareBufferFormatPropertiesANDROID>();

  vk::StructureChain<vk::ImageCreateInfo,
                     // For VK_KHR_external_memory
                     vk::ExternalMemoryImageCreateInfo,
                     // For VK_ANDROID_external_memory_android_hardware_buffer
                     vk::ExternalFormatANDROID>
      image_chain;

  auto& image_info = image_chain.get<vk::ImageCreateInfo>();

  vk::ImageUsageFlags image_usage_flags;
  if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
    image_usage_flags |= vk::ImageUsageFlagBits::eSampled;
  }
  if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
    image_usage_flags |= vk::ImageUsageFlagBits::eColorAttachment;
  }

  vk::ImageCreateFlags image_create_flags;
  if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
    image_create_flags |= vk::ImageCreateFlagBits::eProtected;
  }
  if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
    image_create_flags |= vk::ImageCreateFlagBits::eCubeCompatible;
  }

  image_info.imageType = vk::ImageType::e2D;
  image_info.format = ahb_format.format;
  image_info.extent.width = ahb_desc.width;
  image_info.extent.height = ahb_desc.height;
  image_info.extent.depth = 1;
  image_info.mipLevels =
      (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE)
          ? ISize{ahb_desc.width, ahb_desc.height}.MipCount()
          : 1u;
  image_info.arrayLayers = ahb_desc.layers;
  image_info.samples = vk::SampleCountFlagBits::e1;
  image_info.tiling = vk::ImageTiling::eOptimal;
  image_info.usage = image_usage_flags;
  image_info.flags = image_create_flags;
  image_info.sharingMode = vk::SharingMode::eExclusive;
  image_info.initialLayout = vk::ImageLayout::eUndefined;

  image_chain.get<vk::ExternalMemoryImageCreateInfo>().handleTypes =
      vk::ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID;

  // If the format isn't natively supported by Vulkan (i.e, be a part of the
  // base vkFormat enum), an untyped "external format" must be specified when
  // creating the image and the image views. Usually includes YUV formats.
  if (ahb_format.format == vk::Format::eUndefined) {
    image_chain.get<vk::ExternalFormatANDROID>().externalFormat =
        ahb_format.externalFormat;
  } else {
    image_chain.unlink<vk::ExternalFormatANDROID>();
  }

  auto image = device.createImageUnique(image_chain.get());
  if (image.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create image for external buffer: "
                   << vk::to_string(image.result);
    return {};
  }

  return std::move(image.value);
}

static vk::UniqueDeviceMemory ImportVKDeviceMemoryFromAndroidHarwareBuffer(
    const vk::Device& device,
    const vk::PhysicalDevice& physical_device,
    const vk::Image& image,
    struct AHardwareBuffer* hardware_buffer,
    const AHBProperties& ahb_props) {
  vk::PhysicalDeviceMemoryProperties memory_properties;
  physical_device.getMemoryProperties(&memory_properties);
  int memory_type_index = AllocatorVK::FindMemoryTypeIndex(
      ahb_props.get().memoryTypeBits, memory_properties);
  if (memory_type_index < 0) {
    VALIDATION_LOG << "Could not find memory type of external image.";
    return {};
  }

  vk::StructureChain<vk::MemoryAllocateInfo,
                     // Core in 1.1
                     vk::MemoryDedicatedAllocateInfo,
                     // For VK_ANDROID_external_memory_android_hardware_buffer
                     vk::ImportAndroidHardwareBufferInfoANDROID>
      memory_chain;

  auto& mem_alloc_info = memory_chain.get<vk::MemoryAllocateInfo>();
  mem_alloc_info.allocationSize = ahb_props.get().allocationSize;
  mem_alloc_info.memoryTypeIndex = memory_type_index;

  auto& dedicated_alloc_info =
      memory_chain.get<vk::MemoryDedicatedAllocateInfo>();
  dedicated_alloc_info.image = image;

  auto& ahb_import_info =
      memory_chain.get<vk::ImportAndroidHardwareBufferInfoANDROID>();
  ahb_import_info.buffer = hardware_buffer;

  auto device_memory = device.allocateMemoryUnique(memory_chain.get());
  if (device_memory.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not allocate device memory for external image : "
                   << vk::to_string(device_memory.result);
    return {};
  }

  return std::move(device_memory.value);
}

static std::shared_ptr<YUVConversionVK> CreateYUVConversion(
    const ContextVK& context,
    const AHBProperties& ahb_props) {
  YUVConversionDescriptorVK conversion_chain;

  const auto& ahb_format =
      ahb_props.get<vk::AndroidHardwareBufferFormatPropertiesANDROID>();

  auto& conversion_info = conversion_chain.get();

  conversion_info.format = ahb_format.format;
  conversion_info.ycbcrModel = ahb_format.suggestedYcbcrModel;
  conversion_info.ycbcrRange = ahb_format.suggestedYcbcrRange;
  conversion_info.components = ahb_format.samplerYcbcrConversionComponents;
  conversion_info.xChromaOffset = ahb_format.suggestedXChromaOffset;
  conversion_info.yChromaOffset = ahb_format.suggestedYChromaOffset;
  // If the potential format features of the sampler Y′CBCR conversion do not
  // support VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT,
  // chromaFilter must not be VK_FILTER_LINEAR.
  //
  // Since we are not checking, let's just default to a safe value.
  conversion_info.chromaFilter = vk::Filter::eNearest;
  conversion_info.forceExplicitReconstruction = false;

  if (conversion_info.format == vk::Format::eUndefined) {
    auto& external_format = conversion_chain.get<vk::ExternalFormatANDROID>();
    external_format.externalFormat = ahb_format.externalFormat;
  } else {
    conversion_chain.unlink<vk::ExternalFormatANDROID>();
  }

  return context.GetYUVConversionLibrary()->GetConversion(conversion_chain);
}

static vk::UniqueImageView CreateVKImageView(
    const vk::Device& device,
    const vk::Image& image,
    const vk::SamplerYcbcrConversion& yuv_conversion,
    const AHBProperties& ahb_props,
    const AHardwareBuffer_Desc& ahb_desc) {
  const auto& ahb_format =
      ahb_props.get<vk::AndroidHardwareBufferFormatPropertiesANDROID>();

  vk::StructureChain<vk::ImageViewCreateInfo,
                     // Core in 1.1
                     vk::SamplerYcbcrConversionInfo>
      view_chain;

  auto& view_info = view_chain.get();

  view_info.image = image;
  view_info.viewType = vk::ImageViewType::e2D;
  view_info.format = ahb_format.format;
  view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
  view_info.subresourceRange.baseMipLevel = 0u;
  view_info.subresourceRange.baseArrayLayer = 0u;
  view_info.subresourceRange.levelCount =
      (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE)
          ? ISize{ahb_desc.width, ahb_desc.height}.MipCount()
          : 1u;
  view_info.subresourceRange.layerCount = ahb_desc.layers;

  // We need a custom YUV conversion only if we don't recognize the format.
  if (view_info.format == vk::Format::eUndefined) {
    view_chain.get<vk::SamplerYcbcrConversionInfo>().conversion =
        yuv_conversion;
  } else {
    view_chain.unlink<vk::SamplerYcbcrConversionInfo>();
  }

  auto image_view = device.createImageViewUnique(view_info);
  if (image_view.result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not create external image view: "
                   << vk::to_string(image_view.result);
    return {};
  }

  return std::move(image_view.value);
}

static PixelFormat ToPixelFormat(AHardwareBuffer_Format format) {
  switch (format) {
    case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
      return PixelFormat::kR8G8B8A8UNormInt;
    case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
      return PixelFormat::kR16G16B16A16Float;
    case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
      return PixelFormat::kD24UnormS8Uint;
    case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
      return PixelFormat::kD32FloatS8UInt;
    case AHARDWAREBUFFER_FORMAT_S8_UINT:
      return PixelFormat::kS8UInt;
    case AHARDWAREBUFFER_FORMAT_R8_UNORM:
      return PixelFormat::kR8UNormInt;
    case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
    case AHARDWAREBUFFER_FORMAT_R16G16_UINT:
    case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
    case AHARDWAREBUFFER_FORMAT_R16_UINT:
    case AHARDWAREBUFFER_FORMAT_D24_UNORM:
    case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
    case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
    case AHARDWAREBUFFER_FORMAT_BLOB:
    case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
    case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
    case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
    case AHARDWAREBUFFER_FORMAT_D16_UNORM:
    case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
      // Not understood by the rest of Impeller. Use a placeholder but create
      // the native image and image views using the right external format.
      break;
  }
  return PixelFormat::kR8G8B8A8UNormInt;
}

static TextureType ToTextureType(const AHardwareBuffer_Desc& ahb_desc) {
  if (ahb_desc.layers == 1u) {
    return TextureType::kTexture2D;
  }
  if (ahb_desc.layers % 6u == 0 &&
      (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP)) {
    return TextureType::kTextureCube;
  }
  // Our texture types seem to understand external OES textures. Should these be
  // wired up instead?
  return TextureType::kTexture2D;
}

static TextureDescriptor ToTextureDescriptor(
    const AHardwareBuffer_Desc& ahb_desc) {
  const auto ahb_size = ISize{ahb_desc.width, ahb_desc.height};
  TextureDescriptor desc;
  // We are not going to touch hardware buffers on the CPU or use them as
  // transient attachments. Just treat them as device private.
  desc.storage_mode = StorageMode::kDevicePrivate;
  desc.format =
      ToPixelFormat(static_cast<AHardwareBuffer_Format>(ahb_desc.format));
  desc.size = ahb_size;
  desc.type = ToTextureType(ahb_desc);
  desc.sample_count = SampleCount::kCount1;
  desc.compression_type = CompressionType::kLossless;
  desc.mip_count = (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE)
                       ? ahb_size.MipCount()
                       : 1u;
  return desc;
}

AHBTextureSourceVK::AHBTextureSourceVK(
    const std::shared_ptr<ContextVK>& context,
    struct AHardwareBuffer* ahb,
    const AHardwareBuffer_Desc& ahb_desc)
    : TextureSourceVK(ToTextureDescriptor(ahb_desc)) {
  if (!context) {
    VALIDATION_LOG << "Invalid context.";
    return;
  }

  const auto& device = context->GetDevice();
  const auto& physical_device = context->GetPhysicalDevice();

  AHBProperties ahb_props;

  if (device.getAndroidHardwareBufferPropertiesANDROID(ahb, &ahb_props.get()) !=
      vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not determine properties of the Android hardware "
                      "buffer.";
    return;
  }

  const auto& ahb_format =
      ahb_props.get<vk::AndroidHardwareBufferFormatPropertiesANDROID>();

  // Create an image to refer to our external image.
  auto image =
      CreateVKImageWrapperForAndroidHarwareBuffer(device, ahb_props, ahb_desc);
  if (!image) {
    return;
  }

  // Create a device memory allocation to refer to our external image.
  auto device_memory = ImportVKDeviceMemoryFromAndroidHarwareBuffer(
      device, physical_device, image.get(), ahb, ahb_props);
  if (!device_memory) {
    return;
  }

  // Bind the image to the image memory.
  if (auto result = device.bindImageMemory(image.get(), device_memory.get(), 0);
      result != vk::Result::eSuccess) {
    VALIDATION_LOG << "Could not bind external device memory to image : "
                   << vk::to_string(result);
    return;
  }

  // Figure out how to perform YUV conversions.
  auto yuv_conversion = CreateYUVConversion(*context, ahb_props);
  if (!yuv_conversion || !yuv_conversion->IsValid()) {
    return;
  }

  // Create image view for the newly created image.
  auto image_view = CreateVKImageView(device,                           //
                                      image.get(),                      //
                                      yuv_conversion->GetConversion(),  //
                                      ahb_props,                        //
                                      ahb_desc                          //
  );
  if (!image_view) {
    return;
  }

  needs_yuv_conversion_ = ahb_format.format == vk::Format::eUndefined;
  device_memory_ = std::move(device_memory);
  image_ = std::move(image);
  yuv_conversion_ = std::move(yuv_conversion);
  image_view_ = std::move(image_view);

#ifdef IMPELLER_DEBUG
  context->SetDebugName(device_memory_.get(), "AHB Device Memory");
  context->SetDebugName(image_.get(), "AHB Image");
  context->SetDebugName(yuv_conversion_->GetConversion(), "AHB YUV Conversion");
  context->SetDebugName(image_view_.get(), "AHB ImageView");
#endif  // IMPELLER_DEBUG

  is_valid_ = true;
}

// |TextureSourceVK|
AHBTextureSourceVK::~AHBTextureSourceVK() = default;

bool AHBTextureSourceVK::IsValid() const {
  return is_valid_;
}

// |TextureSourceVK|
vk::Image AHBTextureSourceVK::GetImage() const {
  return image_.get();
}

// |TextureSourceVK|
vk::ImageView AHBTextureSourceVK::GetImageView() const {
  return image_view_.get();
}

// |TextureSourceVK|
vk::ImageView AHBTextureSourceVK::GetRenderTargetView() const {
  return image_view_.get();
}

// |TextureSourceVK|
bool AHBTextureSourceVK::IsSwapchainImage() const {
  return false;
}

// |TextureSourceVK|
std::shared_ptr<YUVConversionVK> AHBTextureSourceVK::GetYUVConversion() const {
  return needs_yuv_conversion_ ? yuv_conversion_ : nullptr;
}

}  // namespace impeller
