/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or 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.GPL2 and 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-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <private/qquickopenglshadereffectnode_p.h>

#include "qquickopenglshadereffect_p.h"
#include <QtQuick/qsgtextureprovider.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtCore/qmutex.h>
#include <QtGui/qopenglfunctions.h>

#ifndef GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif

QT_BEGIN_NAMESPACE

static bool hasAtlasTexture(const QVector<QSGTextureProvider *> &textureProviders)
{
    for (int i = 0; i < textureProviders.size(); ++i) {
        QSGTextureProvider *t = textureProviders.at(i);
        if (t && t->texture() && t->texture()->isAtlasTexture())
            return true;
    }
    return false;
}

class QQuickCustomMaterialShader : public QSGMaterialShader
{
public:
    QQuickCustomMaterialShader(const QQuickOpenGLShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes);
    void deactivate() override;
    void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
    char const *const *attributeNames() const override;

protected:
    friend class QQuickOpenGLShaderEffectNode;

    void compile() override;
    const char *vertexShader() const override;
    const char *fragmentShader() const override;

    const QQuickOpenGLShaderEffectMaterialKey m_key;
    QVector<QByteArray> m_attributes;
    QVector<const char *> m_attributeNames;
    QString m_log;
    bool m_compiled;

    QVector<int> m_uniformLocs[QQuickOpenGLShaderEffectMaterialKey::ShaderTypeCount];
    uint m_initialized : 1;
};

QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickOpenGLShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes)
    : m_key(key)
    , m_attributes(attributes)
    , m_compiled(false)
    , m_initialized(false)
{
    const int attributesCount = m_attributes.count();
    m_attributeNames.reserve(attributesCount + 1);
    for (int i = 0; i < attributesCount; ++i)
        m_attributeNames.append(m_attributes.at(i).constData());
    m_attributeNames.append(0);
}

void QQuickCustomMaterialShader::deactivate()
{
    QSGMaterialShader::deactivate();
    QOpenGLContext::currentContext()->functions()->glDisable(GL_CULL_FACE);
}

