// Copyright 2021 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tests/white_box/VulkanImageWrappingTests.h"

#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/ResourceMemoryAllocatorVk.h"

#include <gtest/gtest.h>
#include <unistd.h>

namespace dawn::native::vulkan {

    class ExternalSemaphoreOpaqueFD : public VulkanImageWrappingTestBackend::ExternalSemaphore {
      public:
        ExternalSemaphoreOpaqueFD(int handle) : mHandle(handle) {
        }
        ~ExternalSemaphoreOpaqueFD() override {
            if (mHandle != -1) {
                close(mHandle);
            }
        }
        int AcquireHandle() {
            int handle = mHandle;
            mHandle = -1;
            return handle;
        }

      private:
        int mHandle = -1;
    };

    class ExternalTextureOpaqueFD : public VulkanImageWrappingTestBackend::ExternalTexture {
      public:
        ExternalTextureOpaqueFD(dawn::native::vulkan::Device* device,
                                int fd,
                                VkDeviceMemory allocation,
                                VkImage handle,
                                VkDeviceSize allocationSize,
                                uint32_t memoryTypeIndex)
            : mDevice(device),
              mFd(fd),
              mAllocation(allocation),
              mHandle(handle),
              allocationSize(allocationSize),
              memoryTypeIndex(memoryTypeIndex) {
        }

        ~ExternalTextureOpaqueFD() override {
            if (mFd != -1) {
                close(mFd);
            }
            if (mAllocation != VK_NULL_HANDLE) {
                mDevice->GetFencedDeleter()->DeleteWhenUnused(mAllocation);
            }
            if (mHandle != VK_NULL_HANDLE) {
                mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
            }
        }

        int Dup() const {
            return dup(mFd);
        }

      private:
        dawn::native::vulkan::Device* mDevice;
        int mFd = -1;
        VkDeviceMemory mAllocation = VK_NULL_HANDLE;
        VkImage mHandle = VK_NULL_HANDLE;

      public:
        const VkDeviceSize allocationSize;
        const uint32_t memoryTypeIndex;
    };

    class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBackend {
      public:
        VulkanImageWrappingTestBackendOpaqueFD(const wgpu::Device& device) : mDevice(device) {
            mDeviceVk = dawn::native::vulkan::ToBackend(dawn::native::FromAPI(device.Get()));
        }

        std::unique_ptr<ExternalTexture> CreateTexture(uint32_t width,
                                                       uint32_t height,
                                                       wgpu::TextureFormat format,
                                                       wgpu::TextureUsage usage) override {
            EXPECT_EQ(format, wgpu::TextureFormat::RGBA8Unorm);
            VkFormat vulkanFormat = VK_FORMAT_R8G8B8A8_UNORM;

            VkImage handle;
            ::VkResult result = CreateImage(mDeviceVk, width, height, vulkanFormat, &handle);
            EXPECT_EQ(result, VK_SUCCESS) << "Failed to create external image";

            VkDeviceMemory allocation;
            VkDeviceSize allocationSize;
            uint32_t memoryTypeIndex;
            ::VkResult resultBool =
                AllocateMemory(mDeviceVk, handle, &allocation, &allocationSize, &memoryTypeIndex);
            EXPECT_EQ(resultBool, VK_SUCCESS) << "Failed to allocate external memory";

            result = BindMemory(mDeviceVk, handle, allocation);
            EXPECT_EQ(result, VK_SUCCESS) << "Failed to bind image memory";

            int fd = GetMemoryFd(mDeviceVk, allocation);

            return std::make_unique<ExternalTextureOpaqueFD>(mDeviceVk, fd, allocation, handle,
                                                             allocationSize, memoryTypeIndex);
        }

        wgpu::Texture WrapImage(
            const wgpu::Device& device,
            const ExternalTexture* texture,
            const ExternalImageDescriptorVkForTesting& descriptor,
            std::vector<std::unique_ptr<ExternalSemaphore>> semaphores) override {
            const ExternalTextureOpaqueFD* textureOpaqueFD =
                static_cast<const ExternalTextureOpaqueFD*>(texture);
            std::vector<int> waitFDs;
            for (auto& semaphore : semaphores) {
                waitFDs.push_back(
                    static_cast<ExternalSemaphoreOpaqueFD*>(semaphore.get())->AcquireHandle());
            }

            ExternalImageDescriptorOpaqueFD descriptorOpaqueFD;
            *static_cast<ExternalImageDescriptorVk*>(&descriptorOpaqueFD) = descriptor;
            descriptorOpaqueFD.memoryFD = textureOpaqueFD->Dup();
            descriptorOpaqueFD.allocationSize = textureOpaqueFD->allocationSize;
            descriptorOpaqueFD.memoryTypeIndex = textureOpaqueFD->memoryTypeIndex;
            descriptorOpaqueFD.waitFDs = std::move(waitFDs);

            return dawn::native::vulkan::WrapVulkanImage(device.Get(), &descriptorOpaqueFD);
        }

