/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "vulkanserverbufferintegration.h"

#include "vulkanwrapper.h"

#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLTexture>
#include <QtGui/QOffscreenSurface>
#include <QtGui/qopengl.h>

#include <unistd.h>
#include <fcntl.h>

#include <QtCore/QDebug>

QT_BEGIN_NAMESPACE
static constexpr bool extraDebug = false;

#define DECL_GL_FUNCTION(name, type) \
    type name

#define FIND_GL_FUNCTION(name, type) \
    do { \
        name = reinterpret_cast<type>(glContext->getProcAddress(#name)); \
        if (!name) {                                                    \
            qWarning() << "ERROR in GL proc lookup. Could not find " #name; \
            return false;                                               \
        } \
    } while (0)

struct VulkanServerBufferGlFunctions
{
    DECL_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
    DECL_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
    //DECL_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
    DECL_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
    DECL_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);

    bool init(QOpenGLContext *glContext)
    {
        FIND_GL_FUNCTION(glCreateMemoryObjectsEXT, PFNGLCREATEMEMORYOBJECTSEXTPROC);
        FIND_GL_FUNCTION(glImportMemoryFdEXT, PFNGLIMPORTMEMORYFDEXTPROC);
        //FIND_GL_FUNCTION(glTextureStorageMem2DEXT, PFNGLTEXTURESTORAGEMEM2DEXTPROC);
        FIND_GL_FUNCTION(glTexStorageMem2DEXT, PFNGLTEXSTORAGEMEM2DEXTPROC);
        FIND_GL_FUNCTION(glDeleteMemoryObjectsEXT, PFNGLDELETEMEMORYOBJECTSEXTPROC);

        return true;
    }
    static bool create(QOpenGLContext *glContext);
};

static VulkanServerBufferGlFunctions *funcs = nullptr;

//RAII
class CurrentContext
{
public:
    CurrentContext()
    {
        if (!QOpenGLContext::currentContext()) {
            if (QOpenGLContext::globalShareContext()) {
                if (!localContext) {
                    localContext = new QOpenGLContext;
                    localContext->setShareContext(QOpenGLContext::globalShareContext());
                    localContext->create();
                }
                if (!offscreenSurface) {
                    offscreenSurface = new QOffscreenSurface;
                    offscreenSurface->setFormat(localContext->format());
                    offscreenSurface->create();
                }
                localContext->makeCurrent(offscreenSurface);
                localContextInUse = true;
            } else {
                qCritical("VulkanServerBufferIntegration: no globalShareContext");
            }
        }
    }
    ~CurrentContext()
    {
        if (localContextInUse)
            localContext->doneCurrent();
    }
    QOpenGLContext *context() { return localContextInUse ? localContext : QOpenGLContext::currentContext(); }
private:
    static QOpenGLContext *localContext;
    static QOffscreenSurface *offscreenSurface;
    bool localContextInUse = false;
};

QOpenGLContext *CurrentContext::localContext = nullptr;
QOffscreenSurface *CurrentContext::offscreenSurface = nullptr;

bool VulkanServerBufferGlFunctions::create(QOpenGLContext *glContext)
{
    if (funcs)
        return true;
    funcs = new VulkanServerBufferGlFunctions;
    if (!funcs->init(glContext)) {
        delete funcs;
        funcs = nullptr;
        return false;
    }
    return true;
}

VulkanServerBuffer::VulkanServerBuffer(VulkanServerBufferIntegration *integration, const QImage &qimage, QtWayland::ServerBuffer::Format format)
    : QtWayland::ServerBuffer(qimage.size(),format)
    , m_integration(integration)
    , m_width(qimage.width())
    , m_height(qimage.height())
{
    m_format = format;
    switch (m_format) {
        case RGBA32:
            m_glInternalFormat = GL_RGBA8;
            break;
        // case A8:
        //     m_glInternalFormat = GL_R8;
        //     break;
        default:
            qWarning("VulkanServerBuffer: unsupported format");
            m_glInternalFormat = GL_RGBA8;
            break;
    }

    auto vulkanWrapper = m_integration->vulkanWrapper();
    m_vImage = vulkanWrapper->createTextureImage(qimage);
    if (m_vImage)
        m_fd = vulkanWrapper->getImageInfo(m_vImage, &m_memorySize);
}

VulkanServerBuffer::VulkanServerBuffer(VulkanServerBufferIntegration *integration, VulkanImageWrapper *vImage, uint glInternalFormat, const QSize &size)
    : QtWayland::ServerBuffer(size, QtWayland::ServerBuffer::Custom)
    , m_integration(integration)
    , m_width(size.width())
    , m_height(size.height())
    , m_vImage(vImage)
    , m_glInternalFormat(glInternalFormat)
{
    auto vulkanWrapper = m_integration->vulkanWrapper();
    m_fd = vulkanWrapper->getImageInfo(m_vImage, &m_memorySize);
}

VulkanServerBuffer::~VulkanServerBuffer()
{
    delete m_texture; //this is always nullptr for now
    auto vulkanWrapper = m_integration->vulkanWrapper();
    vulkanWrapper->freeTextureImage(m_vImage);
}

struct ::wl_resource *VulkanServerBuffer::resourceForClient(struct ::wl_client *client)
{
    auto *bufferResource = resourceMap().value(client);
    if (!bufferResource) {
        auto integrationResource = m_integration->resourceMap().value(client);
        if (!integrationResource) {
            qWarning("VulkanServerBuffer::resourceForClient: Trying to get resource for ServerBuffer. But client is not bound to the vulkan interface");
            return nullptr;
        }
        struct ::wl_resource *shm_integration_resource = integrationResource->handle;
        Resource *resource = add(client, 1);
        m_integration->send_server_buffer_created(shm_integration_resource, resource->handle, m_fd, m_width, m_height, m_memorySize, m_glInternalFormat);
        return resource->handle;
    }
    return bufferResource->handle;
}

QOpenGLTexture *VulkanServerBuffer::toOpenGlTexture()
{
    if (m_texture && m_texture->isCreated())
        return m_texture;

    CurrentContext current;

    if (!funcs && !VulkanServerBufferGlFunctions::create(current.context()))
        return nullptr;

    funcs->glCreateMemoryObjectsEXT(1, &m_memoryObject);
    if (extraDebug) qDebug() << "glCreateMemoryObjectsEXT" << hex << glGetError();


    int dupfd = fcntl(m_fd, F_DUPFD_CLOEXEC, 0);
    if (dupfd < 0) {
        perror("VulkanServerBuffer::toOpenGlTexture() Could not dup fd:");
        return nullptr;
    }

    funcs->glImportMemoryFdEXT(m_memoryObject, m_memorySize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, dupfd);
    if (extraDebug) qDebug() << "glImportMemoryFdEXT" << hex << glGetError();


    if (!m_texture)
        m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_texture->create();

    GLuint texId = m_texture->textureId();
    if (extraDebug) qDebug() << "created texture" << texId << hex << glGetError();

    m_texture->bind();
    if (extraDebug) qDebug() << "bound texture" << texId << hex << glGetError();
    funcs->glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, m_glInternalFormat, m_size.width(), m_size.height(), m_memoryObject, 0 );
    if (extraDebug) qDebug() << "glTexStorageMem2DEXT" << hex << glGetError();
    if (extraDebug) qDebug() << "format" << hex  << m_glInternalFormat << GL_RGBA8;


    return m_texture;
}

