From e49cec310cd4d24949e3bb8cbc39d5b161893e39 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 10 Aug 2015 15:50:30 +0200 Subject: QGraphicsHelperGL4: dedicated helper for OpenGL 4.3+ Will allow the introduction of indirect draw calls Change-Id: Ia830c0f6638382a4884097dd96de61e0fbb4c015 Reviewed-by: Sean Harmer --- src/render/backend/qgraphicscontext.cpp | 7 +- src/render/backend/qgraphicshelpergl4.cpp | 871 ++++++++++++++++++++++++++++++ src/render/backend/qgraphicshelpergl4_p.h | 106 ++++ src/render/backend/render-backend.pri | 2 + 4 files changed, 985 insertions(+), 1 deletion(-) create mode 100644 src/render/backend/qgraphicshelpergl4.cpp create mode 100644 src/render/backend/qgraphicshelpergl4_p.h diff --git a/src/render/backend/qgraphicscontext.cpp b/src/render/backend/qgraphicscontext.cpp index 24c627786..797f31041 100644 --- a/src/render/backend/qgraphicscontext.cpp +++ b/src/render/backend/qgraphicscontext.cpp @@ -57,8 +57,10 @@ #if !defined(QT_OPENGL_ES_2) #include #include +#include #include #include +#include #endif #include @@ -519,7 +521,10 @@ void QGraphicsContext::resolveHighestOpenGLFunctions() #ifndef QT_OPENGL_ES_2 else { QAbstractOpenGLFunctions *glFunctions = Q_NULLPTR; - if ((glFunctions = m_gl->versionFunctions()) != Q_NULLPTR) { + if ((glFunctions = m_gl->versionFunctions()) != Q_NULLPTR) { + qCDebug(Backend) << Q_FUNC_INFO << " Building OpenGL 4.3"; + m_glHelper = new QGraphicsHelperGL4(); + } else if ((glFunctions = m_gl->versionFunctions()) != Q_NULLPTR) { qCDebug(Backend) << Q_FUNC_INFO << " Building OpenGL 3.2"; m_glHelper = new QGraphicsHelperGL3(); } diff --git a/src/render/backend/qgraphicshelpergl4.cpp b/src/render/backend/qgraphicshelpergl4.cpp new file mode 100644 index 000000000..103ea15bf --- /dev/null +++ b/src/render/backend/qgraphicshelpergl4.cpp @@ -0,0 +1,871 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicshelpergl4_p.h" + +#ifndef QT_OPENGL_ES_2 +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3D { +namespace Render { + +QGraphicsHelperGL4::QGraphicsHelperGL4() + : m_funcs(Q_NULLPTR) +{ +} + +void QGraphicsHelperGL4::initializeHelper(QOpenGLContext *context, + QAbstractOpenGLFunctions *functions) +{ + Q_UNUSED(context); + m_funcs = static_cast(functions); + const bool ok = m_funcs->initializeOpenGLFunctions(); + Q_ASSERT(ok); + Q_UNUSED(ok); +} + +void QGraphicsHelperGL4::drawElementsInstanced(GLenum primitiveType, + GLsizei primitiveCount, + GLint indexType, + void *indices, + GLsizei instances, + GLint baseVertex, + GLint baseInstance) +{ + if (baseInstance != 0) + qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2"; + + // glDrawElements OpenGL 3.1 or greater + m_funcs->glDrawElementsInstancedBaseVertex(primitiveType, + primitiveCount, + indexType, + indices, + instances, + baseVertex); +} + +void QGraphicsHelperGL4::drawArraysInstanced(GLenum primitiveType, + GLint first, + GLsizei count, + GLsizei instances) +{ + // glDrawArraysInstanced OpenGL 3.1 or greater + m_funcs->glDrawArraysInstanced(primitiveType, + first, + count, + instances); +} + +void QGraphicsHelperGL4::drawElements(GLenum primitiveType, + GLsizei primitiveCount, + GLint indexType, + void *indices, + GLint baseVertex) +{ + m_funcs->glDrawElementsBaseVertex(primitiveType, + primitiveCount, + indexType, + indices, + baseVertex); +} + +void QGraphicsHelperGL4::drawArrays(GLenum primitiveType, + GLint first, + GLsizei count) +{ + m_funcs->glDrawArrays(primitiveType, + first, + count); +} + +void QGraphicsHelperGL4::setVerticesPerPatch(GLint verticesPerPatch) +{ + m_funcs->glPatchParameteri(GL_PATCH_VERTICES, verticesPerPatch); +} + +void QGraphicsHelperGL4::useProgram(GLuint programId) +{ + m_funcs->glUseProgram(programId); +} + +QVector QGraphicsHelperGL4::programUniformsAndLocations(GLuint programId) +{ + QVector uniforms; + + GLint nbrActiveUniforms = 0; + m_funcs->glGetProgramiv(programId, GL_ACTIVE_UNIFORMS, &nbrActiveUniforms); + uniforms.reserve(nbrActiveUniforms); + char uniformName[256]; + for (GLint i = 0; i < nbrActiveUniforms; i++) { + ShaderUniform uniform; + GLsizei uniformNameLength = 0; + // Size is 1 for scalar and more for struct or arrays + // Type is the GL Type + m_funcs->glGetActiveUniform(programId, i, sizeof(uniformName) - 1, &uniformNameLength, + &uniform.m_size, &uniform.m_type, uniformName); + uniformName[sizeof(uniformName) - 1] = '\0'; + uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName); + uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength); + m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &uniform.m_blockIndex); + m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_OFFSET, &uniform.m_offset); + m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_ARRAY_STRIDE, &uniform.m_arrayStride); + m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_MATRIX_STRIDE, &uniform.m_matrixStride); + uniform.m_rawByteSize = uniformByteSize(uniform); + uniforms.append(uniform); + qCDebug(Render::Rendering) << uniform.m_name << "size" << uniform.m_size + << " offset" << uniform.m_offset + << " rawSize" << uniform.m_rawByteSize; + } + + return uniforms; +} + +QVector QGraphicsHelperGL4::programAttributesAndLocations(GLuint programId) +{ + QVector attributes; + GLint nbrActiveAttributes = 0; + m_funcs->glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTES, &nbrActiveAttributes); + attributes.reserve(nbrActiveAttributes); + char attributeName[256]; + for (GLint i = 0; i < nbrActiveAttributes; i++) { + ShaderAttribute attribute; + GLsizei attributeNameLength = 0; + // Size is 1 for scalar and more for struct or arrays + // Type is the GL Type + m_funcs->glGetActiveAttrib(programId, i, sizeof(attributeName) - 1, &attributeNameLength, + &attribute.m_size, &attribute.m_type, attributeName); + attributeName[sizeof(attributeName) - 1] = '\0'; + attribute.m_location = m_funcs->glGetAttribLocation(programId, attributeName); + attribute.m_name = QString::fromUtf8(attributeName, attributeNameLength); + attributes.append(attribute); + } + return attributes; +} + +QVector QGraphicsHelperGL4::programUniformBlocks(GLuint programId) +{ + QVector blocks; + GLint nbrActiveUniformsBlocks = 0; + m_funcs->glGetProgramiv(programId, GL_ACTIVE_UNIFORM_BLOCKS, &nbrActiveUniformsBlocks); + blocks.reserve(nbrActiveUniformsBlocks); + for (GLint i = 0; i < nbrActiveUniformsBlocks; i++) { + QByteArray uniformBlockName(256, '\0'); + ShaderUniformBlock uniformBlock; + m_funcs->glGetActiveUniformBlockName(programId, i, 256, NULL, uniformBlockName.data()); + uniformBlock.m_name = QString::fromUtf8(uniformBlockName); + uniformBlock.m_index = i; + m_funcs->glGetActiveUniformBlockiv(programId, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformBlock.m_activeUniformsCount); + m_funcs->glGetActiveUniformBlockiv(programId, i, GL_UNIFORM_BLOCK_BINDING, &uniformBlock.m_binding); + m_funcs->glGetActiveUniformBlockiv(programId, i, GL_UNIFORM_BLOCK_DATA_SIZE, &uniformBlock.m_size); + blocks.append(uniformBlock); + } + return blocks; +} + +void QGraphicsHelperGL4::vertexAttribDivisor(GLuint index, GLuint divisor) +{ + Q_UNUSED(index); + Q_UNUSED(divisor); +} + +void QGraphicsHelperGL4::blendEquation(GLenum mode) +{ + m_funcs->glBlendEquation(mode); +} + +void QGraphicsHelperGL4::alphaTest(GLenum, GLenum) +{ + qCWarning(Render::Rendering) << "AlphaTest not available with OpenGL 3.2 core"; +} + +void QGraphicsHelperGL4::depthTest(GLenum mode) +{ + m_funcs->glEnable(GL_DEPTH_TEST); + m_funcs->glDepthFunc(mode); +} + +void QGraphicsHelperGL4::depthMask(GLenum mode) +{ + m_funcs->glDepthMask(mode); +} + +void QGraphicsHelperGL4::cullFace(GLenum mode) +{ + m_funcs->glEnable(GL_CULL_FACE); + m_funcs->glCullFace(mode); +} + +void QGraphicsHelperGL4::frontFace(GLenum mode) +{ + m_funcs->glFrontFace(mode); + +} + +void QGraphicsHelperGL4::enableAlphaCoverage() +{ + m_funcs->glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); +} + +void QGraphicsHelperGL4::disableAlphaCoverage() +{ + m_funcs->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); +} + +GLuint QGraphicsHelperGL4::createFrameBufferObject() +{ + GLuint id; + m_funcs->glGenFramebuffers(1, &id); + return id; +} + +void QGraphicsHelperGL4::releaseFrameBufferObject(GLuint frameBufferId) +{ + m_funcs->glDeleteFramebuffers(1, &frameBufferId); +} + +void QGraphicsHelperGL4::bindFrameBufferObject(GLuint frameBufferId) +{ + m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); +} + +GLuint QGraphicsHelperGL4::boundFrameBufferObject() +{ + GLint id = 0; + m_funcs->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &id); + return id; +} + +bool QGraphicsHelperGL4::checkFrameBufferComplete() +{ + return (m_funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); +} + +void QGraphicsHelperGL4::bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) +{ + GLenum attr = GL_DEPTH_STENCIL_ATTACHMENT; + + if (attachment.m_type <= QRenderAttachment::ColorAttachment15) + attr = GL_COLOR_ATTACHMENT0 + attachment.m_type; + else if (attachment.m_type == QRenderAttachment::DepthAttachment) + attr = GL_DEPTH_ATTACHMENT; + else if (attachment.m_type == QRenderAttachment::StencilAttachment) + attr = GL_STENCIL_ATTACHMENT; + + texture->bind(); + QOpenGLTexture::Target target = texture->target(); + if (target == QOpenGLTexture::Target1DArray || target == QOpenGLTexture::Target2DArray || + target == QOpenGLTexture::Target2DMultisampleArray || target == QOpenGLTexture::Target3D) + m_funcs->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); + else if (target == QOpenGLTexture::TargetCubeMapArray) + m_funcs->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); + else if (target == QOpenGLTexture::TargetCubeMap) + m_funcs->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); + else + m_funcs->glFramebufferTexture(GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel); + texture->release(); +} + +bool QGraphicsHelperGL4::supportsFeature(QGraphicsHelperInterface::Feature feature) const +{ + switch (feature) { + case MRT: + case Tessellation: + case UniformBufferObject: + return true; + default: + return false; + } +} + +void QGraphicsHelperGL4::drawBuffers(GLsizei n, const int *bufs) +{ + // Use QVarLengthArray here + QVarLengthArray drawBufs(n); + + for (int i = 0; i < n; i++) + drawBufs[i] = GL_COLOR_ATTACHMENT0 + bufs[i]; + m_funcs->glDrawBuffers(n, drawBufs.constData()); +} + +void QGraphicsHelperGL4::bindFragDataLocation(GLuint shader, const QHash &outputs) +{ + Q_FOREACH (const QString &name, outputs.keys()) + m_funcs->glBindFragDataLocation(shader, outputs.value(name), name.toStdString().c_str()); +} + +void QGraphicsHelperGL4::bindUniform(const QVariant &v, const ShaderUniform &description) +{ + switch (description.m_type) { + + case GL_FLOAT: + m_funcs->glUniform1fv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1)); + break; + + case GL_FLOAT_VEC2: + m_funcs->glUniform2fv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2)); + break; + + case GL_FLOAT_VEC3: + m_funcs->glUniform3fv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3)); + break; + + case GL_FLOAT_VEC4: + m_funcs->glUniform4fv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4)); + break; + + case GL_FLOAT_MAT2: + m_funcs->glUniformMatrix2fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4)); + break; + + case GL_FLOAT_MAT2x3: + m_funcs->glUniformMatrix2x3fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 6)); + break; + + case GL_FLOAT_MAT2x4: + m_funcs->glUniformMatrix2x4fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 8)); + break; + + case GL_FLOAT_MAT3: + m_funcs->glUniformMatrix3fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 9)); + break; + + case GL_FLOAT_MAT3x2: + m_funcs->glUniformMatrix3x2fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 6)); + break; + + case GL_FLOAT_MAT3x4: + m_funcs->glUniformMatrix3x4fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 12)); + break; + + case GL_FLOAT_MAT4: + m_funcs->glUniformMatrix4fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 16)); + break; + + case GL_FLOAT_MAT4x2: + m_funcs->glUniformMatrix4x2fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 8)); + break; + + case GL_FLOAT_MAT4x3: + m_funcs->glUniformMatrix4x3fv(description.m_location, description.m_size, GL_FALSE, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 12)); + break; + + case GL_INT: + m_funcs->glUniform1iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1)); + break; + + case GL_INT_VEC2: + m_funcs->glUniform2iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2)); + break; + + case GL_INT_VEC3: + m_funcs->glUniform3iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3)); + break; + + case GL_INT_VEC4: + m_funcs->glUniform4iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4)); + break; + + case GL_UNSIGNED_INT: + m_funcs->glUniform1uiv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1)); + break; + + case GL_UNSIGNED_INT_VEC2: + m_funcs->glUniform2uiv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2)); + break; + + case GL_UNSIGNED_INT_VEC3: + m_funcs->glUniform3uiv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3)); + break; + + case GL_UNSIGNED_INT_VEC4: + m_funcs->glUniform4uiv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4)); + break; + + case GL_BOOL: + m_funcs->glUniform1iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1)); + break; + + case GL_BOOL_VEC2: + m_funcs->glUniform2iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2)); + break; + + case GL_BOOL_VEC3: + m_funcs->glUniform3iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3)); + break; + + case GL_BOOL_VEC4: + m_funcs->glUniform4iv(description.m_location, description.m_size, + QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4)); + break; + + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_RECT_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: { + Q_ASSERT(description.m_size == 1); + m_funcs->glUniform1i(description.m_location, v.toInt()); + break; + } + + default: + qWarning() << Q_FUNC_INFO << "unsupported uniform type:" << description.m_type << "for " << description.m_name; + break; + } +} + +void QGraphicsHelperGL4::bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + m_funcs->glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding); +} + +void QGraphicsHelperGL4::bindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + m_funcs->glBindBufferBase(target, index, buffer); +} + +void QGraphicsHelperGL4::buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) +{ + char *bufferData = buffer.data(); + + switch (description.m_type) { + + case GL_FLOAT: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1); + QGraphicsUtils::fillDataArray(bufferData, data, description, 1); + break; + } + + case GL_FLOAT_VEC2: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2); + QGraphicsUtils::fillDataArray(bufferData, data, description, 2); + break; + } + + case GL_FLOAT_VEC3: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3); + QGraphicsUtils::fillDataArray(bufferData, data, description, 3); + break; + } + + case GL_FLOAT_VEC4: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4); + QGraphicsUtils::fillDataArray(bufferData, data, description, 4); + break; + } + + case GL_FLOAT_MAT2: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 2, 2); + break; + } + + case GL_FLOAT_MAT2x3: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 6); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 2, 3); + break; + } + + case GL_FLOAT_MAT2x4: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 8); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 2, 4); + break; + } + + case GL_FLOAT_MAT3: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 9); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 3, 3); + break; + } + + case GL_FLOAT_MAT3x2: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 6); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 3, 2); + break; + } + + case GL_FLOAT_MAT3x4: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 12); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 3, 4); + break; + } + + case GL_FLOAT_MAT4: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 16); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 4, 4); + break; + } + + case GL_FLOAT_MAT4x2: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 8); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 4, 2); + break; + } + + case GL_FLOAT_MAT4x3: { + const GLfloat *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 12); + QGraphicsUtils::fillDataMatrixArray(bufferData, data, description, 4, 3); + break; + } + + case GL_INT: { + const GLint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1); + QGraphicsUtils::fillDataArray(bufferData, data, description, 1); + break; + } + + case GL_INT_VEC2: { + const GLint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2); + QGraphicsUtils::fillDataArray(bufferData, data, description, 2); + break; + } + + case GL_INT_VEC3: { + const GLint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3); + QGraphicsUtils::fillDataArray(bufferData, data, description, 3); + break; + } + + case GL_INT_VEC4: { + const GLint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4); + QGraphicsUtils::fillDataArray(bufferData, data, description, 4); + break; + } + + case GL_UNSIGNED_INT: { + const GLuint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1); + QGraphicsUtils::fillDataArray(bufferData, data, description, 1); + break; + } + + case GL_UNSIGNED_INT_VEC2: { + const GLuint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2); + QGraphicsUtils::fillDataArray(bufferData, data, description, 2); + break; + } + + case GL_UNSIGNED_INT_VEC3: { + const GLuint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3); + QGraphicsUtils::fillDataArray(bufferData, data, description, 3); + break; + } + + case GL_UNSIGNED_INT_VEC4: { + const GLuint *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4); + QGraphicsUtils::fillDataArray(bufferData, data, description, 4); + break; + } + + case GL_BOOL: { + const GLboolean *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 1); + QGraphicsUtils::fillDataArray(bufferData, data, description, 1); + break; + } + + case GL_BOOL_VEC2: { + const GLboolean *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 2); + QGraphicsUtils::fillDataArray(bufferData, data, description, 2); + break; + } + + case GL_BOOL_VEC3: { + const GLboolean *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 3); + QGraphicsUtils::fillDataArray(bufferData, data, description, 3); + break; + } + + case GL_BOOL_VEC4: { + const GLboolean *data = QGraphicsUtils::valueArrayFromVariant(v, description.m_size, 4); + QGraphicsUtils::fillDataArray(bufferData, data, description, 4); + break; + } + + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_RECT_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: { + Q_ASSERT(description.m_size == 1); + int value = v.toInt(); + QGraphicsUtils::fillDataArray(bufferData, &value, description, 1); + break; + } + + default: + qWarning() << Q_FUNC_INFO << "unsupported uniform type:" << description.m_type << "for " << description.m_name; + break; + } +} + +uint QGraphicsHelperGL4::uniformByteSize(const ShaderUniform &description) +{ + uint rawByteSize = 0; + int arrayStride = qMax(description.m_arrayStride, 0); + int matrixStride = qMax(description.m_matrixStride, 0); + + switch (description.m_type) { + + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + rawByteSize = 8; + break; + + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + rawByteSize = 12; + break; + + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + rawByteSize = 16; + break; + + case GL_FLOAT_MAT2: + rawByteSize = matrixStride ? 2 * matrixStride : 16; + break; + + case GL_FLOAT_MAT2x4: + rawByteSize = matrixStride ? 2 * matrixStride : 32; + break; + + case GL_FLOAT_MAT4x2: + rawByteSize = matrixStride ? 4 * matrixStride : 32; + break; + + case GL_FLOAT_MAT3: + rawByteSize = matrixStride ? 3 * matrixStride : 36; + break; + + case GL_FLOAT_MAT2x3: + rawByteSize = matrixStride ? 2 * matrixStride : 24; + break; + + case GL_FLOAT_MAT3x2: + rawByteSize = matrixStride ? 3 * matrixStride : 24; + break; + + case GL_FLOAT_MAT4: + rawByteSize = matrixStride ? 4 * matrixStride : 64; + break; + + case GL_FLOAT_MAT4x3: + rawByteSize = matrixStride ? 4 * matrixStride : 48; + break; + + case GL_FLOAT_MAT3x4: + rawByteSize = matrixStride ? 3 * matrixStride : 48; + break; + + case GL_BOOL: + rawByteSize = 1; + break; + + case GL_BOOL_VEC2: + rawByteSize = 2; + break; + + case GL_BOOL_VEC3: + rawByteSize = 3; + break; + + case GL_BOOL_VEC4: + rawByteSize = 4; + break; + + case GL_INT: + case GL_FLOAT: + case GL_UNSIGNED_INT: + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_RECT_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + rawByteSize = 4; + break; + } + + return arrayStride ? rawByteSize * arrayStride : rawByteSize; +} + +void QGraphicsHelperGL4::enableClipPlane(int clipPlane) +{ + m_funcs->glEnable(GL_CLIP_DISTANCE0 + clipPlane); +} + +void QGraphicsHelperGL4::disableClipPlane(int clipPlane) +{ + m_funcs->glDisable(GL_CLIP_DISTANCE0 + clipPlane); +} + +GLint QGraphicsHelperGL4::maxClipPlaneCount() +{ + GLint max = 0; + m_funcs->glGetIntegerv(GL_MAX_CLIP_DISTANCES, &max); + return max; +} + +} // Render +} // Qt3D + +QT_END_NAMESPACE + +#endif // !QT_OPENGL_ES_2 diff --git a/src/render/backend/qgraphicshelpergl4_p.h b/src/render/backend/qgraphicshelpergl4_p.h new file mode 100644 index 000000000..0c2f82f3c --- /dev/null +++ b/src/render/backend/qgraphicshelpergl4_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3D_RENDER_QGRAPHICSHELPERGL4_H +#define QT3D_RENDER_QGRAPHICSHELPERGL4_H + +#include +#include + +#ifndef QT_OPENGL_ES_2 + +QT_BEGIN_NAMESPACE + +class QOpenGLFunctions_4_3_Core; + +namespace Qt3D { +namespace Render { + +class QGraphicsHelperGL4 : public QGraphicsHelperInterface +{ +public: + QGraphicsHelperGL4(); + + // QGraphicHelperInterface interface + void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE; + void drawElementsInstanced(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) Q_DECL_OVERRIDE; + void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE; + void drawElements(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLint baseVertex = 0) Q_DECL_OVERRIDE; + void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE; + void setVerticesPerPatch(GLint verticesPerPatch) Q_DECL_OVERRIDE; + void useProgram(GLuint programId) Q_DECL_OVERRIDE; + QVector programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE; + QVector programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE; + QVector programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE; + void vertexAttribDivisor(GLuint index, GLuint divisor) Q_DECL_OVERRIDE; + void blendEquation(GLenum mode) Q_DECL_OVERRIDE; + void alphaTest(GLenum mode1, GLenum mode2) Q_DECL_OVERRIDE; + void depthTest(GLenum mode) Q_DECL_OVERRIDE; + void depthMask(GLenum mode) Q_DECL_OVERRIDE; + void cullFace(GLenum mode) Q_DECL_OVERRIDE; + void frontFace(GLenum mode) Q_DECL_OVERRIDE; + void enableAlphaCoverage() Q_DECL_OVERRIDE; + void disableAlphaCoverage() Q_DECL_OVERRIDE; + GLuint createFrameBufferObject() Q_DECL_OVERRIDE; + void releaseFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + GLuint boundFrameBufferObject() Q_DECL_OVERRIDE; + bool checkFrameBufferComplete() Q_DECL_OVERRIDE; + void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; + bool supportsFeature(Feature feature) const Q_DECL_OVERRIDE; + void drawBuffers(GLsizei n, const int *bufs) Q_DECL_OVERRIDE; + void bindFragDataLocation(GLuint shader, const QHash &outputs) Q_DECL_OVERRIDE; + void bindUniform(const QVariant &v, const ShaderUniform &description) Q_DECL_OVERRIDE; + void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; + void bindBufferBase(GLenum target, GLuint bindingIndex, GLuint buffer) Q_DECL_OVERRIDE; + void buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) Q_DECL_OVERRIDE; + uint uniformByteSize(const ShaderUniform &description) Q_DECL_OVERRIDE; + void enableClipPlane(int clipPlane) Q_DECL_OVERRIDE; + void disableClipPlane(int clipPlane) Q_DECL_OVERRIDE; + GLint maxClipPlaneCount() Q_DECL_OVERRIDE; + +private: + QOpenGLFunctions_4_3_Core *m_funcs; +}; + +} // Render +} // Qt3D + +QT_END_NAMESPACE + +#endif // !QT_OPENGL_ES_2 + +#endif // QT3D_RENDER_QGRAPHICSHELPERGL4_H diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index 0f57db809..316e33e27 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -19,6 +19,7 @@ HEADERS += \ $$PWD/states/blendstate_p.h \ $$PWD/genericstate_p.h \ $$PWD/qgraphicshelperinterface_p.h \ + $$PWD/qgraphicshelpergl4_p.h \ $$PWD/qgraphicshelpergl3_p.h \ $$PWD/qgraphicshelperes2_p.h \ $$PWD/qgraphicshelpergl2_p.h \ @@ -72,6 +73,7 @@ SOURCES += \ $$PWD/quniformvalue.cpp \ $$PWD/rendertexture.cpp \ $$PWD/states/blendstate.cpp \ + $$PWD/qgraphicshelpergl4.cpp \ $$PWD/qgraphicshelpergl3.cpp \ $$PWD/qgraphicshelperes2.cpp \ $$PWD/qgraphicshelpergl2.cpp \ -- cgit v1.2.3