// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <fcntl.h>
#include <gbm.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "VideoViewsTests.h"
#include "dawn/common/Assert.h"
#include "dawn/native/VulkanBackend.h"

namespace dawn {
namespace {

// "linux-chromeos-rel"'s gbm.h is too old to compile, missing this change at least:
// https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/1963001/10/gbm.h#244
#ifndef MINIGBM
#define GBM_BO_USE_TEXTURING (1 << 5)
#define GBM_BO_USE_SW_WRITE_RARELY (1 << 12)
#define GBM_BO_USE_HW_VIDEO_DECODER (1 << 13)
#endif

#ifndef DRM_FORMAT_MOD_LINEAR
#define DRM_FORMAT_MOD_LINEAR 0
#endif

class PlatformTextureGbm : public VideoViewsTestBackend::PlatformTexture {
  public:
    PlatformTextureGbm(wgpu::Texture&& texture, gbm_bo* gbmBo)
        : PlatformTexture(std::move(texture)), mGbmBo(gbmBo) {}
    ~PlatformTextureGbm() override = default;

    // TODO(chromium:1258986): Add DISJOINT vkImage support for multi-plannar formats.
    bool CanWrapAsWGPUTexture() override {
        DAWN_ASSERT(mGbmBo != nullptr);
        // Checks if all plane handles of a multi-planar gbm_bo are same.
        gbm_bo_handle plane0Handle = gbm_bo_get_handle_for_plane(mGbmBo, 0);
        for (int plane = 1; plane < gbm_bo_get_plane_count(mGbmBo); ++plane) {
            if (gbm_bo_get_handle_for_plane(mGbmBo, plane).u32 != plane0Handle.u32) {
                return false;
            }
        }
        return true;
    }

    gbm_bo* GetGbmBo() { return mGbmBo; }

  private:
    gbm_bo* mGbmBo = nullptr;
};

class VideoViewsTestBackendGbm : public VideoViewsTestBackend {
  public:
    void OnSetUp(WGPUDevice device) override {
        mWGPUDevice = device;
        mGbmDevice = CreateGbmDevice();
    }

    void OnTearDown() override { gbm_device_destroy(mGbmDevice); }

  private:
    gbm_device* 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;
            }
        }
        DAWN_ASSERT(renderNodeFd > 0);

