// Copyright 2020 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 "dawn/tests/white_box/VulkanImageWrappingTests.h"

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

namespace dawn::native::vulkan {

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

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

      private:
        int mHandle = -1;
    };

    class ExternalTextureDmaBuf : public VulkanImageWrappingTestBackend::ExternalTexture {
      public:
        ExternalTextureDmaBuf(gbm_bo* bo, int fd, uint32_t stride, uint64_t drmModifier)
            : mGbmBo(bo), mFd(fd), stride(stride), drmModifier(drmModifier) {
        }

        ~ExternalTextureDmaBuf() override {
            if (mFd != -1) {
                close(mFd);
            }
            if (mGbmBo != nullptr) {
                gbm_bo_destroy(mGbmBo);
            }
        }

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

      private:
        gbm_bo* mGbmBo = nullptr;
        int mFd = -1;

      public:
        const uint32_t stride;
        const uint64_t drmModifier;
    };

    class VulkanImageWrappingTestBackendDmaBuf : public VulkanImageWrappingTestBackend {
      public:
        VulkanImageWrappingTestBackendDmaBuf(const wgpu::Device& device) {
        }

        ~VulkanImageWrappingTestBackendDmaBuf() {
            if (mGbmDevice != nullptr) {
                gbm_device_destroy(mGbmDevice);
                mGbmDevice = nullptr;
            }
        }

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

            gbm_bo* bo = CreateGbmBo(width, height, true);

            return std::make_unique<ExternalTextureDmaBuf>(
                bo, gbm_bo_get_fd(bo), gbm_bo_get_stride_for_plane(bo, 0), gbm_bo_get_modifier(bo));
        }

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

            ExternalImageDescriptorDmaBuf descriptorDmaBuf;
            *static_cast<ExternalImageDescriptorVk*>(&descriptorDmaBuf) = descriptor;

            descriptorDmaBuf.memoryFD = textureDmaBuf->Dup();
            descriptorDmaBuf.waitFDs = std::move(waitFDs);

            descriptorDmaBuf.stride = textureDmaBuf->stride;
            descriptorDmaBuf.drmModifier = textureDmaBuf->drmModifier;

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

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

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

            return success;
        }

        void CreateGbmDevice() {
            // Render nodes [1] are the primary interface for communicating with the GPU on
            // devices that support DRM. The actual filename of the render node is
            // implementation-specific, so we must scan through all possible filenames to find
            // one that we can use [2].
            //
            // [1] https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#render-nodes
            // [2]
            // https://cs.chromium.org/chromium/src/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.cc
            const uint32_t kRenderNodeStart = 128;
            const uint32_t kRenderNodeEnd = kRenderNodeStart + 16;
            const std::string kRenderNodeTemplate = "/dev/dri/renderD";

            int renderNodeFd = -1;
            for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) {
                std::string renderNode = kRenderNodeTemplate + std::to_string(i);
                renderNodeFd = open(renderNode.c_str(), O_RDWR);
                if (renderNodeFd >= 0)
                    break;
            }
            EXPECT_GE(renderNodeFd, 0) << "Failed to get file descriptor for render node";

            gbm_device* gbmDevice = gbm_create_device(renderNodeFd);
            EXPECT_NE(gbmDevice, nullptr) << "Failed to create GBM device";
            mGbmDevice = gbmDevice;
        }

      private:
        gbm_bo* CreateGbmBo(uint32_t width, uint32_t height, bool linear) {
            uint32_t flags = GBM_BO_USE_RENDERING;
            if (linear)
                flags |= GBM_BO_USE_LINEAR;
            gbm_bo* gbmBo = gbm_bo_create(mGbmDevice, width, height, GBM_FORMAT_XBGR8888, flags);
            EXPECT_NE(gbmBo, nullptr) << "Failed to create GBM buffer object";
            return gbmBo;
        }

        gbm_device* mGbmDevice = nullptr;
    };

    // static
    std::unique_ptr<VulkanImageWrappingTestBackend> VulkanImageWrappingTestBackend::Create(
        const wgpu::Device& device) {
        auto backend = std::make_unique<VulkanImageWrappingTestBackendDmaBuf>(device);
        backend->CreateGbmDevice();
        return backend;
    }
}  // namespace dawn::native::vulkan
