/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D 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 "submissioncontext_p.h"

#include <Qt3DRender/qgraphicsapifilter.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qcullface.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/shader_p.h>
#include <Qt3DRender/private/material_p.h>
#include <Qt3DRender/private/buffer_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/renderstates_p.h>
#include <Qt3DRender/private/renderstateset_p.h>
#include <Qt3DRender/private/rendertarget_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/attachmentpack_p.h>
#include <Qt3DRender/private/qbuffer_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <gltexture_p.h>
#include <rendercommand_p.h>
#include <graphicshelperinterface_p.h>
#include <renderer_p.h>
#include <glresourcemanagers_p.h>
#include <renderbuffer_p.h>
#include <glshader_p.h>
#include <openglvertexarrayobject_p.h>
#include <QOpenGLShaderProgram>

#if !defined(QT_OPENGL_ES_2)
#include <QOpenGLFunctions_2_0>
#include <QOpenGLFunctions_3_2_Core>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLFunctions_4_3_Core>
#include <graphicshelpergl2_p.h>
#include <graphicshelpergl3_2_p.h>
#include <graphicshelpergl3_3_p.h>
#include <graphicshelpergl4_p.h>
#endif
#include <graphicshelperes2_p.h>
#include <graphicshelperes3_p.h>

#include <private/qdebug_p.h>
#include <QSurface>
#include <QWindow>
#include <QOpenGLTexture>
#include <QOpenGLDebugLogger>

QT_BEGIN_NAMESPACE

#ifndef GL_READ_FRAMEBUFFER
#define GL_READ_FRAMEBUFFER 0x8CA8
#endif

#ifndef GL_DRAW_FRAMEBUFFER
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif

namespace Qt3DRender {
namespace Render {
namespace OpenGL {


static QHash<unsigned int, SubmissionContext*> static_contexts;

unsigned int nextFreeContextId()
{
    for (unsigned int i=0; i < 0xffff; ++i) {
        if (!static_contexts.contains(i))
            return i;
    }

    qFatal("Couldn't find free context ID");
    return 0;
}

namespace {

GLBuffer::Type attributeTypeToGLBufferType(QAttribute::AttributeType type)
{
    switch (type) {
    case QAttribute::VertexAttribute:
        return GLBuffer::ArrayBuffer;
    case QAttribute::IndexAttribute:
        return GLBuffer::IndexBuffer;
    case QAttribute::DrawIndirectAttribute:
        return GLBuffer::DrawIndirectBuffer;
    default:
        Q_UNREACHABLE();
    }
}

void copyGLFramebufferDataToImage(QImage &img, const uchar *srcData, uint stride, uint width, uint height, QAbstractTexture::TextureFormat format)
{
    switch (format) {
    case QAbstractTexture::RGBA32F:
        {
            uchar *srcScanline = (uchar *)srcData + stride * (height - 1);
            for (uint i = 0; i < height; ++i) {
                uchar *dstScanline = img.scanLine(i);
                float *pSrc = (float*)srcScanline;
                for (uint j = 0; j < width; j++) {
                    *dstScanline++ = (uchar)(255.0f * qBound(0.0f, pSrc[4*j+2], 1.0f));
                    *dstScanline++ = (uchar)(255.0f * qBound(0.0f, pSrc[4*j+1], 1.0f));
                    *dstScanline++ = (uchar)(255.0f * qBound(0.0f, pSrc[4*j+0], 1.0f));
                    *dstScanline++ = (uchar)(255.0f * qBound(0.0f, pSrc[4*j+3], 1.0f));
                }
                srcScanline -= stride;
            }
        } break;
    default:
        {
            uchar* srcScanline = (uchar *)srcData + stride * (height - 1);
            for (uint i = 0; i < height; ++i) {
                memcpy(img.scanLine(i), srcScanline, stride);
                srcScanline -= stride;
            }
        } break;
    }
}

// Render States Helpers
template<typename GenericState>
void applyStateHelper(const GenericState *state, SubmissionContext *gc)
{
    Q_UNUSED(state);
    Q_UNUSED(gc);
}

template<>
void applyStateHelper<AlphaFunc>(const AlphaFunc *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->alphaTest(std::get<0>(values), std::get<1>(values));
}

template<>
void applyStateHelper<BlendEquationArguments>(const BlendEquationArguments *state, SubmissionContext *gc)
{
    const auto values = state->values();
    // Un-indexed BlendEquationArguments -> Use normal GL1.0 functions
    if (std::get<5>(values) < 0) {
        if (std::get<4>(values)) {
            gc->openGLContext()->functions()->glEnable(GL_BLEND);
            gc->openGLContext()->functions()->glBlendFuncSeparate(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values));
        } else {
            gc->openGLContext()->functions()->glDisable(GL_BLEND);
        }
    }
    // BlendEquationArguments for a particular Draw Buffer. Different behaviours for
    //  (1) 3.0-3.3: only enablei/disablei supported.
    //  (2) 4.0+: all operations supported.
    // We just ignore blend func parameter for (1), so no warnings get
    // printed.
    else {
        if (std::get<4>(values)) {
            gc->enablei(GL_BLEND, std::get<5>(values));
            if (gc->supportsDrawBuffersBlend()) {
                gc->blendFuncSeparatei(std::get<5>(values), std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values));
            }
        } else {
            gc->disablei(GL_BLEND, std::get<5>(values));
        }
    }
}

template<>
void applyStateHelper<BlendEquation>(const BlendEquation *state, SubmissionContext *gc)
{
    gc->blendEquation(std::get<0>(state->values()));
}

template<>
void applyStateHelper<MSAAEnabled>(const MSAAEnabled *state, SubmissionContext *gc)
{
    gc->setMSAAEnabled(std::get<0>(state->values()));
}

template<>
void applyStateHelper<DepthRange>(const DepthRange *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->depthRange(std::get<0>(values), std::get<1>(values));
}

template<>
void applyStateHelper<DepthTest>(const DepthTest *state, SubmissionContext *gc)
{
    gc->depthTest(std::get<0>(state->values()));
}

template<>
void applyStateHelper<RasterMode>(const RasterMode *state, SubmissionContext *gc)
{
    gc->rasterMode(std::get<0>(state->values()), std::get<1>(state->values()));
}

template<>
void applyStateHelper<NoDepthMask>(const NoDepthMask *state, SubmissionContext *gc)
{
    gc->depthMask(std::get<0>(state->values()));
}

template<>
void applyStateHelper<CullFace>(const CullFace *state, SubmissionContext *gc)
{
    const auto values = state->values();
    if (std::get<0>(values) == QCullFace::NoCulling) {
        gc->openGLContext()->functions()->glDisable(GL_CULL_FACE);
    } else {
        gc->openGLContext()->functions()->glEnable(GL_CULL_FACE);
        gc->openGLContext()->functions()->glCullFace(std::get<0>(values));
    }
}

template<>
void applyStateHelper<FrontFace>(const FrontFace *state, SubmissionContext *gc)
{
    gc->frontFace(std::get<0>(state->values()));
}

template<>
void applyStateHelper<ScissorTest>(const ScissorTest *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glEnable(GL_SCISSOR_TEST);
    gc->openGLContext()->functions()->glScissor(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values));
}

template<>
void applyStateHelper<StencilTest>(const StencilTest *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glEnable(GL_STENCIL_TEST);
    gc->openGLContext()->functions()->glStencilFuncSeparate(GL_FRONT, std::get<0>(values), std::get<1>(values), std::get<2>(values));
    gc->openGLContext()->functions()->glStencilFuncSeparate(GL_BACK, std::get<3>(values), std::get<4>(values), std::get<5>(values));
}

template<>
void applyStateHelper<AlphaCoverage>(const AlphaCoverage *, SubmissionContext *gc)
{
    gc->setAlphaCoverageEnabled(true);
}

template<>
void applyStateHelper<PointSize>(const PointSize *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->pointSize(std::get<0>(values), std::get<1>(values));
}


template<>
void applyStateHelper<PolygonOffset>(const PolygonOffset *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glEnable(GL_POLYGON_OFFSET_FILL);
    gc->openGLContext()->functions()->glPolygonOffset(std::get<0>(values), std::get<1>(values));
}

template<>
void applyStateHelper<ColorMask>(const ColorMask *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glColorMask(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values));
}