void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
    typedef QQuickOpenGLShaderEffectMaterial::UniformData UniformData;

    Q_ASSERT(newEffect != nullptr);

    QQuickOpenGLShaderEffectMaterial *material = static_cast<QQuickOpenGLShaderEffectMaterial *>(newEffect);
    if (!material->m_emittedLogChanged && material->m_node) {
        material->m_emittedLogChanged = true;
        emit material->m_node->logAndStatusChanged(m_log, m_compiled ? QQuickShaderEffect::Compiled
                                                                     : QQuickShaderEffect::Error);
    }

    int textureProviderIndex = 0;
    if (!m_initialized) {
        for (int shaderType = 0; shaderType < QQuickOpenGLShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
            Q_ASSERT(m_uniformLocs[shaderType].isEmpty());
            m_uniformLocs[shaderType].reserve(material->uniforms[shaderType].size());
            for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
                const UniformData &d = material->uniforms[shaderType].at(i);
                QByteArray name = d.name;
                if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
                    program()->setUniformValue(d.name.constData(), textureProviderIndex++);
                    // We don't need to store the sampler uniform locations, since their values
                    // only need to be set once. Look for the "qt_SubRect_" uniforms instead.
                    // These locations are used when binding the textures later.
                    name = "qt_SubRect_" + name;
                }
                m_uniformLocs[shaderType].append(program()->uniformLocation(name.constData()));
            }
        }
        m_initialized = true;
        textureProviderIndex = 0;
    }

    QOpenGLFunctions *functions = state.context()->functions();
    for (int shaderType = 0; shaderType < QQuickOpenGLShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
        for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
            const UniformData &d = material->uniforms[shaderType].at(i);
            int loc = m_uniformLocs[shaderType].at(i);
            if (d.specialType == UniformData::Sampler || d.specialType == UniformData::SamplerExternal) {
                int idx = textureProviderIndex++;
                functions->glActiveTexture(GL_TEXTURE0 + idx);
                if (QSGTextureProvider *provider = material->textureProviders.at(idx)) {
                    if (QSGTexture *texture = provider->texture()) {

#ifndef QT_NO_DEBUG
                        if (!qsg_safeguard_texture(texture))
                            continue;
#endif

                        if (loc >= 0) {
                            QRectF r = texture->normalizedTextureSubRect();
                            program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
                        } else if (texture->isAtlasTexture() && !material->geometryUsesTextureSubRect) {
                            texture = texture->removedFromAtlas();
                        }
                        texture->bind();
                        continue;
                    }
                }
                if (d.specialType == UniformData::Sampler)
                    functions->glBindTexture(GL_TEXTURE_2D, 0);
                else if (d.specialType == UniformData::SamplerExternal)
                    functions->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
            } else if (d.specialType == UniformData::Opacity) {
                program()->setUniformValue(loc, state.opacity());
            } else if (d.specialType == UniformData::Matrix) {
                if (state.isMatrixDirty())
                    program()->setUniformValue(loc, state.combinedMatrix());
            } else if (d.specialType == UniformData::None) {
                switch (int(d.value.userType())) {
                case QMetaType::QColor:
                    program()->setUniformValue(loc, qt_premultiply_color(qvariant_cast<QColor>(d.value)));
                    break;
                case QMetaType::Float:
                    program()->setUniformValue(loc, qvariant_cast<float>(d.value));
                    break;
                case QMetaType::Double:
                    program()->setUniformValue(loc, (float) qvariant_cast<double>(d.value));
                    break;
                case QMetaType::QTransform:
                    program()->setUniformValue(loc, qvariant_cast<QTransform>(d.value));
                    break;
                case QMetaType::Int:
                    program()->setUniformValue(loc, d.value.toInt());
                    break;
                case QMetaType::Bool:
                    program()->setUniformValue(loc, GLint(d.value.toBool()));
                    break;
                case QMetaType::QSize:
                case QMetaType::QSizeF:
                    program()->setUniformValue(loc, d.value.toSizeF());
                    break;
                case QMetaType::QPoint:
                case QMetaType::QPointF:
                    program()->setUniformValue(loc, d.value.toPointF());
                    break;
                case QMetaType::QRect:
                case QMetaType::QRectF:
                    {
                        QRectF r = d.value.toRectF();
                        program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
                    }
                    break;
                case QMetaType::QVector2D:
                    program()->setUniformValue(loc, qvariant_cast<QVector2D>(d.value));
                    break;
                case QMetaType::QVector3D:
                    program()->setUniformValue(loc, qvariant_cast<QVector3D>(d.value));
                    break;
                case QMetaType::QVector4D:
                    program()->setUniformValue(loc, qvariant_cast<QVector4D>(d.value));
                    break;
                case QMetaType::QQuaternion:
                    {
                        QQuaternion q = qvariant_cast<QQuaternion>(d.value);
                        program()->setUniformValue(loc, q.x(), q.y(), q.z(), q.scalar());
                    }
                    break;
                case QMetaType::QMatrix4x4:
                    program()->setUniformValue(loc, qvariant_cast<QMatrix4x4>(d.value));
                    break;
                default:
                    break;
                }
            }
        }
    }
    functions->glActiveTexture(GL_TEXTURE0);

    const QQuickOpenGLShaderEffectMaterial *oldMaterial = static_cast<const QQuickOpenGLShaderEffectMaterial *>(oldEffect);
    if (oldEffect == nullptr || material->cullMode != oldMaterial->cullMode) {
        switch (material->cullMode) {
        case QQuickShaderEffect::FrontFaceCulling:
            functions->glEnable(GL_CULL_FACE);
            functions->glCullFace(GL_FRONT);
            break;
        case QQuickShaderEffect::BackFaceCulling:
            functions->glEnable(GL_CULL_FACE);
            functions->glCullFace(GL_BACK);
            break;
        default:
            functions->glDisable(GL_CULL_FACE);
            break;
        }
    }
}

char const *const *QQuickCustomMaterialShader::attributeNames() const
{
    return m_attributeNames.constData();
}

void QQuickCustomMaterialShader::compile()
{
    Q_ASSERT_X(!program()->isLinked(), "QQuickCustomMaterialShader::compile()", "Compile called multiple times!");

    m_log.clear();
    m_compiled = true;
    if (!program()->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader())) {
        m_log += QLatin1String("*** Vertex shader ***\n") + program()->log();
        m_compiled = false;
    }
    if (!program()->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader())) {
        m_log += QLatin1String("*** Fragment shader ***\n") + program()->log();
        m_compiled = false;
    }

    char const *const *attr = attributeNames();