        gbm_device* gbmDevice = gbm_create_device(renderNodeFd);
        DAWN_ASSERT(gbmDevice != nullptr);
        return gbmDevice;
    }

    static uint32_t GetGbmBoFormat(wgpu::TextureFormat format) {
        switch (format) {
            case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
                return GBM_FORMAT_NV12;
            default:
                DAWN_UNREACHABLE();
        }
    }

    WGPUTextureFormat ToWGPUTextureFormat(wgpu::TextureFormat format) {
        switch (format) {
            case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
                return WGPUTextureFormat_R8BG8Biplanar420Unorm;
            default:
                DAWN_UNREACHABLE();
        }
    }

    WGPUTextureUsage ToWGPUTextureUsage(wgpu::TextureUsage usage) {
        switch (usage) {
            case wgpu::TextureUsage::TextureBinding:
                return WGPUTextureUsage_TextureBinding;
            default:
                DAWN_UNREACHABLE();
        }
    }

    std::unique_ptr<VideoViewsTestBackend::PlatformTexture> CreateVideoTextureForTest(
        wgpu::TextureFormat format,
        wgpu::TextureUsage usage,
        bool isCheckerboard,
        bool initialized) override {
        // The flags Chromium is using for the VAAPI decoder.
        uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING | GBM_BO_USE_HW_VIDEO_DECODER;
        if (initialized) {
            // The flag specifically used for tests, which need to initialize the GBM buffer with
            // the expected raw video data via CPU, and then sample and draw the buffer via GPU.
            // With the flag added, the buffer's drm modifier will be DRM_FORMAT_MOD_LINEAR instead
            // of I915_FORMAT_MOD_Y_TILED.
            flags |= GBM_BO_USE_SW_WRITE_RARELY;
        }
        gbm_bo* gbmBo = gbm_bo_create(mGbmDevice, VideoViewsTestsBase::kYUVAImageDataWidthInTexels,
                                      VideoViewsTestsBase::kYUVAImageDataHeightInTexels,
                                      GetGbmBoFormat(format), flags);
        if (gbmBo == nullptr) {
            return nullptr;
        }

        if (initialized) {
            void* mapHandle = nullptr;
            uint32_t strideBytes = 0;
            void* addr = gbm_bo_map(gbmBo, 0, 0, VideoViewsTestsBase::kYUVAImageDataWidthInTexels,
                                    VideoViewsTestsBase::kYUVAImageDataHeightInTexels,
                                    GBM_BO_TRANSFER_WRITE, &strideBytes, &mapHandle);
            EXPECT_NE(addr, nullptr);
            std::vector<uint8_t> initialData = VideoViewsTestsBase::GetTestTextureData<uint8_t>(
                /*isMultiPlane*/ true, isCheckerboard,
                /*hasAlpha*/ false);
            uint8_t* srcBegin = initialData.data();
            uint8_t* srcEnd = srcBegin + initialData.size();
            uint8_t* dstBegin = static_cast<uint8_t*>(addr);
            for (; srcBegin < srcEnd; srcBegin += VideoViewsTestsBase::kYUVAImageDataWidthInTexels,
                                      dstBegin += strideBytes) {
                std::memcpy(dstBegin, srcBegin, VideoViewsTestsBase::kYUVAImageDataWidthInTexels);
            }

            gbm_bo_unmap(gbmBo, mapHandle);
        }

        wgpu::TextureDescriptor textureDesc;
        textureDesc.format = format;
        textureDesc.dimension = wgpu::TextureDimension::e2D;
        textureDesc.usage = usage;
        textureDesc.size = {VideoViewsTestsBase::kYUVAImageDataWidthInTexels,
                            VideoViewsTestsBase::kYUVAImageDataHeightInTexels, 1};

        wgpu::DawnTextureInternalUsageDescriptor internalDesc;
        internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
        textureDesc.nextInChain = &internalDesc;

        native::vulkan::ExternalImageDescriptorDmaBuf descriptor = {};
        descriptor.cTextureDescriptor =
            reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc);
        descriptor.isInitialized = initialized;

        descriptor.memoryFD = gbm_bo_get_fd(gbmBo);
        for (int plane = 0; plane < gbm_bo_get_plane_count(gbmBo); ++plane) {
            descriptor.planeLayouts[plane].stride = gbm_bo_get_stride_for_plane(gbmBo, plane);
            descriptor.planeLayouts[plane].offset = gbm_bo_get_offset(gbmBo, plane);
        }
        descriptor.drmModifier = gbm_bo_get_modifier(gbmBo);
        descriptor.waitFDs = {};

        return std::make_unique<PlatformTextureGbm>(
            native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor), gbmBo);
    }

    void DestroyVideoTextureForTest(
        std::unique_ptr<VideoViewsTestBackend::PlatformTexture>&& platformTexture) override {
        // Exports the signal and ignores it.
        native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
        native::vulkan::ExportVulkanImage(platformTexture->wgpuTexture.Get(),
                                          VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo);
        for (int fd : exportInfo.semaphoreHandles) {
            ASSERT_NE(fd, -1);
            close(fd);
        }
        gbm_bo* gbmBo = static_cast<PlatformTextureGbm*>(platformTexture.get())->GetGbmBo();
        ASSERT_NE(gbmBo, nullptr);
        gbm_bo_destroy(gbmBo);
    }

    WGPUDevice mWGPUDevice = nullptr;
    gbm_device* mGbmDevice = nullptr;
};

}  // anonymous namespace

// static
std::vector<BackendTestConfig> VideoViewsTestBackend::Backends() {
    return {VulkanBackend()};
}

// static
std::vector<Format> VideoViewsTestBackend::Formats() {
    // TODO(dawn:551): Support sharing P010 video surfaces.
    return {wgpu::TextureFormat::R8BG8Biplanar420Unorm};
}

// static
std::unique_ptr<VideoViewsTestBackend> VideoViewsTestBackend::Create() {
    return std::make_unique<VideoViewsTestBackendGbm>();
}

}  // namespace dawn