template<>
void applyStateHelper<ClipPlane>(const ClipPlane *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->enableClipPlane(std::get<0>(values));
    gc->setClipPlane(std::get<0>(values), std::get<1>(values), std::get<2>(values));
}

template<>
void applyStateHelper<SeamlessCubemap>(const SeamlessCubemap *, SubmissionContext *gc)
{
    gc->setSeamlessCubemap(true);
}

template<>
void applyStateHelper<StencilOp>(const StencilOp *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glStencilOpSeparate(GL_FRONT, std::get<0>(values), std::get<1>(values), std::get<2>(values));
    gc->openGLContext()->functions()->glStencilOpSeparate(GL_BACK, std::get<3>(values), std::get<4>(values), std::get<5>(values));
}

template<>
void applyStateHelper<StencilMask>(const StencilMask *state, SubmissionContext *gc)
{
    const auto values = state->values();
    gc->openGLContext()->functions()->glStencilMaskSeparate(GL_FRONT, std::get<0>(values));
    gc->openGLContext()->functions()->glStencilMaskSeparate(GL_BACK, std::get<1>(values));
}

template<>
void applyStateHelper<Dithering>(const Dithering *, SubmissionContext *gc)
{
    gc->openGLContext()->functions()->glEnable(GL_DITHER);
}

#ifndef GL_LINE_SMOOTH
#define GL_LINE_SMOOTH 0x0B20
#endif

template<>
void applyStateHelper<LineWidth>(const LineWidth *state, SubmissionContext *gc)
{
    const auto values = state->values();
    if (std::get<1>(values))
        gc->openGLContext()->functions()->glEnable(GL_LINE_SMOOTH);
    else
        gc->openGLContext()->functions()->glDisable(GL_LINE_SMOOTH);

    gc->openGLContext()->functions()->glLineWidth(std::get<0>(values));
}

GLint glAttachmentPoint(const QRenderTargetOutput::AttachmentPoint &attachmentPoint)
{
    if (attachmentPoint <= QRenderTargetOutput::Color15)
        return GL_COLOR_ATTACHMENT0 + attachmentPoint;

    switch (attachmentPoint) {
    case QRenderTargetOutput::Depth:
    case QRenderTargetOutput::DepthStencil:
        return GL_DEPTH_ATTACHMENT;
    case QRenderTargetOutput::Stencil:
        return GL_STENCIL_ATTACHMENT;
    default:
        Q_UNREACHABLE();
        return GL_NONE;
    }
}

} // anonymous


SubmissionContext::SubmissionContext()
    : GraphicsContext()
    , m_ownCurrent(true)
    , m_id(nextFreeContextId())
    , m_surface(nullptr)
    , m_activeShader(nullptr)
    , m_renderTargetFormat(QAbstractTexture::NoFormat)
    , m_currClearStencilValue(0)
    , m_currClearDepthValue(1.f)
    , m_currClearColorValue(0,0,0,0)
    , m_material(nullptr)
    , m_activeFBO(0)
    , m_boundArrayBuffer(nullptr)
    , m_stateSet(nullptr)
    , m_renderer(nullptr)
    , m_uboTempArray(QByteArray(1024, 0))
{
    static_contexts[m_id] = this;
}

SubmissionContext::~SubmissionContext()
{
    releaseOpenGL();

    Q_ASSERT(static_contexts[m_id] == this);
    static_contexts.remove(m_id);
}

void SubmissionContext::initialize()
{
    GraphicsContext::initialize();
    m_textureContext.initialize(this);
    m_imageContext.initialize(this);
}

void SubmissionContext::resolveRenderTargetFormat()
{
    const QSurfaceFormat format = m_gl->format();
    const uint a = (format.alphaBufferSize() == -1) ? 0 : format.alphaBufferSize();
    const uint r = format.redBufferSize();
    const uint g = format.greenBufferSize();
    const uint b = format.blueBufferSize();

#define RGBA_BITS(r,g,b,a) (r | (g << 6) | (b << 12) | (a << 18))

    const uint bits = RGBA_BITS(r,g,b,a);
    switch (bits) {
    case RGBA_BITS(8,8,8,8):
        m_renderTargetFormat = QAbstractTexture::RGBA8_UNorm;
        break;
    case RGBA_BITS(8,8,8,0):
        m_renderTargetFormat = QAbstractTexture::RGB8_UNorm;
        break;
    case RGBA_BITS(5,6,5,0):
        m_renderTargetFormat = QAbstractTexture::R5G6B5;
        break;
    }
#undef RGBA_BITS
}

bool SubmissionContext::beginDrawing(QSurface *surface)
{
    Q_ASSERT(surface);
    Q_ASSERT(m_gl);

    m_surface = surface;

    // TO DO: Find a way to make to pause work if the window is not exposed
    //    if (m_surface && m_surface->surfaceClass() == QSurface::Window) {
    //        qDebug() << Q_FUNC_INFO << 1;
    //        if (!static_cast<QWindow *>(m_surface)->isExposed())
    //            return false;
    //        qDebug() << Q_FUNC_INFO << 2;
    //    }

    // Makes the surface current on the OpenGLContext
    // and sets the right glHelper
    m_ownCurrent = !(m_gl->surface() == m_surface);
    if (m_ownCurrent && !makeCurrent(m_surface))
        return false;

    // TODO: cache surface format somewhere rather than doing this every time render surface changes
    resolveRenderTargetFormat();

#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG)
    GLint err = m_gl->functions()->glGetError();
    if (err != 0) {
        qCWarning(Backend) << Q_FUNC_INFO << "glGetError:" << err;
    }
#endif

    if (!isInitialized())
        initialize();
    initializeHelpers(m_surface);

    // need to reset these values every frame, may get overwritten elsewhere
    m_gl->functions()->glClearColor(m_currClearColorValue.redF(), m_currClearColorValue.greenF(), m_currClearColorValue.blueF(), m_currClearColorValue.alphaF());
    m_gl->functions()->glClearDepthf(m_currClearDepthValue);
    m_gl->functions()->glClearStencil(m_currClearStencilValue);

    if (m_activeShader) {
        m_activeShader = nullptr;
    }

    m_boundArrayBuffer = nullptr;
    return true;
}

void SubmissionContext::endDrawing(bool swapBuffers)
{
    if (swapBuffers)
        m_gl->swapBuffers(m_surface);
    if (m_ownCurrent)
        m_gl->doneCurrent();
    m_textureContext.endDrawing();
    m_imageContext.endDrawing();
}

void SubmissionContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, GLuint defaultFboId)
{
    GLuint fboId = defaultFboId; // Default FBO
    if (renderTargetNodeId) {
        // New RenderTarget
        if (!m_renderTargets.contains(renderTargetNodeId)) {
            if (m_defaultFBO && fboId == m_defaultFBO) {
                // this is the default fbo that some platforms create (iOS), we never
                // register it
            } else {
                fboId = createRenderTarget(renderTargetNodeId, attachments);
            }
        } else {
            fboId = updateRenderTarget(renderTargetNodeId, attachments, true);
        }
    }
    m_activeFBO = fboId;
    m_activeFBONodeId = renderTargetNodeId;
    m_glHelper->bindFrameBufferObject(m_activeFBO, GraphicsHelperInterface::FBODraw);
    // Set active drawBuffers
    activateDrawBuffers(attachments);
}

void SubmissionContext::releaseRenderTarget(const Qt3DCore::QNodeId id)
{
    if (m_renderTargets.contains(id)) {
        const RenderTargetInfo targetInfo = m_renderTargets.take(id);
        const GLuint fboId = targetInfo.fboId;
        m_glHelper->releaseFrameBufferObject(fboId);
    }
}

GLuint SubmissionContext::createRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments)
{
    const GLuint fboId = m_glHelper->createFrameBufferObject();
    if (fboId) {
        // The FBO is created and its attachments are set once
        // Bind FBO
        m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw);
        // Insert FBO into hash
        const RenderTargetInfo info = bindFrameBufferAttachmentHelper(fboId, attachments);
        m_renderTargets.insert(renderTargetNodeId, info);
    } else {
        qCritical("Failed to create FBO");
    }
    return fboId;
}

GLuint SubmissionContext::updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, bool isActiveRenderTarget)
{
    const RenderTargetInfo fboInfo = m_renderTargets.value(renderTargetNodeId);
    const GLuint fboId =fboInfo.fboId;

    // We need to check if  one of the attachnent have changed QTBUG-64757
    bool needsRebuild = attachments != fboInfo.attachments;

    // Even if the attachment packs are the same, one of the inner texture might have
    // been resized or recreated, we need to check for that
    if (!needsRebuild) {
        // render target exists, has attachment been resized?
        GLTextureManager *glTextureManager = m_renderer->glResourceManagers()->glTextureManager();
        const QSize s = fboInfo.size;

        const auto attachments_ = attachments.attachments();
        for (const Attachment &attachment : attachments_) {
            const bool textureWasUpdated = m_updateTextureIds.contains(attachment.m_textureUuid);
            GLTexture *rTex = glTextureManager->lookupResource(attachment.m_textureUuid);
            if (rTex) {
                const bool sizeHasChanged = rTex->size() != s;
                needsRebuild |= sizeHasChanged;
                if (isActiveRenderTarget && attachment.m_point == QRenderTargetOutput::Color0)
                    m_renderTargetFormat = rTex->properties().format;
            }
            needsRebuild |= textureWasUpdated;
        }
    }

    if (needsRebuild) {
        m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw);
        const RenderTargetInfo updatedInfo = bindFrameBufferAttachmentHelper(fboId, attachments);
        // Update our stored Render Target Info
        m_renderTargets.insert(renderTargetNodeId, updatedInfo);
    }

    return fboId;
}

void SubmissionContext::releaseRenderTargets()
{
    const auto keys = m_renderTargets.keys();
    for (Qt3DCore::QNodeId renderTargetId : keys)
        releaseRenderTarget(renderTargetId);
}

QSize SubmissionContext::renderTargetSize(const QSize &surfaceSize) const
{
    QSize renderTargetSize;
    if (m_activeFBO != m_defaultFBO) {
        // For external FBOs we may not have a m_renderTargets entry.
        if (m_renderTargets.contains(m_activeFBONodeId)) {
            renderTargetSize = m_renderTargets[m_activeFBONodeId].size;
        } else if (surfaceSize.isValid()) {
            renderTargetSize = surfaceSize;
        } else {
            // External FBO (when used with QtQuick2 Scene3D)

            // Query FBO color attachment 0 size
            GLint attachmentObjectType = GL_NONE;
            GLint attachment0Name = 0;
            m_gl->functions()->glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
                                                                     GL_COLOR_ATTACHMENT0,
                                                                     GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                                     &attachmentObjectType);
            m_gl->functions()->glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
                                                                     GL_COLOR_ATTACHMENT0,
                                                                     GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
                                                                     &attachment0Name);

            if (attachmentObjectType == GL_RENDERBUFFER && m_glHelper->supportsFeature(GraphicsHelperInterface::RenderBufferDimensionRetrieval))
                renderTargetSize = m_glHelper->getRenderBufferDimensions(attachment0Name);
            else if (attachmentObjectType == GL_TEXTURE && m_glHelper->supportsFeature(GraphicsHelperInterface::TextureDimensionRetrieval))
                // Assumes texture level 0 and GL_TEXTURE_2D target
                renderTargetSize = m_glHelper->getTextureDimensions(attachment0Name, GL_TEXTURE_2D);
            else
                return renderTargetSize;
        }
    } else {
        renderTargetSize = surfaceSize;
        if (m_surface->surfaceClass() == QSurface::Window) {
            const float dpr = static_cast<QWindow *>(m_surface)->devicePixelRatio();
            renderTargetSize *= dpr;
        }
    }
    return renderTargetSize;
}