void VulkanServerBuffer::releaseOpenGlTexture()
{
    if (!m_texture || !m_texture->isCreated())
        return;

    CurrentContext current;
    m_texture->destroy();
    funcs->glDeleteMemoryObjectsEXT(1, &m_memoryObject);
}


bool VulkanServerBuffer::bufferInUse()
{
    return (m_texture && m_texture->isCreated()) || resourceMap().count() > 0;
}

void VulkanServerBuffer::server_buffer_release(Resource *resource)
{
    qCDebug(qLcWaylandCompositorHardwareIntegration) << "server_buffer RELEASE resource" << resource->handle << wl_resource_get_id(resource->handle) << "for client" << resource->client();
    wl_resource_destroy(resource->handle);
}

VulkanServerBufferIntegration::VulkanServerBufferIntegration()
{
}

VulkanServerBufferIntegration::~VulkanServerBufferIntegration()
{
}

bool VulkanServerBufferIntegration::initializeHardware(QWaylandCompositor *compositor)
{
    Q_ASSERT(QGuiApplication::platformNativeInterface());

    QtWaylandServer::zqt_vulkan_server_buffer_v1::init(compositor->display(), 1);
    return true;
}

bool VulkanServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const
{
    switch (format) {
        case QtWayland::ServerBuffer::RGBA32:
            return true;
        case QtWayland::ServerBuffer::A8:
            return false;
        default:
            return false;
    }
}

QtWayland::ServerBuffer *VulkanServerBufferIntegration::createServerBufferFromImage(const QImage &qimage, QtWayland::ServerBuffer::Format format)
{
    if (!m_vulkanWrapper) {
        CurrentContext current;
        m_vulkanWrapper = new VulkanWrapper(current.context());
    }
    return new VulkanServerBuffer(this, qimage, format);
}

QtWayland::ServerBuffer *VulkanServerBufferIntegration::createServerBufferFromData(const QByteArray &data, const QSize &size, uint glInternalFormat)
{
    if (!m_vulkanWrapper) {
        CurrentContext current;
        m_vulkanWrapper = new VulkanWrapper(current.context());
    }

    auto *vImage = m_vulkanWrapper->createTextureImageFromData(reinterpret_cast<const uchar*>(data.constData()), data.size(), size, glInternalFormat);

    if (vImage)
        return new VulkanServerBuffer(this, vImage, glInternalFormat, size);

    qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not load compressed texture";
    return nullptr;
}

QT_END_NAMESPACE