        bool ExportImage(const wgpu::Texture& texture,
                         VkImageLayout layout,
                         ExternalImageExportInfoVkForTesting* exportInfo) override {
            ExternalImageExportInfoOpaqueFD infoOpaqueFD;
            bool success = ExportVulkanImage(texture.Get(), layout, &infoOpaqueFD);

            *static_cast<ExternalImageExportInfoVk*>(exportInfo) = infoOpaqueFD;
            for (int fd : infoOpaqueFD.semaphoreHandles) {
                EXPECT_NE(fd, -1);
                exportInfo->semaphores.push_back(std::make_unique<ExternalSemaphoreOpaqueFD>(fd));
            }

            return success;
        }

      private:
        // Creates a VkImage with external memory
        ::VkResult CreateImage(dawn::native::vulkan::Device* deviceVk,
                               uint32_t width,
                               uint32_t height,
                               VkFormat format,
                               VkImage* image) {
            VkExternalMemoryImageCreateInfoKHR externalInfo;
            externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
            externalInfo.pNext = nullptr;
            externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

            auto usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                         VK_IMAGE_USAGE_TRANSFER_DST_BIT;

            VkImageCreateInfo createInfo;
            createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
            createInfo.pNext = &externalInfo;
            createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
            createInfo.imageType = VK_IMAGE_TYPE_2D;
            createInfo.format = format;
            createInfo.extent = {width, height, 1};
            createInfo.mipLevels = 1;
            createInfo.arrayLayers = 1;
            createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
            createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
            createInfo.usage = usage;
            createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
            createInfo.queueFamilyIndexCount = 0;
            createInfo.pQueueFamilyIndices = nullptr;
            createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;

            return deviceVk->fn.CreateImage(deviceVk->GetVkDevice(), &createInfo, nullptr,
                                            &**image);
        }

        // Allocates memory for an image
        ::VkResult AllocateMemory(dawn::native::vulkan::Device* deviceVk,
                                  VkImage handle,
                                  VkDeviceMemory* allocation,
                                  VkDeviceSize* allocationSize,
                                  uint32_t* memoryTypeIndex) {
            // Create the image memory and associate it with the container
            VkMemoryRequirements requirements;
            deviceVk->fn.GetImageMemoryRequirements(deviceVk->GetVkDevice(), handle, &requirements);

            // Import memory from file descriptor
            VkExportMemoryAllocateInfoKHR externalInfo;
            externalInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
            externalInfo.pNext = nullptr;
            externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

            int bestType = deviceVk->GetResourceMemoryAllocator()->FindBestTypeIndex(
                requirements, MemoryKind::Opaque);
            VkMemoryAllocateInfo allocateInfo;
            allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
            allocateInfo.pNext = &externalInfo;
            allocateInfo.allocationSize = requirements.size;
            allocateInfo.memoryTypeIndex = static_cast<uint32_t>(bestType);

            *allocationSize = allocateInfo.allocationSize;
            *memoryTypeIndex = allocateInfo.memoryTypeIndex;

            return deviceVk->fn.AllocateMemory(deviceVk->GetVkDevice(), &allocateInfo, nullptr,
                                               &**allocation);
        }

        // Binds memory to an image
        ::VkResult BindMemory(dawn::native::vulkan::Device* deviceVk,
                              VkImage handle,
                              VkDeviceMemory memory) {
            return deviceVk->fn.BindImageMemory(deviceVk->GetVkDevice(), handle, memory, 0);
        }

        // Extracts a file descriptor representing memory on a device
        int GetMemoryFd(dawn::native::vulkan::Device* deviceVk, VkDeviceMemory memory) {
            VkMemoryGetFdInfoKHR getFdInfo;
            getFdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
            getFdInfo.pNext = nullptr;
            getFdInfo.memory = memory;
            getFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

            int memoryFd = -1;
            deviceVk->fn.GetMemoryFdKHR(deviceVk->GetVkDevice(), &getFdInfo, &memoryFd);

            EXPECT_GE(memoryFd, 0) << "Failed to get file descriptor for external memory";
            return memoryFd;
        }

        // Prepares and exports memory for an image on a given device
        void CreateBindExportImage(dawn::native::vulkan::Device* deviceVk,
                                   uint32_t width,
                                   uint32_t height,
                                   VkFormat format,
                                   VkImage* handle,
                                   VkDeviceMemory* allocation,
                                   VkDeviceSize* allocationSize,
                                   uint32_t* memoryTypeIndex,
                                   int* memoryFd) {
        }

        wgpu::Device mDevice;
        dawn::native::vulkan::Device* mDeviceVk;
    };

    // static
    std::unique_ptr<VulkanImageWrappingTestBackend> VulkanImageWrappingTestBackend::Create(
        const wgpu::Device& device) {
        return std::make_unique<VulkanImageWrappingTestBackendOpaqueFD>(device);
    }

}  // namespace dawn::native::vulkan