QImage SubmissionContext::readFramebuffer(const QRect &rect)
{
    QImage img;
    const unsigned int area = rect.width() * rect.height();
    unsigned int bytes;
    GLenum format, type;
    QImage::Format imageFormat;
    uint stride;

    /* format value should match GL internalFormat */
    GLenum internalFormat = m_renderTargetFormat;

    switch (m_renderTargetFormat) {
    case QAbstractTexture::RGBAFormat:
    case QAbstractTexture::RGBA8_SNorm:
    case QAbstractTexture::RGBA8_UNorm:
    case QAbstractTexture::RGBA8U:
    case QAbstractTexture::SRGB8_Alpha8:
#ifdef QT_OPENGL_ES_2
        format = GL_RGBA;
        imageFormat = QImage::Format_RGBA8888_Premultiplied;
#else
        format = GL_BGRA;
        imageFormat = QImage::Format_ARGB32_Premultiplied;
        internalFormat = GL_RGBA8;
#endif
        type = GL_UNSIGNED_BYTE;
        bytes = area * 4;
        stride = rect.width() * 4;
        break;
    case QAbstractTexture::SRGB8:
    case QAbstractTexture::RGBFormat:
    case QAbstractTexture::RGB8U:
    case QAbstractTexture::RGB8_UNorm:
#ifdef QT_OPENGL_ES_2
        format = GL_RGBA;
        imageFormat = QImage::Format_RGBX8888;
#else
        format = GL_BGRA;
        imageFormat = QImage::Format_RGB32;
        internalFormat = GL_RGB8;
#endif
        type = GL_UNSIGNED_BYTE;
        bytes = area * 4;
        stride = rect.width() * 4;
        break;
#ifndef QT_OPENGL_ES_2
    case QAbstractTexture::RG11B10F:
        bytes = area * 4;
        format = GL_RGB;
        type = GL_UNSIGNED_INT_10F_11F_11F_REV;
        imageFormat = QImage::Format_RGB30;
        stride = rect.width() * 4;
        break;
    case QAbstractTexture::RGB10A2:
        bytes = area * 4;
        format = GL_RGBA;
        type = GL_UNSIGNED_INT_2_10_10_10_REV;
        imageFormat = QImage::Format_A2BGR30_Premultiplied;
        stride = rect.width() * 4;
        break;
    case QAbstractTexture::R5G6B5:
        bytes = area * 2;
        format = GL_RGB;
        type = GL_UNSIGNED_SHORT;
        internalFormat = GL_UNSIGNED_SHORT_5_6_5_REV;
        imageFormat = QImage::Format_RGB16;
        stride = rect.width() * 2;
        break;
    case QAbstractTexture::RGBA16F:
    case QAbstractTexture::RGBA16U:
    case QAbstractTexture::RGBA32F:
    case QAbstractTexture::RGBA32U:
        bytes = area * 16;
        format = GL_RGBA;
        type = GL_FLOAT;
        imageFormat = QImage::Format_ARGB32_Premultiplied;
        stride = rect.width() * 16;
        break;
#endif
    default:
        auto warning = qWarning();
        warning << "Unable to convert";
        QtDebugUtils::formatQEnum(warning, m_renderTargetFormat);
        warning << "render target texture format to QImage.";
        return img;
    }

    GLint samples = 0;
    m_gl->functions()->glGetIntegerv(GL_SAMPLES, &samples);
    if (samples > 0 && !m_glHelper->supportsFeature(GraphicsHelperInterface::BlitFramebuffer)) {
        qCWarning(Backend) << Q_FUNC_INFO << "Unable to capture multisampled framebuffer; "
                                             "Required feature BlitFramebuffer is missing.";
        return img;
    }

    img = QImage(rect.width(), rect.height(), imageFormat);

    QScopedArrayPointer<uchar> data(new uchar [bytes]);

    if (samples > 0) {
        // resolve multisample-framebuffer to renderbuffer and read pixels from it
        GLuint fbo, rb;
        QOpenGLFunctions *gl = m_gl->functions();
        gl->glGenFramebuffers(1, &fbo);
        gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
        gl->glGenRenderbuffers(1, &rb);
        gl->glBindRenderbuffer(GL_RENDERBUFFER, rb);
        gl->glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, rect.width(), rect.height());
        gl->glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);

        const GLenum status = gl->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
        if (status != GL_FRAMEBUFFER_COMPLETE) {
            gl->glDeleteRenderbuffers(1, &rb);
            gl->glDeleteFramebuffers(1, &fbo);
            qCWarning(Backend) << Q_FUNC_INFO << "Copy-framebuffer not complete: " << status;
            return img;
        }

        m_glHelper->blitFramebuffer(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(),
                                    0, 0, rect.width(), rect.height(),
                                    GL_COLOR_BUFFER_BIT, GL_NEAREST);
        gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
        gl->glReadPixels(0,0,rect.width(), rect.height(), format, type, data.data());

        copyGLFramebufferDataToImage(img, data.data(), stride, rect.width(), rect.height(), m_renderTargetFormat);

        gl->glBindRenderbuffer(GL_RENDERBUFFER, rb);
        gl->glDeleteRenderbuffers(1, &rb);
        gl->glBindFramebuffer(GL_FRAMEBUFFER, m_activeFBO);
        gl->glDeleteFramebuffers(1, &fbo);
    } else {
        // read pixels directly from framebuffer
        m_gl->functions()->glReadPixels(rect.x(), rect.y(), rect.width(), rect.height(), format, type, data.data());
        copyGLFramebufferDataToImage(img, data.data(), stride, rect.width(), rect.height(), m_renderTargetFormat);
    }

    return img;
}

void SubmissionContext::setViewport(const QRectF &viewport, const QSize &surfaceSize)
{
    //    // save for later use; this has nothing to do with the viewport but it is
    //    // here that we get to know the surfaceSize from the RenderView.
        m_surfaceSize = surfaceSize;

    m_viewport = viewport;
    QSize size = renderTargetSize(surfaceSize);

    // Check that the returned size is before calling glViewport
    if (size.isEmpty())
        return;

    // Qt3D 0------------------> 1  OpenGL  1^
    //      |                                |
    //      |                                |
    //      |                                |
    //      V                                |
    //      1                                0---------------------> 1
    // The Viewport is defined between 0 and 1 which allows us to automatically
    // scale to the size of the provided window surface
    m_gl->functions()->glViewport(m_viewport.x() * size.width(),
                                  (1.0 - m_viewport.y() - m_viewport.height()) * size.height(),
                                  m_viewport.width() * size.width(),
                                  m_viewport.height() * size.height());
}

void SubmissionContext::releaseOpenGL()
{
    m_renderBufferHash.clear();

    // Stop and destroy the OpenGL logger
    if (m_debugLogger) {
        m_debugLogger->stopLogging();
        m_debugLogger.reset(nullptr);
    }
}

// The OpenGLContext is not current on any surface at this point
void SubmissionContext::setOpenGLContext(QOpenGLContext* ctx)
{
    Q_ASSERT(ctx);

    releaseOpenGL();
    m_gl = ctx;
}

// Called only from RenderThread
bool SubmissionContext::activateShader(GLShader *shader)
{
    if (shader->shaderProgram() != m_activeShader) {
        // Ensure material uniforms are re-applied
        m_material = nullptr;

        m_activeShader = shader->shaderProgram();
        if (Q_LIKELY(m_activeShader != nullptr)) {
            m_activeShader->bind();
        } else {
            m_glHelper->useProgram(0);
            qWarning() << "No shader program found";
            return false;
        }
    }
    return true;
}

SubmissionContext::RenderTargetInfo SubmissionContext::bindFrameBufferAttachmentHelper(GLuint fboId, const AttachmentPack &attachments)
{
    // Set FBO attachments. These are normally textures, except that on Open GL
    // ES <= 3.1 we must use a renderbuffer if a combined depth+stencil is
    // desired since this cannot be achieved neither with a single texture (not
    // before GLES 3.2) nor with separate textures (no suitable format for
    // stencil before 3.1 with the appropriate extension).

    QSize fboSize;
    GLTextureManager *glTextureManager = m_renderer->glResourceManagers()->glTextureManager();
    const auto attachments_ = attachments.attachments();
    for (const Attachment &attachment : attachments_) {
        GLTexture *rTex = glTextureManager->lookupResource(attachment.m_textureUuid);
        if (!m_glHelper->frameBufferNeedsRenderBuffer(attachment)) {
            QOpenGLTexture *glTex = rTex ? rTex->getGLTexture() : nullptr;
            if (glTex != nullptr) {
                // The texture can not be rendered simultaniously by another renderer
                Q_ASSERT(!rTex->isExternalRenderingEnabled());
                if (fboSize.isEmpty())
                    fboSize = QSize(glTex->width(), glTex->height());
                else
                    fboSize = QSize(qMin(fboSize.width(), glTex->width()), qMin(fboSize.height(), glTex->height()));
                m_glHelper->bindFrameBufferAttachment(glTex, attachment);
            }
        } else {
            RenderBuffer *renderBuffer = rTex ? rTex->getOrCreateRenderBuffer() : nullptr;
            if (renderBuffer) {
                if (fboSize.isEmpty())
                    fboSize = QSize(renderBuffer->width(), renderBuffer->height());
                else
                    fboSize = QSize(qMin(fboSize.width(), renderBuffer->width()), qMin(fboSize.height(), renderBuffer->height()));
                m_glHelper->bindFrameBufferAttachment(renderBuffer, attachment);
            }
        }
    }
    return {fboId, fboSize, attachments};
}