#ifndef QT_NO_DEBUG
    int maxVertexAttribs = 0;
    QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    int attrCount = 0;
    while (attrCount < maxVertexAttribs && attr[attrCount])
        ++attrCount;
    if (attr[attrCount]) {
        qWarning("List of attribute names is too long.\n"
                 "Maximum number of attributes on this hardware is %i.\n"
                 "Vertex shader:\n%s\n"
                 "Fragment shader:\n%s\n",
                 maxVertexAttribs, vertexShader(), fragmentShader());
    }
#endif

    if (m_compiled) {
#ifndef QT_NO_DEBUG
        for (int i = 0; i < attrCount; ++i) {
#else
        for (int i = 0; attr[i]; ++i) {
#endif
            if (*attr[i])
                program()->bindAttributeLocation(attr[i], i);
        }
        m_compiled = program()->link();
        m_log += program()->log();
    }

    if (!m_compiled) {
        qWarning("QQuickCustomMaterialShader: Shader compilation failed:");
        qWarning() << program()->log();

        QSGShaderSourceBuilder::initializeProgramFromFiles(
            program(),
            QStringLiteral(":/qt-project.org/items/shaders/shadereffectfallback.vert"),
            QStringLiteral(":/qt-project.org/items/shaders/shadereffectfallback.frag"));

#ifndef QT_NO_DEBUG
        for (int i = 0; i < attrCount; ++i) {
#else
        for (int i = 0; attr[i]; ++i) {
#endif
            if (qstrcmp(attr[i], qtPositionAttributeName()) == 0)
                program()->bindAttributeLocation("v", i);
        }
        program()->link();
    }
}

const char *QQuickCustomMaterialShader::vertexShader() const
{
    return m_key.sourceCode[QQuickOpenGLShaderEffectMaterialKey::VertexShader].constData();
}

const char *QQuickCustomMaterialShader::fragmentShader() const
{
    return m_key.sourceCode[QQuickOpenGLShaderEffectMaterialKey::FragmentShader].constData();
}


bool QQuickOpenGLShaderEffectMaterialKey::operator == (const QQuickOpenGLShaderEffectMaterialKey &other) const
{
    for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) {
        if (sourceCode[shaderType] != other.sourceCode[shaderType])
            return false;
    }
    return true;
}

bool QQuickOpenGLShaderEffectMaterialKey::operator != (const QQuickOpenGLShaderEffectMaterialKey &other) const
{
    return !(*this == other);
}

uint qHash(const QQuickOpenGLShaderEffectMaterialKey &key)
{
    uint hash = 1;
    typedef QQuickOpenGLShaderEffectMaterialKey Key;
    for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
        hash = hash * 31337 + qHash(key.sourceCode[shaderType]);
    return hash;
}

class QQuickOpenGLShaderEffectMaterialCache : public QObject
{
    Q_OBJECT
public:
    static QQuickOpenGLShaderEffectMaterialCache *get(bool create = true) {
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
        QQuickOpenGLShaderEffectMaterialCache *me = ctx->findChild<QQuickOpenGLShaderEffectMaterialCache *>(QStringLiteral("__qt_ShaderEffectCache"), Qt::FindDirectChildrenOnly);
        if (!me && create) {
            me = new QQuickOpenGLShaderEffectMaterialCache();
            me->setObjectName(QStringLiteral("__qt_ShaderEffectCache"));
            me->setParent(ctx);
        }
        return me;
    }
    QHash<QQuickOpenGLShaderEffectMaterialKey, QSGMaterialType *> cache;
};

QQuickOpenGLShaderEffectMaterial::QQuickOpenGLShaderEffectMaterial(QQuickOpenGLShaderEffectNode *node)
    : cullMode(QQuickShaderEffect::NoCulling)
    , geometryUsesTextureSubRect(false)
    , m_node(node)
    , m_emittedLogChanged(false)
{
    setFlag(Blending | RequiresFullMatrix, true);
}

QSGMaterialType *QQuickOpenGLShaderEffectMaterial::type() const
{
    return m_type;
}

QSGMaterialShader *QQuickOpenGLShaderEffectMaterial::createShader() const
{
    return new QQuickCustomMaterialShader(m_source, attributes);
}

