// 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 {

    ExternalImageDescriptorVkForTesting::ExternalImageDescriptorVkForTesting()
        : ExternalImageDescriptorVk(ExternalImageType::OpaqueFD) {
    }
    ExternalImageExportInfoVkForTesting::ExternalImageExportInfoVkForTesting()
        : ExternalImageExportInfoVk(ExternalImageType::OpaqueFD) {
    }

    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