void SubmissionContext::activateDrawBuffers(const AttachmentPack &attachments)
{
    const QVector<int> activeDrawBuffers = attachments.getGlDrawBuffers();

    if (m_glHelper->checkFrameBufferComplete()) {
        if (activeDrawBuffers.size() > 1) {// We need MRT
            if (m_glHelper->supportsFeature(GraphicsHelperInterface::MRT)) {
                // Set up MRT, glDrawBuffers...
                m_glHelper->drawBuffers(activeDrawBuffers.size(), activeDrawBuffers.data());
            }
        }
    } else {
        qCWarning(Backend) << "FBO incomplete";
    }
}


void SubmissionContext::setActiveMaterial(Material *rmat)
{
    if (m_material == rmat)
        return;

    m_textureContext.deactivateTexturesWithScope(TextureSubmissionContext::TextureScopeMaterial);
    m_imageContext.deactivateImages();
    m_material = rmat;
}

void SubmissionContext::setCurrentStateSet(RenderStateSet *ss)
{
    if (ss == m_stateSet)
        return;
    if (ss)
        applyStateSet(ss);
    m_stateSet = ss;
}

RenderStateSet *SubmissionContext::currentStateSet() const
{
    return m_stateSet;
}

void SubmissionContext::applyState(const StateVariant &stateVariant)
{
    switch (stateVariant.type) {

    case AlphaCoverageStateMask: {
        applyStateHelper<AlphaCoverage>(static_cast<const AlphaCoverage *>(stateVariant.constState()), this);
        break;
    }
    case AlphaTestMask: {
        applyStateHelper<AlphaFunc>(static_cast<const AlphaFunc *>(stateVariant.constState()), this);
        break;
    }
    case BlendStateMask: {
        applyStateHelper<BlendEquation>(static_cast<const BlendEquation *>(stateVariant.constState()), this);
        break;
    }
    case BlendEquationArgumentsMask: {
        applyStateHelper<BlendEquationArguments>(static_cast<const BlendEquationArguments *>(stateVariant.constState()), this);
        break;
    }
    case MSAAEnabledStateMask: {
        applyStateHelper<MSAAEnabled>(static_cast<const MSAAEnabled *>(stateVariant.constState()), this);
        break;
    }

    case CullFaceStateMask: {
        applyStateHelper<CullFace>(static_cast<const CullFace *>(stateVariant.constState()), this);
        break;
    }

    case DepthWriteStateMask: {
        applyStateHelper<NoDepthMask>(static_cast<const NoDepthMask *>(stateVariant.constState()), this);
        break;
    }

    case DepthTestStateMask: {
        applyStateHelper<DepthTest>(static_cast<const DepthTest *>(stateVariant.constState()), this);
        break;
    }

    case DepthRangeMask: {
        applyStateHelper<DepthRange>(static_cast<const DepthRange *>(stateVariant.constState()), this);
        break;
    }

    case RasterModeMask: {
        applyStateHelper<RasterMode>(static_cast<const RasterMode *>(stateVariant.constState()), this);
        break;
    }

    case FrontFaceStateMask: {
        applyStateHelper<FrontFace>(static_cast<const FrontFace *>(stateVariant.constState()), this);
        break;
    }

    case ScissorStateMask: {
        applyStateHelper<ScissorTest>(static_cast<const ScissorTest *>(stateVariant.constState()), this);
        break;
    }

    case StencilTestStateMask: {
        applyStateHelper<StencilTest>(static_cast<const StencilTest *>(stateVariant.constState()), this);
        break;
    }

    case PointSizeMask: {
        applyStateHelper<PointSize>(static_cast<const PointSize *>(stateVariant.constState()), this);
        break;
    }

    case PolygonOffsetStateMask: {
        applyStateHelper<PolygonOffset>(static_cast<const PolygonOffset *>(stateVariant.constState()), this);
        break;
    }

    case ColorStateMask: {
        applyStateHelper<ColorMask>(static_cast<const ColorMask *>(stateVariant.constState()), this);
        break;
    }

    case ClipPlaneMask: {
        applyStateHelper<ClipPlane>(static_cast<const ClipPlane *>(stateVariant.constState()), this);
        break;
    }

    case SeamlessCubemapMask: {
        applyStateHelper<SeamlessCubemap>(static_cast<const SeamlessCubemap *>(stateVariant.constState()), this);
        break;
    }

    case StencilOpMask: {
        applyStateHelper<StencilOp>(static_cast<const StencilOp *>(stateVariant.constState()), this);
        break;
    }

    case StencilWriteStateMask: {
        applyStateHelper<StencilMask>(static_cast<const StencilMask *>(stateVariant.constState()), this);
        break;
    }

    case DitheringStateMask: {
        applyStateHelper<Dithering>(static_cast<const Dithering *>(stateVariant.constState()), this);
        break;
    }

    case LineWidthMask: {
        applyStateHelper<LineWidth>(static_cast<const LineWidth *>(stateVariant.constState()), this);
        break;
    }
    default:
        Q_UNREACHABLE();
    }
}

void SubmissionContext::resetMasked(qint64 maskOfStatesToReset)
{
    // TO DO -> Call gcHelper methods instead of raw GL
    // QOpenGLFunctions shouldn't be used here directly
    QOpenGLFunctions *funcs = m_gl->functions();

    if (maskOfStatesToReset & ScissorStateMask)
        funcs->glDisable(GL_SCISSOR_TEST);

    if (maskOfStatesToReset & BlendStateMask)
        funcs->glDisable(GL_BLEND);

    if (maskOfStatesToReset & StencilWriteStateMask)
        funcs->glStencilMask(0);

    if (maskOfStatesToReset & StencilTestStateMask)
        funcs->glDisable(GL_STENCIL_TEST);

    if (maskOfStatesToReset & DepthRangeMask)
        depthRange(0.0f, 1.0f);

    if (maskOfStatesToReset & DepthTestStateMask)
        funcs->glDisable(GL_DEPTH_TEST);

    if (maskOfStatesToReset & DepthWriteStateMask)
        funcs->glDepthMask(GL_TRUE); // reset to default

    if (maskOfStatesToReset & FrontFaceStateMask)
        funcs->glFrontFace(GL_CCW); // reset to default

    if (maskOfStatesToReset & CullFaceStateMask)
        funcs->glDisable(GL_CULL_FACE);

    if (maskOfStatesToReset & DitheringStateMask)
        funcs->glDisable(GL_DITHER);

    if (maskOfStatesToReset & AlphaCoverageStateMask)
        setAlphaCoverageEnabled(false);

    if (maskOfStatesToReset & PointSizeMask)
        pointSize(false, 1.0f);    // reset to default

    if (maskOfStatesToReset & PolygonOffsetStateMask)
        funcs->glDisable(GL_POLYGON_OFFSET_FILL);

    if (maskOfStatesToReset & ColorStateMask)
        funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

    if (maskOfStatesToReset & ClipPlaneMask) {
        GLint max = maxClipPlaneCount();
        for (GLint i = 0; i < max; ++i)
            disableClipPlane(i);
    }

    if (maskOfStatesToReset & SeamlessCubemapMask)
        setSeamlessCubemap(false);

    if (maskOfStatesToReset & StencilOpMask)
        funcs->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

    if (maskOfStatesToReset & LineWidthMask)
        funcs->glLineWidth(1.0f);

#ifndef QT_OPENGL_ES_2
    if (maskOfStatesToReset & RasterModeMask)
        m_glHelper->rasterMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
}