bool QQuickOpenGLShaderEffectMaterial::UniformData::operator == (const UniformData &other) const
{
    if (specialType != other.specialType)
        return false;
    if (name != other.name)
        return false;

    if (specialType == UniformData::Sampler || specialType == UniformData::SamplerExternal) {
        // We can't check the source objects as these live in the GUI thread,
        // so return true here and rely on the textureProvider check for
        // equality of these..
        return true;
    } else {
        return value == other.value;
    }
}

int QQuickOpenGLShaderEffectMaterial::compare(const QSGMaterial *o) const
{
    const QQuickOpenGLShaderEffectMaterial *other = static_cast<const QQuickOpenGLShaderEffectMaterial *>(o);
    if ((hasAtlasTexture(textureProviders) && !geometryUsesTextureSubRect) || (hasAtlasTexture(other->textureProviders) && !other->geometryUsesTextureSubRect))
        return 1;
    if (cullMode != other->cullMode)
        return 1;
    for (int shaderType = 0; shaderType < QQuickOpenGLShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
        if (uniforms[shaderType] != other->uniforms[shaderType])
            return 1;
    }

    // Check the texture providers..
    if (textureProviders.size() != other->textureProviders.size())
        return 1;
    for (int i=0; i<textureProviders.size(); ++i) {
        QSGTextureProvider *tp1 = textureProviders.at(i);
        QSGTextureProvider *tp2 = other->textureProviders.at(i);
        if (!tp1 || !tp2)
            return tp1 == tp2 ? 0 : 1;
        QSGTexture *t1 = tp1->texture();
        QSGTexture *t2 = tp2->texture();
        if (!t1 || !t2)
            return t1 == t2 ? 0 : 1;
        // Check texture id's as textures may be in the same atlas.
        if (t1->textureId() != t2->textureId())
            return 1;
    }
    return 0;
}

void QQuickOpenGLShaderEffectMaterial::setProgramSource(const QQuickOpenGLShaderEffectMaterialKey &source)
{
    m_source = source;
    m_emittedLogChanged = false;

    QQuickOpenGLShaderEffectMaterialCache *cache = QQuickOpenGLShaderEffectMaterialCache::get();
    m_type = cache->cache.value(m_source);
    if (!m_type) {
        m_type = new QSGMaterialType();
        cache->cache.insert(source, m_type);
    }
}

void QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache()
{
    QQuickOpenGLShaderEffectMaterialCache *cache = QQuickOpenGLShaderEffectMaterialCache::get(false);
    if (cache) {
        qDeleteAll(cache->cache);
        delete cache;
    }
}

void QQuickOpenGLShaderEffectMaterial::updateTextures() const
{
    for (int i = 0; i < textureProviders.size(); ++i) {
        if (QSGTextureProvider *provider = textureProviders.at(i)) {
            if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
                texture->updateTexture();
        }
    }
}

void QQuickOpenGLShaderEffectMaterial::invalidateTextureProvider(const QObject *provider)
{
    for (int i = 0; i < textureProviders.size(); ++i) {
        if (provider == textureProviders.at(i))
            textureProviders[i] = nullptr;
    }
}


QQuickOpenGLShaderEffectNode::QQuickOpenGLShaderEffectNode()
{
    QSGNode::setFlag(UsePreprocess, true);

#ifdef QSG_RUNTIME_DESCRIPTION
    qsgnode_set_description(this, QLatin1String("shadereffect"));
#endif
}

QQuickOpenGLShaderEffectNode::~QQuickOpenGLShaderEffectNode()
{
}

void QQuickOpenGLShaderEffectNode::markDirtyTexture()
{
    markDirty(DirtyMaterial);
    Q_EMIT dirtyTexture();
}

void QQuickOpenGLShaderEffectNode::textureProviderDestroyed(QObject *object)
{
    Q_ASSERT(material());
    static_cast<QQuickOpenGLShaderEffectMaterial *>(material())->invalidateTextureProvider(object);
}

void QQuickOpenGLShaderEffectNode::preprocess()
{
    Q_ASSERT(material());
    static_cast<QQuickOpenGLShaderEffectMaterial *>(material())->updateTextures();
}

#include "qquickopenglshadereffectnode.moc"
#include "moc_qquickopenglshadereffectnode_p.cpp"

QT_END_NAMESPACE
