/*
 * Copyright (C) 2022 Metrological Group B.V.
 * Copyright (C) 2022 Igalia S.L.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
#include "TextureMapperPlatformLayerProxyDMABuf.h"

#if USE(COORDINATED_GRAPHICS) && USE(TEXTURE_MAPPER_DMABUF)

#include "PlatformDisplay.h"
#include "TextureMapperGL.h"
#include "TextureMapperGLHeaders.h"
#include "TextureMapperLayer.h"
#include <fcntl.h>
#include <initializer_list>
#include <unistd.h>

#if USE(LIBEPOXY)
#include "EpoxyEGL.h"
#else
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

// This has to be included after the EGL headers.
#include "DMABufEGLUtilities.h"

namespace WebCore {

static PFNEGLCREATEIMAGEKHRPROC createImageKHR()
{
    static PFNEGLCREATEIMAGEKHRPROC s_createImageKHR;
    static std::once_flag s_flag;
    std::call_once(s_flag,
        [&] {
            s_createImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
        });
    return s_createImageKHR;
}

static PFNEGLDESTROYIMAGEKHRPROC destroyImageKHR()
{
    static PFNEGLDESTROYIMAGEKHRPROC s_destroyImageKHR;
    static std::once_flag s_flag;
    std::call_once(s_flag,
        [&] {
            s_destroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
        });
    return s_destroyImageKHR;
}

struct TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::EGLImageData {
    WTF_MAKE_STRUCT_FAST_ALLOCATED;

    ~EGLImageData()
    {
        if (numImages) {
            glDeleteTextures(numImages, texture.data());

            for (unsigned i = 0; i < numImages; ++i) {
                if (image[i] != EGL_NO_IMAGE_KHR)
                    destroyImageKHR()(PlatformDisplay::sharedDisplayForCompositing().eglDisplay(), image[i]);
            }
        }
    }

    uint32_t width { 0 };
    uint32_t height { 0 };
    unsigned numImages { 0 };
    std::array<GLuint, DMABufFormat::c_maxPlanes> texture { 0, 0, 0, 0 };
    std::array<EGLImageKHR, DMABufFormat::c_maxPlanes> image { EGL_NO_IMAGE_KHR, EGL_NO_IMAGE_KHR, EGL_NO_IMAGE_KHR, EGL_NO_IMAGE_KHR };
};

TextureMapperPlatformLayerProxyDMABuf::TextureMapperPlatformLayerProxyDMABuf() = default;
TextureMapperPlatformLayerProxyDMABuf::~TextureMapperPlatformLayerProxyDMABuf() = default;

void TextureMapperPlatformLayerProxyDMABuf::activateOnCompositingThread(Compositor* compositor, TextureMapperLayer* targetLayer)
{
#if ASSERT_ENABLED
    if (!m_compositorThread)
        m_compositorThread = &Thread::current();
#endif
    ASSERT(m_compositorThread == &Thread::current());
    ASSERT(compositor);
    ASSERT(targetLayer);

    {
        Locker locker { m_lock };
        m_compositor = compositor;
        m_targetLayer = targetLayer;
    }
}

void TextureMapperPlatformLayerProxyDMABuf::invalidate()
{
    ASSERT(m_compositorThread == &Thread::current());
#if ASSERT_ENABLED
    m_compositorThread = nullptr;
#endif

    Locker locker { m_lock };

    m_pendingLayer = nullptr;
    m_committedLayer = nullptr;
    m_layers = { };

    m_compositor = nullptr;
    m_targetLayer = nullptr;
}

void TextureMapperPlatformLayerProxyDMABuf::swapBuffer()
{
    Locker locker { m_lock };
    if (!m_targetLayer || !m_pendingLayer)
        return;

    auto previousLayer = WTFMove(m_committedLayer);
    m_committedLayer = WTFMove(m_pendingLayer);
    m_targetLayer->setContentsLayer(m_committedLayer.get());

    // The previous and just-committed layers shouldn't be the same. But if they are, don't perform a release.
    ASSERT(!previousLayer || previousLayer != m_committedLayer);
    if (previousLayer && previousLayer != m_committedLayer)
        previousLayer->release();

    if (!m_committedLayer->m_imageData)
        m_committedLayer->m_imageData = DMABufLayer::createEGLImageData(m_committedLayer->m_object);
    m_committedLayer->m_age = 0;

    // Remove any stale layers, e.g. if a layer has gone unused for >c_maximumAge swaps or doesn't match the latest size.
    auto& committedObject = m_committedLayer->m_object;
    auto isStaleLayer =
        [&](auto& it)
        {
            auto& layer = it.value.get();
            return layer.m_age > DMABufLayer::c_maximumAge
                || !(layer.m_object.width == committedObject.width && layer.m_object.height == committedObject.height);
        };

    bool hasStaleLayers = false;
    for (auto it = m_layers.begin(); it != m_layers.end(); ++it) {
        ++it->value->m_age;
        hasStaleLayers |= isStaleLayer(*it);
    }

    if (hasStaleLayers)
        m_layers.removeIf(isStaleLayer);
}

void TextureMapperPlatformLayerProxyDMABuf::pushDMABuf(Ref<DMABufLayer>&& dmabufLayer)
{
    ASSERT(m_lock.isHeld());

    // The pending and just-pushed layers shouldn't be the same. But if they are, don't perform a release.
    ASSERT(!m_pendingLayer || m_pendingLayer != dmabufLayer.ptr());
    if (m_pendingLayer && m_pendingLayer != dmabufLayer.ptr())
        m_pendingLayer->release();

    m_pendingLayer = WTFMove(dmabufLayer);
    if (m_compositor)
        m_compositor->onNewBufferAvailable();
}

TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::DMABufLayer(DMABufObject&& object, TextureMapperGL::Flags flags)
    : m_object(WTFMove(object))
    , m_flags(flags)
{ }

TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::~DMABufLayer() = default;

void TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::paintToTextureMapper(TextureMapper& textureMapper, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity)
{
    if (!m_imageData)
        return;

    static constexpr std::array<GLfloat, 16> s_bt601ConversionMatrix {
        1.164383561643836,  0.0,                1.596026785714286, -0.874202217873451,
        1.164383561643836, -0.391762290094914, -0.812967647237771,  0.531667823499146,
        1.164383561643836,  2.017232142857143,  0.0,               -1.085630789302022,
        0.0,                0.0,                0.0,                1.0,
    };

    static constexpr std::array<GLfloat, 16> s_bt709ConversionMatrix {
        1.164383561643836,  0.0,                1.792741071428571, -0.972945075016308,
        1.164383561643836, -0.213248614273730, -0.532909328559444,  0.301482665475862,
        1.164383561643836,  2.112401785714286,  0.0,               -1.133402217873451,
        0.0,                0.0,                0.0,                1.0,
    };

    static constexpr std::array<GLfloat, 16> s_bt2020ConversionMatrix {
        1.164383561643836,  0.0,                1.678674107142857, -0.915687932159165,
        1.164383561643836, -0.187326104219343, -0.650424318505057,  0.347458498519301,
        1.164383561643836,  2.141772321428571,  0.0,               -1.148145075016308,
        0.0,                0.0,                0.0,                1.0,
    };

    static constexpr std::array<GLfloat, 16> s_smpte240MConversionMatrix {
        1.164383561643836,  0.0,                1.793651785714286, -0.973402217873451,
        1.164383561643836, -0.256532845251675, -0.542724809537390,  0.328136638536074,
        1.164383561643836,  2.07984375,         0.0,               -1.117059360730593,
        0.0,                0.0,                0.0,                1.0,
    };

    // Based on the specified colorspace, a YUV-to-RGB matrix is chosen. The default is the BT.601 matrix.
    // Invalid or SRGB colorspace defaults to that as well, but in case of RGBA-like formats, the matrix
    // of course goes unused. This is complemented with the below assert that for those formats the specified
    // colorspace is either invalid or SRGB.
    const std::array<GLfloat, 16>& yuvToRGB =
        [&] {
            switch (m_object.colorSpace) {
            case DMABufColorSpace::Invalid:
            case DMABufColorSpace::SRGB:
                break;
            case DMABufColorSpace::BT601:
                return s_bt601ConversionMatrix;
            case DMABufColorSpace::BT709:
                return s_bt709ConversionMatrix;
            case DMABufColorSpace::BT2020:
                return s_bt2020ConversionMatrix;
            case DMABufColorSpace::SMPTE240M:
                return s_smpte240MConversionMatrix;
            }
            return s_bt601ConversionMatrix;
        }();

    TextureMapperGL& texmapGL = static_cast<TextureMapperGL&>(textureMapper);
    auto& data = *m_imageData;

    switch (m_object.format.fourcc) {
    case DMABufFormat::FourCC::XRGB8888:
    case DMABufFormat::FourCC::XBGR8888:
    case DMABufFormat::FourCC::ARGB8888:
    case DMABufFormat::FourCC::ABGR8888:
        // Either no colorspace or the SRGB colorspace was defined for this object. Other options are not meaningful.
        ASSERT(m_object.colorSpace == DMABufColorSpace::Invalid || m_object.colorSpace == DMABufColorSpace::SRGB);
        texmapGL.drawTexture(data.texture[0], m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity);
        break;
    case DMABufFormat::FourCC::I420:
    case DMABufFormat::FourCC::Y444:
    case DMABufFormat::FourCC::Y41B:
    case DMABufFormat::FourCC::Y42B:
        texmapGL.drawTexturePlanarYUV(std::array<GLuint, 3> { data.texture[0], data.texture[1], data.texture[2] },
            yuvToRGB, m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity, std::nullopt);
        break;
    case DMABufFormat::FourCC::YV12:
        texmapGL.drawTexturePlanarYUV(std::array<GLuint, 3> { data.texture[0], data.texture[2], data.texture[1] },
            yuvToRGB, m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity, std::nullopt);
        break;
    case DMABufFormat::FourCC::A420:
        texmapGL.drawTexturePlanarYUV(std::array<GLuint, 3> { data.texture[0], data.texture[1], data.texture[2] },
            yuvToRGB, m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity, data.texture[3]);
        break;
    case DMABufFormat::FourCC::NV12:
    case DMABufFormat::FourCC::NV21:
        texmapGL.drawTextureSemiPlanarYUV(std::array<GLuint, 2> { data.texture[0], data.texture[1] },
            (m_object.format.fourcc == DMABufFormat::FourCC::NV21),
            yuvToRGB, m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity);
        break;
    case DMABufFormat::FourCC::YUY2:
    case DMABufFormat::FourCC::YVYU:
    case DMABufFormat::FourCC::UYVY:
    case DMABufFormat::FourCC::VYUY:
    case DMABufFormat::FourCC::VUYA:
    case DMABufFormat::FourCC::AYUV:
        texmapGL.drawTexturePackedYUV(data.texture[0],
            yuvToRGB, m_flags, IntSize(data.width, data.height), targetRect, modelViewMatrix, opacity);
        break;
    default:
        break;
    }
}

std::unique_ptr<TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::EGLImageData> TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::createEGLImageData(DMABufObject& object)
{
    using EGLImageData = TextureMapperPlatformLayerProxyDMABuf::DMABufLayer::EGLImageData;

    auto& platformDisplay = PlatformDisplay::sharedDisplayForCompositing();
    EGLDisplay eglDisplay = platformDisplay.eglDisplay();

    EGLImageKHR image[DMABufFormat::c_maxPlanes];
    for (unsigned i = 0; i < object.format.numPlanes; ++i) {
        auto attributes = DMABufEGLUtilities::constructEGLCreateImageAttributes(object, i,
            DMABufEGLUtilities::PlaneModifiersUsage { platformDisplay.eglExtensions().EXT_image_dma_buf_import_modifiers });
        image[i] = createImageKHR()(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attributes.data());
    }

    auto imageData = makeUnique<EGLImageData>();
    auto& data = *imageData;
    data.width = object.width;
    data.height = object.height;
    data.numImages = object.format.numPlanes;
    glGenTextures(data.numImages, data.texture.data());
    for (unsigned i = 0; i < data.numImages; ++i) {
        data.image[i] = image[i];

        glBindTexture(GL_TEXTURE_2D, data.texture[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, data.image[i]);
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    return imageData;
}

} // namespace WebCore

#endif // USE(COORDINATED_GRAPHICS) && USE(TEXTURE_MAPPER_DMABUF)