void SubmissionContext::applyStateSet(RenderStateSet *ss)
{
    RenderStateSet* previousStates = currentStateSet();

    const StateMaskSet invOurState = ~ss->stateMask();
    // generate a mask for each set bit in previous, where we do not have
    // the corresponding bit set.

    StateMaskSet stateToReset = 0;
    if (previousStates) {
        stateToReset = previousStates->stateMask() & invOurState;
        qCDebug(RenderStates) << "previous states " << QString::number(previousStates->stateMask(), 2);
    }
    qCDebug(RenderStates) << " current states " << QString::number(ss->stateMask(), 2)  << "inverse " << QString::number(invOurState, 2) << " -> states to change:  " << QString::number(stateToReset, 2);

    // Reset states that aren't active in the current state set
    resetMasked(stateToReset);

    // Apply states that weren't in the previous state or that have
    // different values
    const QVector<StateVariant> statesToSet = ss->states();
    for (const StateVariant &ds : statesToSet) {
        if (previousStates && previousStates->contains(ds))
            continue;
        applyState(ds);
    }
}

void SubmissionContext::clearColor(const QColor &color)
{
    if (m_currClearColorValue != color) {
        m_currClearColorValue = color;
        m_gl->functions()->glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
    }
}

void SubmissionContext::clearDepthValue(float depth)
{
    if (m_currClearDepthValue != depth) {
        m_currClearDepthValue = depth;
        m_gl->functions()->glClearDepthf(depth);
    }
}

void SubmissionContext::clearStencilValue(int stencil)
{
    if (m_currClearStencilValue != stencil) {
        m_currClearStencilValue = stencil;
        m_gl->functions()->glClearStencil(stencil);
    }
}

GLFence SubmissionContext::fenceSync()
{
    return m_glHelper->fenceSync();
}

void SubmissionContext::clientWaitSync(GLFence sync, GLuint64 nanoSecTimeout)
{
    qDebug() << Q_FUNC_INFO << sync;
    m_glHelper->clientWaitSync(sync, nanoSecTimeout);
}

void SubmissionContext::waitSync(GLFence sync)
{
    qDebug() << Q_FUNC_INFO << sync;
    m_glHelper->waitSync(sync);
}

bool SubmissionContext::wasSyncSignaled(GLFence sync)
{
    return m_glHelper->wasSyncSignaled(sync);
}

void SubmissionContext::deleteSync(GLFence sync)
{
    m_glHelper->deleteSync(sync);
}

void SubmissionContext::setUpdatedTexture(const Qt3DCore::QNodeIdVector &updatedTextureIds)
{
    m_updateTextureIds = updatedTextureIds;
}

// It will be easier if the QGraphicContext applies the QUniformPack
// than the other way around
bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack, GLShader *shader)
{
    static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
    static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
    // Activate textures and update TextureUniform in the pack
    // with the correct textureUnit

    // Set the pinned texture of the previous material texture
    // to pinable so that we should easily find an available texture unit
    m_textureContext.deactivateTexturesWithScope(TextureSubmissionContext::TextureScopeMaterial);
    // Update the uniforms with the correct texture unit id's
    PackUniformHash &uniformValues = parameterPack.uniforms();

    // Fill Texture Uniform Value with proper texture units
    // so that they can be applied as regular uniforms in a second step
    for (int i = 0; i < parameterPack.textures().size(); ++i) {
        const ShaderParameterPack::NamedResource &namedTex = parameterPack.textures().at(i);
        // Given a Texture QNodeId, we retrieve the associated shared GLTexture
        if (uniformValues.contains(namedTex.glslNameId)) {
            GLTexture *t = m_renderer->glResourceManagers()->glTextureManager()->lookupResource(namedTex.nodeId);
            if (t != nullptr) {
                UniformValue &texUniform = uniformValues.value(namedTex.glslNameId);
                if (texUniform.valueType() == UniformValue::TextureValue) {
                    const int texUnit = m_textureContext.activateTexture(TextureSubmissionContext::TextureScopeMaterial, m_gl, t);
                    texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit;
                    if (texUnit == -1) {
                        if (namedTex.glslNameId != irradianceId &&
                            namedTex.glslNameId != specularId) {
                            // Only return false if we are not dealing with env light textures
                            qCWarning(Backend) << "Unable to find suitable Texture Unit";
                            return false;
                        }
                    }
                }
            }
        }
    }

    // Fill Image Uniform Value with proper image units
    // so that they can be applied as regular uniforms in a second step
    for (int i = 0; i < parameterPack.images().size(); ++i) {
        const ShaderParameterPack::NamedResource &namedTex = parameterPack.images().at(i);
        // Given a Texture QNodeId, we retrieve the associated shared GLTexture
        if (uniformValues.contains(namedTex.glslNameId)) {
            ShaderImage *img = m_renderer->nodeManagers()->shaderImageManager()->lookupResource(namedTex.nodeId);
            if (img != nullptr) {
                GLTexture *t = m_renderer->glResourceManagers()->glTextureManager()->lookupResource(img->textureId());
                if (t == nullptr) {
                    qCWarning(Backend) << "Shader Image referencing invalid texture";
                    continue;
                } else {
                    UniformValue &imgUniform = uniformValues.value(namedTex.glslNameId);
                    if (imgUniform.valueType() == UniformValue::ShaderImageValue) {
                        const int imgUnit = m_imageContext.activateImage(img, t);
                        imgUniform.data<int>()[namedTex.uniformArrayIndex] = imgUnit;
                        if (imgUnit == -1) {
                            qCWarning(Backend) << "Unable to bind Image to Texture";
                            return false;
                        }
                    }
                }
            }
        }
    }

    QOpenGLShaderProgram *glShader = activeShader();

    // TO DO: We could cache the binding points somehow and only do the binding when necessary
    // for SSBO and UBO

    // Bind Shader Storage block to SSBO and update SSBO
    const std::vector<BlockToSSBO> &blockToSSBOs = parameterPack.shaderStorageBuffers();
    for (const BlockToSSBO b : blockToSSBOs) {
        Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID);
        GLBuffer *ssbo = glBufferForRenderBuffer(cpuBuffer);
        // bindShaderStorageBlock
        // This is currently not required as we are introspecting the bindingIndex
        // value from the shaders and not replacing them, making such a call useless
        // bindShaderStorageBlock(shader->programId(), b.m_blockIndex, b.m_bindingIndex);
        bindShaderStorageBlock(glShader->programId(), b.m_blockIndex, b.m_bindingIndex);
        // Needed to avoid conflict where the buffer would already
        // be bound as a VertexArray
        bindGLBuffer(ssbo, GLBuffer::ShaderStorageBuffer);
        ssbo->bindBufferBase(this, b.m_bindingIndex, GLBuffer::ShaderStorageBuffer);
        // TO DO: Make sure that there's enough binding points
    }

    // Bind UniformBlocks to UBO and update UBO from Buffer
    // TO DO: Convert ShaderData to Buffer so that we can use that generic process
    const std::vector<BlockToUBO> &blockToUBOs = parameterPack.uniformBuffers();
    int uboIndex = 0;
    for (const BlockToUBO &b : blockToUBOs) {
        Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID);
        GLBuffer *ubo = glBufferForRenderBuffer(cpuBuffer);
        bindUniformBlock(glShader->programId(), b.m_blockIndex, uboIndex);
        // Needed to avoid conflict where the buffer would already
        // be bound as a VertexArray
        bindGLBuffer(ubo, GLBuffer::UniformBuffer);
        ubo->bindBufferBase(this, uboIndex++, GLBuffer::UniformBuffer);
        // TO DO: Make sure that there's enough binding points
    }

    // Update uniforms in the Default Uniform Block
    const PackUniformHash& values = parameterPack.uniforms();
    const auto &activeUniformsIndices = parameterPack.submissionUniformIndices();
    const QVector<ShaderUniform> &shaderUniforms = shader->uniforms();

    for (const int shaderUniformIndex : activeUniformsIndices) {
        const ShaderUniform &uniform = shaderUniforms[shaderUniformIndex];
        values.apply(uniform.m_nameId, [&] (const UniformValue& v) {
            // skip invalid textures/images
            if (!((v.valueType() == UniformValue::TextureValue ||
                   v.valueType() == UniformValue::ShaderImageValue) &&
                  *v.constData<int>() == -1))
                applyUniform(uniform, v);
        });

    }
    // if not all data is valid, the next frame will be rendered immediately
    return true;
}

