diff options
author | Mike Krus <mike.krus@kdab.com> | 2020-02-07 18:08:29 +0000 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2020-02-07 18:10:43 +0000 |
commit | b0eb152b82cdd9658154ff7d9ef9e764eccc1ebd (patch) | |
tree | d754ad4412d5c1d26caedd54f2455f3e27cbbd46 /tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp | |
parent | 137b0cbbc746eecc6dd6a93f9a268f8d42c96bcc (diff) | |
parent | fa6799f63f3211300705b814b97716ca689d4bfa (diff) |
Merge remote-tracking branch 5.15 into dev
Change-Id: I731aa986e1cc45b3af920db1a23f256927beecf7
Diffstat (limited to 'tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp')
-rw-r--r-- | tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp | 2394 |
1 files changed, 2394 insertions, 0 deletions
diff --git a/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp new file mode 100644 index 000000000..b463e6236 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -0,0 +1,2394 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/qrendertargetoutput.h> +#include <Qt3DRender/private/uniform_p.h> +#include <Qt3DRender/private/attachmentpack_p.h> +#include <graphicshelpergl3_3_p.h> +#include <QOpenGLBuffer> +#include <QOpenGLFunctions_3_3_Core> +#include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> + +#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) + +#define TEST_SHOULD_BE_PERFORMED 1 + +using namespace Qt3DRender; +using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::OpenGL; + +namespace { + +const QByteArray vertCode = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "out vec2 texCoord;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "in int vertexColorIndex;\n" \ + "out vec2 texCoord;\n" \ + "flat out int colorIndex;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " colorIndex = vertexColorIndex;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeFragOutputs = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "out vec2 temp;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ + " temp = vec2(1.0, 0.3);\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "uniform float multiplier;\n" \ + "uniform vec2 multiplierVec2;\n" \ + "uniform vec3 multiplierVec3;\n" \ + "uniform vec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsInt = QByteArrayLiteral( + "#version 330 core\n" \ + "out ivec4 color;\n" \ + "uniform int multiplier;\n" \ + "uniform ivec2 multiplierVec2;\n" \ + "uniform ivec3 multiplierVec3;\n" \ + "uniform ivec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ + " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( + "#version 330 core\n" \ + "out uvec4 color;\n" \ + "uniform uint multiplier;\n" \ + "uniform uvec2 multiplierVec2;\n" \ + "uniform uvec3 multiplierVec3;\n" \ + "uniform uvec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ + " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "uniform mat2 m2;\n" \ + "uniform mat2x3 m23;\n" \ + "uniform mat3x2 m32;\n" \ + "uniform mat2x4 m24;\n" \ + "uniform mat4x2 m42;\n" \ + "uniform mat3 m3;\n" \ + "uniform mat3x4 m34;\n" \ + "uniform mat4x3 m43;\n" \ + "uniform mat4 m4;\n" \ + "void main()\n" \ + "{\n" \ + " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ + " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ + "}\n"); + +const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ + "flat in int colorIndex;\n" \ + "uniform ColorArray\n" \ + "{\n" \ + " vec4 colors[256];\n" \ + "};\n" \ + "void main()\n" \ + "{\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeSamplers = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec2 texCoord;\n" \ + "out vec4 color;\n" \ + "uniform sampler1D s1;\n" \ + "uniform sampler2D s2;\n" \ + "uniform sampler2DArray s2a;\n" \ + "uniform sampler3D s3;\n" \ + "uniform samplerCube scube;\n" \ + "uniform sampler2DRect srect;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1, 0, 0, 1) *" \ + " texture(s1, texCoord.x) *" \ + " texture(s2, texCoord) *" \ + " texture(s2a, vec3(texCoord, 0.0)) *" \ + " texture(s3, vec3(texCoord, 0.0)) *" \ + " texture(scube, vec3(texCoord, 0)) *" \ + " texture(srect, texCoord);\n" \ + "}\n"); + +} // anonymous + +class tst_GraphicsHelperGL3_3 : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void init() + { + m_window.reset(new QWindow); + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + + QSurfaceFormat format; + format.setVersion(3, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + m_window->setFormat(format); + m_glContext.setFormat(format); + + m_window->create(); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to maed OpenGL context current"; + return; + } + + if ((m_func = m_glContext.versionFunctions<QOpenGLFunctions_3_3_Core>()) != nullptr) { + m_glHelper.initializeHelper(&m_glContext, m_func); + m_initializationSuccessful = true; + } + } + + void cleanup() + { + m_glContext.doneCurrent(); + } + + void alphaTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Deprecated + } + + void bindBufferBase() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint bufferId = 0; + // WHEN + m_func->glGenBuffers(1, &bufferId); + // THEN + QVERIFY(bufferId != 0); + + + // WHEN + m_func->glBindBuffer(GL_UNIFORM_BUFFER, bufferId); + m_glHelper.bindBufferBase(GL_UNIFORM_BUFFER, 2, bufferId); + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundToPointBufferId = 0; + m_func->glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, 2, &boundToPointBufferId); + QVERIFY(boundToPointBufferId == GLint(bufferId)); + + // Restore to sane state + m_func->glBindBuffer(GL_UNIFORM_BUFFER, 0); + m_func->glDeleteBuffers(1, &bufferId); + } + + void bindFragDataLocation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // WHEN + QHash<QString, int> fragLocations; + fragLocations.insert(QStringLiteral("temp"), 2); + fragLocations.insert(QStringLiteral("color"), 1); + m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); + + // THEN + QVERIFY(shaderProgram.link()); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); + const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); + QCOMPARE(tempLocation, 2); + QCOMPARE(colorLocation, 1); + } + + void bindFrameBufferAttachment() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + { + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + GLint maxAttachmentsCount = 0; + m_func->glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachmentsCount); + + // THEN + QVERIFY(fboId != 0); + QVERIFY(maxAttachmentsCount >= 3); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QCOMPARE(int(status), GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureAttachmentId = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &textureAttachmentId); + QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + { // Check All Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_TRUE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { // Check Specific Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureFace = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + &textureFace); + QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_FALSE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + } + } + + void bindFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundindFBOId = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // Cleanup + m_func->glDeleteFramebuffers(1, &fboId); + } + + void bindShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Not supported in OpenGL 3.3 + } + + void bindUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void blendEquation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLint equation = 0; + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_ADD); + + // WHEN + m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); + + // THEN + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); + } + + void blendFunci() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Not supported by OpenGL 3.3 + } + + void blendFuncSeparatei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Not supported by OpenGL 3.3 + } + + void boundFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + // THEN + GLint boundBuffer = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); + QCOMPARE(GLuint(boundBuffer), fboId); + + // THEN + QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); + + // Reset state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void checkFrameBufferComplete() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + QVERIFY(m_glHelper.checkFrameBufferComplete()); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void clearBufferf() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + // Create 4 attachments + QOpenGLTexture *textures[4]; + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // Set Draw buffers + GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; + m_func->glDrawBuffers(1, &clearBufferEnum); + + const GLint bufferIndex = 0; // index of the element in the draw buffers + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // WHEN + const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); + m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast<const float *>(&clearValue1)); + error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + QVector<QVector4D> colors(512 * 512); + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + + for (const QVector4D c : colors) { + QVERIFY(c == clearValue1); + } + + // WHEN + const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); + m_glHelper.clearBufferf(bufferIndex, clearValue2); + + // THEN + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + for (const QVector4D c : colors) { + QVERIFY(c == clearValue2); + } + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void createFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // WHEN + const GLuint fboId = m_glHelper.createFrameBufferObject(); + + // THEN + QVERIFY(fboId != 0); + + // Restore + m_func->glDeleteFramebuffers(1, &fboId); + } + + void depthMask() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLboolean depthWritingEnabled = false; + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + + // THEN + QVERIFY(depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_FALSE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(!depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_TRUE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(depthWritingEnabled); + } + + void depthTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_DEPTH_TEST); + m_func->glDepthFunc(GL_LESS); + + // WHEN + m_glHelper.depthTest(GL_LEQUAL); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + GLint depthMode = 0; + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LEQUAL); + + // WHEN + m_glHelper.depthTest(GL_LESS); + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LESS); + } + + void disableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_CLIP_DISTANCE0 + 5); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + + // WHEN + m_glHelper.disableClipPlane(5); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + } + + void disablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnablei(GL_BLEND, 2); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); + + // WHEN + m_glHelper.disablei(GL_BLEND, 2); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); + } + + void disablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.disablePrimitiveRestart(); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + } + + void drawBuffers() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + QOpenGLTexture *textures[4]; + + // Create 4 attachments + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // WHEN + GLenum bufferEnum = GL_COLOR_ATTACHMENT4; + m_func->glDrawBuffers(1, &bufferEnum); + + // THEN + GLint enumValue = -1; + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); + + // WHEN + GLint newBufferEnum = 2; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // WHEN + newBufferEnum = 0; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void enableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_CLIP_DISTANCE0 + 4); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + + // WHEN + m_glHelper.enableClipPlane(4); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + } + + void enablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisablei(GL_BLEND, 4); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); + + // WHEN + m_glHelper.enablei(GL_BLEND, 4); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); + } + + void enablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.enablePrimitiveRestart(883); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + GLint restartIndex = 0; + m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); + QCOMPARE(restartIndex, 883); + + // Restore + m_func->glDisable(GL_PRIMITIVE_RESTART); + } + + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void frontFace() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glFrontFace(GL_CW); + + // THEN + GLint face = 0; + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CW); + + // WHEN + m_glHelper.frontFace(GL_CCW); + + // THEN + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CCW); + } + + void getRenderBufferDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint renderBufferId = 0; + m_func->glGenRenderbuffers(1, &renderBufferId); + QVERIFY(renderBufferId != 0); + + // WHEN + m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); + m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); + m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); + const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + + // Restore + m_func->glDeleteRenderbuffers(1, &renderBufferId); + } + + void getTextureDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // WHEN + const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + } + + void pointSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PROGRAM_POINT_SIZE); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + GLfloat size = 0; + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 1.0f); + + // WHEN + m_glHelper.pointSize(false, 0.5f); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 0.5f); + } + + void maxClipPlaneCount() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLint maxCount = -1; + m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); + + // THEN + QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); + } + + void programUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector<ShaderUniformBlock> activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniformBlocks.size(), 1); + const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); + + QCOMPARE(uniformBlock.m_activeUniformsCount, 1); + QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); + + GLint blockIndex = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + GLint blockBinding = -1; + m_func->glGetActiveUniformBlockiv(shaderProgram.programId(), blockIndex, GL_UNIFORM_BLOCK_BINDING, &blockBinding); + QCOMPARE(blockIndex, uniformBlock.m_index); + QCOMPARE(blockBinding, uniformBlock.m_binding); + } + + void programAttributesAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector<ShaderAttribute> activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeAttributes.size(), 2); + std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); + + const ShaderAttribute attribute1 = activeAttributes.at(0); + QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); + QCOMPARE(attribute1.m_size, 1); + QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); + QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); + + const ShaderAttribute attribute2 = activeAttributes.at(1); + QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); + QCOMPARE(attribute2.m_size, 1); + QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); + QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); + } + + void programUniformsAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniforms.size(), 4); + std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); + + const ShaderUniform uniform1 = activeUniforms.at(0); + QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); + QCOMPARE(uniform1.m_offset, -1); + QCOMPARE(uniform1.m_blockIndex, -1); + QCOMPARE(uniform1.m_arrayStride, -1); + QCOMPARE(uniform1.m_matrixStride, -1); + QCOMPARE(uniform1.m_size, 1); + QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); + QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); + + const ShaderUniform uniform2 = activeUniforms.at(1); + QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); + QCOMPARE(uniform2.m_offset, -1); + QCOMPARE(uniform2.m_blockIndex, -1); + QCOMPARE(uniform2.m_arrayStride, -1); + QCOMPARE(uniform2.m_matrixStride, -1); + QCOMPARE(uniform2.m_size, 1); + QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); + QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); + + const ShaderUniform uniform3 = activeUniforms.at(2); + QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); + QCOMPARE(uniform3.m_offset, -1); + QCOMPARE(uniform3.m_blockIndex, -1); + QCOMPARE(uniform3.m_arrayStride, -1); + QCOMPARE(uniform3.m_matrixStride, -1); + QCOMPARE(uniform3.m_size, 1); + QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); + QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); + + const ShaderUniform uniform4 = activeUniforms.at(3); + QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); + QCOMPARE(uniform4.m_offset, -1); + QCOMPARE(uniform4.m_blockIndex, -1); + QCOMPARE(uniform4.m_arrayStride, -1); + QCOMPARE(uniform4.m_matrixStride, -1); + QCOMPARE(uniform4.m_size, 1); + QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); + QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); + } + + void programShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Not supported in 3.3 + } + + void releaseFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.releaseFrameBufferObject(fboId); + + // THEN + QVERIFY(!m_func->glIsFramebuffer(fboId)); + } + + void setMSAAEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_MULTISAMPLE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + } + + void setAlphaCoverageEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + } + + void setClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Deprecated in 3.3 core + } + + void setSeamlessCubemap() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + + void setVerticesPerPatch() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + +#define SUPPORTS_FEATURE(Feature, IsSupported) \ + QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); + + void supportsFeature() + { + SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); + // Tesselation could be true or false depending on extensions so not tested + SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, true); + } + + +#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ + QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; + + void uniformsByteSize_data() + { + QTest::addColumn<QByteArray>("fragShader"); + QTest::addColumn<QString>("name"); + QTest::addColumn<int>("type"); + QTest::addColumn<int>("componentSize"); + QTest::addColumn<int>("expectedByteSize"); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplier", GL_UNSIGNED_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec2", GL_UNSIGNED_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec3", GL_UNSIGNED_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec4", GL_UNSIGNED_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2a", GL_SAMPLER_2D_ARRAY, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "srect", GL_SAMPLER_2D_RECT, 1, 4); + } + + void uniformsByteSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QFETCH(QByteArray, fragShader); + QFETCH(QString, name); + QFETCH(int, type); + QFETCH(int, componentSize); + QFETCH(int, expectedByteSize); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); + QVERIFY(shaderProgram.link()); + + GLint location = shaderProgram.uniformLocation(name); + // WHEN + const QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + ShaderUniform matchingUniform; + for (const ShaderUniform &u : activeUniforms) { + if (u.m_location == location) { + matchingUniform = u; + break; + } + } + + + // THEN + QCOMPARE(matchingUniform.m_location, location); + QCOMPARE(matchingUniform.m_type, GLuint(type)); + QCOMPARE(matchingUniform.m_size, componentSize); + + // WHEN + const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); + + // THEN + QCOMPARE(expectedByteSize, computedRawByteSize); + + // Restore + m_func->glUseProgram(0); + } + + + void useProgram() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // THEN + QVERIFY(shaderProgram.link()); + + GLint currentProg = 0; + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + + // WHEN + m_glHelper.useProgram(shaderProgram.programId()); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QCOMPARE(GLuint(currentProg), shaderProgram.programId()); + + // WHEN + m_glHelper.useProgram(0); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + } + + void vertexAttribDivisor() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + } + + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void glUniform1fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat value = 883.0f; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1fv(location, 1, &value); + + // THEN + GLfloat setValue = 0.0f; + m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[2] = { 383.0f, 427.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2fv(location, 1, values); + + // THEN + GLfloat setValues[2] = { 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3fv(location, 1, values); + + // THEN + GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint value = 883; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1iv(location, 1, &value); + + // THEN + GLint setValue = 0; + m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[2] = { 383, 427 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2iv(location, 1, values); + + // THEN + GLint setValues[2] = { 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[3] = { 572, 1340, 1584 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3iv(location, 1, values); + + // THEN + GLint setValues[3] = { 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[4] = { 454, 350, 883, 355 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4iv(location, 1, values); + + // THEN + GLint setValues[4] = { 0, 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint value = 883U; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1uiv(location, 1, &value); + + // THEN + GLuint setValue = 0U; + m_func->glGetUniformuiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[2] = { 383U, 427U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2uiv(location, 1, values); + + // THEN + GLuint setValues[2] = { 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[3] = { 572U, 1340U, 1584U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3uiv(location, 1, values); + + // THEN + GLuint setValues[3] = { 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[4] = { 454U, 350U, 883U, 355U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4uiv(location, 1, values); + + // THEN + GLuint setValues[4] = { 0U, 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("m2"); + m_glHelper.glUniformMatrix2fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; + const GLint location = shaderProgram.uniformLocation("m3"); + m_glHelper.glUniformMatrix3fv(location, 1, values); + + // THEN + GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 9; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; + const GLint location = shaderProgram.uniformLocation("m4"); + m_glHelper.glUniformMatrix4fv(location, 1, values); + + // THEN + GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 16; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m23"); + m_glHelper.glUniformMatrix2x3fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m32"); + m_glHelper.glUniformMatrix3x2fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m24"); + m_glHelper.glUniformMatrix2x4fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m42"); + m_glHelper.glUniformMatrix4x2fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f}; + const GLint location = shaderProgram.uniformLocation("m34"); + m_glHelper.glUniformMatrix3x4fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m43"); + m_glHelper.glUniformMatrix4x3fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + + void blitFramebuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + GLint maxSamples; + m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples < 1) + QSKIP("This test requires an implementation that supports multisampled textures"); + + // GIVEN + GLuint fbos[2]; + GLuint fboTextures[2]; + + m_func->glGenFramebuffers(2, fbos); + m_func->glGenTextures(2, fboTextures); + + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + + m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); + m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + m_func->glBindTexture(GL_TEXTURE_2D, 0); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); + + GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); + + status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); + + m_func->glEnable(GL_MULTISAMPLE); + m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); + m_func->glClear(GL_COLOR_BUFFER_BIT); + m_func->glDisable(GL_MULTISAMPLE); + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); + + // WHEN + m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + + GLuint result[10*10]; + m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); + + // THEN + GLuint v = (0.2f) * 255; + v = v | (v<<8) | (v<<16) | (v<<24); + for (GLuint value : result) { + QCOMPARE(value, v); + } + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + m_func->glDeleteFramebuffers(2, fbos); + m_func->glDeleteTextures(2, fboTextures); + } + +#define ADD_GL_TYPE_ENTRY(Type, Expected) \ + QTest::newRow(#Type) << Type << Expected; + + void uniformTypeFromGLType_data() + { + QTest::addColumn<int>("glType"); + QTest::addColumn<UniformType>("expected"); + + ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); + ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); + ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); + ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); + ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); + } + + void uniformTypeFromGLType() + { + // GIVEN + QFETCH(int, glType); + QFETCH(UniformType, expected); + + // WHEN + UniformType computed = m_glHelper.uniformTypeFromGLType(glType); + + // THEN + QCOMPARE(computed, expected); + } + + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void fenceSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync()); + + // THEN + QVERIFY(sync != nullptr); + QCOMPARE(m_func->glIsSync(sync), GL_TRUE); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void clientWaitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + QElapsedTimer t; + t.start(); + + GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync()); + + m_glHelper.clientWaitSync(sync, 1000000); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + qDebug() << t.nsecsElapsed(); + } + + void waitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void wasSyncSignaled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // Shouldn't loop forever + while (!m_glHelper.wasSyncSignaled(sync)) + ; + } + + void deleteSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync()); + m_glHelper.clientWaitSync(sync, GLuint64(-1)); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); + + // WHEN + m_glHelper.deleteSync(sync); + + // THEN + QCOMPARE(m_func->glIsSync(sync), GL_FALSE); + } + + void rasterMode() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 functions not supported"); + + m_func->glGetError(); + m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_POLYGON_MODE, &p); + QCOMPARE(p, GL_LINE); + } + +private: + QScopedPointer<QWindow> m_window; + QOpenGLContext m_glContext; + GraphicsHelperGL3_3 m_glHelper; + QOpenGLFunctions_3_3_Core *m_func = nullptr; + bool m_initializationSuccessful = false; +}; + +#endif + +int main(int argc, char *argv[]) +{ +#ifdef TEST_SHOULD_BE_PERFORMED + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + tst_GraphicsHelperGL3_3 tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +#endif + return 0; +} + +#ifdef TEST_SHOULD_BE_PERFORMED +#include "tst_graphicshelpergl3_3.moc" +#endif |