void SubmissionContext::enableAttribute(const VAOVertexAttribute &attr)
{
    // Bind buffer within the current VAO
    GLBuffer *buf = m_renderer->glResourceManagers()->glBufferManager()->data(attr.bufferHandle);
    Q_ASSERT(buf);
    bindGLBuffer(buf, attr.attributeType);

    // Don't use QOpenGLShaderProgram::setAttributeBuffer() because of QTBUG-43199.
    // Use the introspection data and set the attribute explicitly
    m_glHelper->enableVertexAttributeArray(attr.location);
    m_glHelper->vertexAttributePointer(attr.shaderDataType,
                                       attr.location,
                                       attr.vertexSize,
                                       attr.dataType,
                                       GL_TRUE, // TODO: Support normalization property on QAttribute
                                       attr.byteStride,
                                       reinterpret_cast<const void *>(qintptr(attr.byteOffset)));


    // Done by the helper if it supports it
    if (attr.divisor != 0)
        m_glHelper->vertexAttribDivisor(attr.location, attr.divisor);
}

void SubmissionContext::disableAttribute(const SubmissionContext::VAOVertexAttribute &attr)
{
    QOpenGLShaderProgram *prog = activeShader();
    prog->disableAttributeArray(attr.location);
}

// Note: needs to be called while VAO is bound
void SubmissionContext::specifyAttribute(const Attribute *attribute,
                                       Buffer *buffer,
                                       const ShaderAttribute *attributeDescription)
{
    const int location = attributeDescription->m_location;
    if (location < 0) {
        qCWarning(Backend) << "failed to resolve location for attribute:" << attribute->name();
        return;
    }

    const GLint attributeDataType = glDataTypeFromAttributeDataType(attribute->vertexBaseType());
    const HGLBuffer glBufferHandle = m_renderer->glResourceManagers()->glBufferManager()->lookupHandle(buffer->peerId());
    Q_ASSERT(!glBufferHandle.isNull());
    const GLBuffer::Type attributeType = attributeTypeToGLBufferType(attribute->attributeType());

    int typeSize = 0;
    int attrCount = 0;

    if (attribute->vertexSize() >= 1 && attribute->vertexSize() <= 4) {
        attrCount = 1;
    } else if (attribute->vertexSize() == 9) {
        typeSize = byteSizeFromType(attributeDataType);
        attrCount = 3;
    } else if (attribute->vertexSize() == 16) {
        typeSize = byteSizeFromType(attributeDataType);
        attrCount = 4;
    } else {
        Q_UNREACHABLE();
    }

    Q_ASSERT(!glBufferHandle.isNull());
    VAOVertexAttribute attr;
    attr.bufferHandle = glBufferHandle;
    attr.attributeType = attributeType;
    attr.dataType = attributeDataType;
    attr.divisor = attribute->divisor();
    attr.vertexSize = attribute->vertexSize() / attrCount;
    attr.byteStride = (attribute->byteStride() != 0) ? attribute->byteStride() : (attrCount * attrCount * typeSize);
    attr.shaderDataType = attributeDescription->m_type;

    for (int i = 0; i < attrCount; i++) {
        attr.location = location + i;
        attr.byteOffset = attribute->byteOffset() + (i * attrCount * typeSize);

        enableAttribute(attr);

        // Save this in the current emulated VAO
        if (m_currentVAO)
            m_currentVAO->saveVertexAttribute(attr);
    }
}

void SubmissionContext::specifyIndices(Buffer *buffer)
{
    GLBuffer *buf = glBufferForRenderBuffer(buffer);
    if (!bindGLBuffer(buf, GLBuffer::IndexBuffer))
        qCWarning(Backend) << Q_FUNC_INFO << "binding index buffer failed";

    // bound within the current VAO
    // Save this in the current emulated VAO
    if (m_currentVAO)
        m_currentVAO->saveIndexAttribute(m_renderer->glResourceManagers()->glBufferManager()->lookupHandle(buffer->peerId()));
}

void SubmissionContext::updateBuffer(Buffer *buffer)
{
    const QHash<Qt3DCore::QNodeId, HGLBuffer>::iterator it = m_renderBufferHash.find(buffer->peerId());
    if (it != m_renderBufferHash.end())
        uploadDataToGLBuffer(buffer, m_renderer->glResourceManagers()->glBufferManager()->data(it.value()));
}

QByteArray SubmissionContext::downloadBufferContent(Buffer *buffer)
{
    const QHash<Qt3DCore::QNodeId, HGLBuffer>::iterator it = m_renderBufferHash.find(buffer->peerId());
    if (it != m_renderBufferHash.end())
        return downloadDataFromGLBuffer(buffer, m_renderer->glResourceManagers()->glBufferManager()->data(it.value()));
    return QByteArray();
}

void SubmissionContext::releaseBuffer(Qt3DCore::QNodeId bufferId)
{
    auto it = m_renderBufferHash.find(bufferId);
    if (it != m_renderBufferHash.end()) {
        HGLBuffer glBuffHandle = it.value();
        GLBuffer *glBuff = m_renderer->glResourceManagers()->glBufferManager()->data(glBuffHandle);

        Q_ASSERT(glBuff);
        // Destroy the GPU resource
        glBuff->destroy(this);
        // Destroy the GLBuffer instance
        m_renderer->glResourceManagers()->glBufferManager()->releaseResource(bufferId);
        // Remove Id - HGLBuffer entry
        m_renderBufferHash.erase(it);
    }
}

bool SubmissionContext::hasGLBufferForBuffer(Buffer *buffer)
{
    const QHash<Qt3DCore::QNodeId, HGLBuffer>::iterator it = m_renderBufferHash.find(buffer->peerId());
    return (it != m_renderBufferHash.end());
}

GLBuffer *SubmissionContext::glBufferForRenderBuffer(Buffer *buf)
{
    if (!m_renderBufferHash.contains(buf->peerId()))
        m_renderBufferHash.insert(buf->peerId(), createGLBufferFor(buf));
    return m_renderer->glResourceManagers()->glBufferManager()->data(m_renderBufferHash.value(buf->peerId()));
}

HGLBuffer SubmissionContext::createGLBufferFor(Buffer *buffer)
{
    GLBuffer *b = m_renderer->glResourceManagers()->glBufferManager()->getOrCreateResource(buffer->peerId());
    //    b.setUsagePattern(static_cast<QOpenGLBuffer::UsagePattern>(buffer->usage()));
    Q_ASSERT(b);
    if (!b->create(this))
        qCWarning(Io) << Q_FUNC_INFO << "buffer creation failed";

    return m_renderer->glResourceManagers()->glBufferManager()->lookupHandle(buffer->peerId());
}

bool SubmissionContext::bindGLBuffer(GLBuffer *buffer, GLBuffer::Type type)
{
    if (type == GLBuffer::ArrayBuffer && buffer == m_boundArrayBuffer)
        return true;

    if (buffer->bind(this, type)) {
        if (type == GLBuffer::ArrayBuffer)
            m_boundArrayBuffer = buffer;
        return true;
    }
    return false;
}

void SubmissionContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool releaseBuffer)
{
    if (!bindGLBuffer(b, GLBuffer::ArrayBuffer)) // We're uploading, the type doesn't matter here
        qCWarning(Io) << Q_FUNC_INFO << "buffer bind failed";
    // If the buffer is dirty (hence being called here)
    // there are two possible cases
    // * setData was called changing the whole data or functor (or the usage pattern)
    // * partial buffer updates where received

    // TO DO: Handle usage pattern
    QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates());
    for (auto it = updates.begin(); it != updates.end(); ++it) {
        auto update = it;
        // We have a partial update
        if (update->offset >= 0) {
            //accumulate sequential updates as single one
            int bufferSize = update->data.size();
            auto it2 = it + 1;
            while ((it2 != updates.end())
                   && (it2->offset - update->offset == bufferSize)) {
                bufferSize += it2->data.size();
                ++it2;
            }
            update->data.resize(bufferSize);
            while (it + 1 != it2) {
                ++it;
                update->data.replace(it->offset - update->offset, it->data.size(), it->data);
                it->data.clear();
            }
            // TO DO: based on the number of updates .., it might make sense to
            // sometime use glMapBuffer rather than glBufferSubData
            b->update(this, update->data.constData(), update->data.size(), update->offset);
        } else {
            // We have an update that was done by calling QBuffer::setData
            // which is used to resize or entirely clear the buffer
            // Note: we use the buffer data directly in that case
            const int bufferSize = buffer->data().size();
            b->allocate(this, bufferSize, false); // orphan the buffer
            b->allocate(this, buffer->data().constData(), bufferSize, false);
        }
    }

    if (releaseBuffer) {
        b->release(this);
        m_boundArrayBuffer = nullptr;
    }
    qCDebug(Io) << "uploaded buffer size=" << buffer->data().size();
}

QByteArray SubmissionContext::downloadDataFromGLBuffer(Buffer *buffer, GLBuffer *b)
{
    if (!bindGLBuffer(b, GLBuffer::ArrayBuffer)) // We're downloading, the type doesn't matter here
        qCWarning(Io) << Q_FUNC_INFO << "buffer bind failed";

    QByteArray data = b->download(this, buffer->data().size());
    return data;
}

void SubmissionContext::blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId,
                                        Qt3DCore::QNodeId outputRenderTargetId,
                                        QRect inputRect, QRect outputRect,
                                        uint defaultFboId,
                                        QRenderTargetOutput::AttachmentPoint inputAttachmentPoint,
                                        QRenderTargetOutput::AttachmentPoint outputAttachmentPoint,
                                        QBlitFramebuffer::InterpolationMethod interpolationMethod)
{
    GLuint inputFboId = defaultFboId;
    bool inputBufferIsDefault = true;
    if (!inputRenderTargetId.isNull()) {
        RenderTarget *renderTarget = m_renderer->nodeManagers()->renderTargetManager()->lookupResource(inputRenderTargetId);
        if (renderTarget) {
            AttachmentPack attachments(renderTarget, m_renderer->nodeManagers()->attachmentManager());
            if (m_renderTargets.contains(inputRenderTargetId))
                inputFboId = updateRenderTarget(inputRenderTargetId, attachments, false);
            else
                inputFboId = createRenderTarget(inputRenderTargetId, attachments);
        }
        inputBufferIsDefault = false;
    }

    GLuint outputFboId = defaultFboId;
    bool outputBufferIsDefault = true;
    if (!outputRenderTargetId.isNull()) {
        RenderTarget *renderTarget = m_renderer->nodeManagers()->renderTargetManager()->lookupResource(outputRenderTargetId);
        if (renderTarget) {
            AttachmentPack attachments(renderTarget, m_renderer->nodeManagers()->attachmentManager());
            if (m_renderTargets.contains(outputRenderTargetId))
                outputFboId = updateRenderTarget(outputRenderTargetId, attachments, false);
            else
                outputFboId = createRenderTarget(outputRenderTargetId, attachments);
        }
        outputBufferIsDefault = false;
    }

    // Up until this point the input and output rects are normal Qt rectangles.
    // Convert them to GL rectangles (Y at bottom).
    const int inputFboHeight = inputFboId == defaultFboId ? m_surfaceSize.height() : m_renderTargets[inputRenderTargetId].size.height();
    const GLint srcX0 = inputRect.left();
    const GLint srcY0 = inputFboHeight - (inputRect.top() + inputRect.height());
    const GLint srcX1 = srcX0 + inputRect.width();
    const GLint srcY1 = srcY0 + inputRect.height();

    const int outputFboHeight = outputFboId == defaultFboId ? m_surfaceSize.height() : m_renderTargets[outputRenderTargetId].size.height();
    const GLint dstX0 = outputRect.left();
    const GLint dstY0 = outputFboHeight - (outputRect.top() + outputRect.height());
    const GLint dstX1 = dstX0 + outputRect.width();
    const GLint dstY1 = dstY0 + outputRect.height();

    //Get the last bounded framebuffers
    const GLuint lastDrawFboId = boundFrameBufferObject();

    // Activate input framebuffer for reading
    bindFramebuffer(inputFboId, GraphicsHelperInterface::FBORead);

    // Activate output framebuffer for writing
    bindFramebuffer(outputFboId, GraphicsHelperInterface::FBODraw);

    //Bind texture
    if (!inputBufferIsDefault)
        readBuffer(glAttachmentPoint(inputAttachmentPoint));

    if (!outputBufferIsDefault) {
        // Note that we use glDrawBuffers, not glDrawBuffer. The
        // latter is not available with GLES.
        const int buf = glAttachmentPoint(outputAttachmentPoint);
        drawBuffers(1, &buf);
    }

    // Blit framebuffer
    const GLenum mode = interpolationMethod ? GL_NEAREST : GL_LINEAR;
    m_glHelper->blitFramebuffer(srcX0, srcY0, srcX1, srcY1,
                                dstX0, dstY0, dstX1, dstY1,
                                GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT,
                                mode);

    // Reset draw buffer
    bindFramebuffer(lastDrawFboId, GraphicsHelperInterface::FBOReadAndDraw);
    if (outputAttachmentPoint != QRenderTargetOutput::Color0) {
        const int buf = QRenderTargetOutput::Color0;
        drawBuffers(1, &buf);
    }
}

} // namespace OpenGL
} // namespace Render
} // namespace Qt3DRender of namespace

QT_END_NAMESPACE
