1/****************************************************************************
2**
3** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QTest>
30#include <Qt3DRender/qrendertargetoutput.h>
31#include <Qt3DRender/private/uniform_p.h>
32#include <Qt3DRender/private/attachmentpack_p.h>
33#include <graphicshelpergl4_p.h>
34#include <QOpenGLBuffer>
35#include <QOpenGLFunctions_4_3_Core>
36#include <QOpenGLShaderProgram>
37#include <QOpenGLVertexArrayObject>
38#include <QSurfaceFormat>
39
40#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_4_3)
41
42#define TEST_SHOULD_BE_PERFORMED 1
43
44using namespace Qt3DRender;
45using namespace Qt3DRender::Render;
46using namespace Qt3DRender::Render::OpenGL;
47
48namespace {
49
50const QByteArray vertCode = QByteArrayLiteral(
51 "#version 430 core\n" \
52 "layout(location = 1) in vec3 vertexPosition;\n" \
53 "layout(location = 2) in vec2 vertexTexCoord;\n" \
54 "out vec2 texCoord;\n" \
55 "void main()\n" \
56 "{\n" \
57 " texCoord = vertexTexCoord;\n" \
58 " gl_Position = vec4(vertexPosition, 1.0);\n" \
59 "}\n");
60
61const QByteArray vertCodeUniformBuffer = QByteArrayLiteral(
62 "#version 430 core\n" \
63 "layout(location = 1) in vec3 vertexPosition;\n" \
64 "layout(location = 2) in vec2 vertexTexCoord;\n" \
65 "layout(location = 3) in int vertexColorIndex;\n" \
66 "layout(location = 4) in double vertexTexCoordScale;\n" \
67 "out vec2 texCoord;\n" \
68 "flat out int colorIndex;\n" \
69 "void main()\n" \
70 "{\n" \
71 " texCoord = vec2(vertexTexCoordScale * vertexTexCoord);\n" \
72 " colorIndex = vertexColorIndex;\n" \
73 " gl_Position = vec4(vertexPosition, 1.0);\n" \
74 "}\n");
75
76const QByteArray fragCodeFragOutputs = QByteArrayLiteral(
77 "#version 430 core\n" \
78 "out vec4 color;\n" \
79 "out vec2 temp;\n" \
80 "void main()\n" \
81 "{\n" \
82 " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \
83 " temp = vec2(1.0, 0.3);\n" \
84 "}\n");
85
86const QByteArray fragCodeUniformsFloat = QByteArrayLiteral(
87 "#version 430 core\n" \
88 "out vec4 color;\n" \
89 "layout(location = 1) uniform float multiplier;\n" \
90 "layout(location = 2) uniform vec2 multiplierVec2;\n" \
91 "layout(location = 3) uniform vec3 multiplierVec3;\n" \
92 "layout(location = 4) uniform vec4 multiplierVec4;\n" \
93 "void main()\n" \
94 "{\n" \
95 " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \
96 " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \
97 "}\n");
98
99const QByteArray fragCodeUniformsInt = QByteArrayLiteral(
100 "#version 430 core\n" \
101 "out ivec4 color;\n" \
102 "layout(location = 1) uniform int multiplier;\n" \
103 "layout(location = 2) uniform ivec2 multiplierVec2;\n" \
104 "layout(location = 3) uniform ivec3 multiplierVec3;\n" \
105 "layout(location = 4) uniform ivec4 multiplierVec4;\n" \
106 "void main()\n" \
107 "{\n" \
108 " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \
109 " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \
110 "}\n");
111
112const QByteArray fragCodeUniformsUInt = QByteArrayLiteral(
113 "#version 430 core\n" \
114 "out uvec4 color;\n" \
115 "layout(location = 1) uniform uint multiplier;\n" \
116 "layout(location = 2) uniform uvec2 multiplierVec2;\n" \
117 "layout(location = 3) uniform uvec3 multiplierVec3;\n" \
118 "layout(location = 4) uniform uvec4 multiplierVec4;\n" \
119 "void main()\n" \
120 "{\n" \
121 " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \
122 " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \
123 "}\n");
124
125const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral(
126 "#version 430 core\n" \
127 "out vec4 color;\n" \
128 "layout(location = 1) uniform mat2 m2;\n" \
129 "layout(location = 2) uniform mat2x3 m23;\n" \
130 "layout(location = 3) uniform mat3x2 m32;\n" \
131 "layout(location = 4) uniform mat2x4 m24;\n" \
132 "layout(location = 5) uniform mat4x2 m42;\n" \
133 "layout(location = 6) uniform mat3 m3;\n" \
134 "layout(location = 7) uniform mat3x4 m34;\n" \
135 "layout(location = 8) uniform mat4x3 m43;\n" \
136 "layout(location = 9) uniform mat4 m4;\n" \
137 "void main()\n" \
138 "{\n" \
139 " 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" \
140 " color = vec4(1, 0, 0, 1) * lengthSum;\n" \
141 "}\n");
142
143const QByteArray fragCodeUniformBuffer = QByteArrayLiteral(
144 "#version 430 core\n" \
145 "out vec4 color;\n" \
146 "in vec2 texCoord;\n" \
147 "flat in int colorIndex;\n" \
148 "layout(binding = 2, std140) uniform ColorArray\n" \
149 "{\n" \
150 " vec4 colors[256];\n" \
151 "};\n" \
152 "void main()\n" \
153 "{\n" \
154 " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \
155 "}\n");
156
157const QByteArray fragCodeSamplers = QByteArrayLiteral(
158 "#version 430 core\n" \
159 "in vec2 texCoord;\n" \
160 "out vec4 color;\n" \
161 "layout(location = 1) uniform sampler1D s1;\n" \
162 "layout(location = 2) uniform sampler2D s2;\n" \
163 "layout(location = 3) uniform sampler2DArray s2a;\n" \
164 "layout(location = 4) uniform sampler3D s3;\n" \
165 "layout(location = 5) uniform samplerCube scube;\n" \
166 "layout(location = 6) uniform sampler2DRect srect;\n" \
167 "void main()\n" \
168 "{\n" \
169 " color = vec4(1, 0, 0, 1) *" \
170 " texture(s1, texCoord.x) *" \
171 " texture(s2, texCoord) *" \
172 " texture(s2a, vec3(texCoord, 0.0)) *" \
173 " texture(s3, vec3(texCoord, 0.0)) *" \
174 " texture(scube, vec3(texCoord, 0)) *" \
175 " texture(srect, texCoord);\n" \
176 "}\n");
177
178const QByteArray fragCodeImages = QByteArrayLiteral(
179 "#version 430 core\n" \
180 "in vec2 texCoord;\n" \
181 "out vec4 color;\n" \
182 "layout(location = 1, rgba32f) readonly uniform image1D s1;\n" \
183 "layout(location = 2, rg16f) readonly uniform image2D s2;\n" \
184 "layout(location = 3, r16f) readonly uniform image2DArray s2a;\n" \
185 "layout(location = 4, rg8) readonly uniform image3D s3;\n" \
186 "layout(location = 5, rgba16_snorm) readonly uniform imageCube scube;\n" \
187 "layout(location = 6, rg16) readonly uniform image2DRect srect;\n" \
188 "void main()\n" \
189 "{\n" \
190 " ivec2 coords = ivec2(texCoord);\n"\
191 " color = vec4(1, 0, 0, 1) *" \
192 " imageLoad(s1, coords.x) *" \
193 " imageLoad(s2, coords) *" \
194 " imageLoad(s2a, ivec3(coords, 0)) *" \
195 " imageLoad(s3, ivec3(coords, 0)) *" \
196 " imageLoad(scube, ivec3(coords, 0)) *" \
197 " imageLoad(srect, coords);\n" \
198 "}\n");
199
200const QByteArray computeShader = QByteArrayLiteral(
201 "#version 430 core\n" \
202 "uniform float particleStep;\n" \
203 "uniform float finalCollisionFactor;\n" \
204 "layout (local_size_x = 1024) in;\n" \
205 "struct ParticleData\n" \
206 "{\n" \
207 " vec4 position;\n" \
208 " vec4 direction;\n" \
209 " vec4 color;\n" \
210 "};\n" \
211 "layout (std140, binding = 6) coherent buffer Particles\n" \
212 "{\n" \
213 " ParticleData particles[];\n" \
214 "} data;\n" \
215 "void main(void)\n" \
216 "{\n" \
217 " uint globalId = gl_GlobalInvocationID.x;\n" \
218 " ParticleData currentParticle = data.particles[globalId];\n" \
219 " currentParticle.position = currentParticle.position + currentParticle.direction * particleStep;\n" \
220 " vec4 acceleration = normalize(vec4(0.0) - currentParticle.position) * finalCollisionFactor;\n" \
221 " currentParticle.direction = currentParticle.direction + acceleration * particleStep;\n" \
222 " data.particles[globalId] = currentParticle;\n" \
223 "}");
224
225} // anonymous
226
227class tst_GraphicsHelperGL4 : public QObject
228{
229 Q_OBJECT
230private Q_SLOTS:
231 void init()
232 {
233 m_window.reset(other: new QWindow);
234 m_window->setSurfaceType(QWindow::OpenGLSurface);
235 m_window->setGeometry(posx: 0, posy: 0, w: 10, h: 10);
236
237 QSurfaceFormat format;
238 format.setVersion(major: 4, minor: 3);
239 format.setProfile(QSurfaceFormat::CoreProfile);
240 format.setDepthBufferSize(24);
241 format.setSamples(4);
242 format.setStencilBufferSize(8);
243 m_window->setFormat(format);
244 m_glContext.setFormat(format);
245
246 m_window->create();
247
248 if (!m_glContext.create()) {
249 qWarning() << "Failed to create OpenGL context";
250 return;
251 }
252
253 if (!m_glContext.makeCurrent(surface: m_window.data())) {
254 qWarning() << "Failed to make OpenGL context current";
255 return;
256 }
257
258 if ((m_func = m_glContext.versionFunctions<QOpenGLFunctions_4_3_Core>()) != nullptr) {
259 m_glHelper.initializeHelper(context: &m_glContext, functions: m_func);
260 m_initializationSuccessful = true;
261 }
262 }
263
264 void cleanup()
265 {
266 m_glContext.doneCurrent();
267 }
268
269 void alphaTest()
270 {
271 if (!m_initializationSuccessful)
272 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
273 // Deprecated
274 }
275
276 void bindBufferBase()
277 {
278 if (!m_initializationSuccessful)
279 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
280
281 // GIVEN
282 GLuint bufferId = 0;
283 // WHEN
284 m_func->glGenBuffers(n: 1, buffers: &bufferId);
285 // THEN
286 QVERIFY(bufferId != 0);
287
288
289 // WHEN
290 m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer: bufferId);
291 m_glHelper.bindBufferBase(GL_SHADER_STORAGE_BUFFER, index: 2, buffer: bufferId);
292 // THEN
293 const GLint error = m_func->glGetError();
294 QVERIFY(error == 0);
295 GLint boundToPointBufferId = 0;
296 m_func->glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, index: 2, data: &boundToPointBufferId);
297 QVERIFY(boundToPointBufferId == GLint(bufferId));
298
299 // Restore to sane state
300 m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer: 0);
301 m_func->glDeleteBuffers(n: 1, buffers: &bufferId);
302 }
303
304 void bindFragDataLocation()
305 {
306 if (!m_initializationSuccessful)
307 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
308
309 // GIVEN
310 QOpenGLShaderProgram shaderProgram;
311 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
312 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeFragOutputs);
313
314 // WHEN
315 QHash<QString, int> fragLocations;
316 fragLocations.insert(QStringLiteral("temp"), avalue: 2);
317 fragLocations.insert(QStringLiteral("color"), avalue: 1);
318 m_glHelper.bindFragDataLocation(shader: shaderProgram.programId(), outputs: fragLocations);
319
320 // THEN
321 QVERIFY(shaderProgram.link());
322 const GLint error = m_func->glGetError();
323 QVERIFY(error == 0);
324 const GLint tempLocation = m_func->glGetFragDataLocation(program: shaderProgram.programId(), name: "temp");
325 const GLint colorLocation = m_func->glGetFragDataLocation(program: shaderProgram.programId(), name: "color");
326 QCOMPARE(tempLocation, 2);
327 QCOMPARE(colorLocation, 1);
328 }
329
330 void bindFrameBufferAttachment()
331 {
332 if (!m_initializationSuccessful)
333 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
334
335 {
336 // GIVEN
337 GLuint fboId;
338 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
339
340 Attachment attachment;
341 attachment.m_point = QRenderTargetOutput::Color2;
342
343 // THEN
344 QVERIFY(fboId != 0);
345
346 // WHEN
347 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
348
349 QOpenGLTexture texture(QOpenGLTexture::Target2D);
350 texture.setSize(width: 512, height: 512);
351 texture.setFormat(QOpenGLTexture::RGBA32F);
352 texture.setMinificationFilter(QOpenGLTexture::Linear);
353 texture.setMagnificationFilter(QOpenGLTexture::Linear);
354 texture.setWrapMode(QOpenGLTexture::ClampToEdge);
355 if (!texture.create())
356 qWarning() << "Texture creation failed";
357 texture.allocateStorage();
358 QVERIFY(texture.isStorageAllocated());
359 GLint error = m_func->glGetError();
360 QVERIFY(error == 0);
361 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
362
363 // THEN
364 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
365 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
366
367 error = m_func->glGetError();
368 QVERIFY(error == 0);
369 GLint textureAttachmentId = 0;
370 m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER,
371 GL_COLOR_ATTACHMENT0 + 2,
372 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
373 params: &textureAttachmentId);
374 QCOMPARE(GLuint(textureAttachmentId), texture.textureId());
375
376 // Restore state
377 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
378 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
379 }
380 {
381 // GIVEN
382 QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap);
383 texture.setSize(width: 512, height: 512);
384 texture.setFormat(QOpenGLTexture::RGBA32F);
385 texture.setMinificationFilter(QOpenGLTexture::Linear);
386 texture.setMagnificationFilter(QOpenGLTexture::Linear);
387 texture.setWrapMode(QOpenGLTexture::ClampToEdge);
388 if (!texture.create())
389 qWarning() << "Texture creation failed";
390 texture.allocateStorage();
391 QVERIFY(texture.isStorageAllocated());
392 GLint error = m_func->glGetError();
393 QVERIFY(error == 0);
394
395 { // Check All Faces
396
397 // GIVEN
398 GLuint fboId;
399 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
400
401 // THEN
402 QVERIFY(fboId != 0);
403
404 // WHEN
405 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
406
407 Attachment attachment;
408 attachment.m_point = QRenderTargetOutput::Color0;
409 attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces;
410
411 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
412
413 // THEN
414 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
415 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
416
417 error = m_func->glGetError();
418 QVERIFY(error == 0);
419 GLint textureIsLayered = 0;
420 m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER,
421 GL_COLOR_ATTACHMENT0,
422 GL_FRAMEBUFFER_ATTACHMENT_LAYERED,
423 params: &textureIsLayered);
424 QCOMPARE(textureIsLayered, GL_TRUE);
425
426 // Restore state
427 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
428 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
429 }
430 { // Check Specific Faces
431
432 // GIVEN
433 GLuint fboId;
434 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
435
436 // THEN
437 QVERIFY(fboId != 0);
438
439 // WHEN
440 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
441
442 Attachment attachment;
443 attachment.m_point = QRenderTargetOutput::Color0;
444 attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ;
445
446 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
447
448 // THEN
449 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
450 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
451
452 error = m_func->glGetError();
453 QVERIFY(error == 0);
454 GLint textureFace = 0;
455 m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER,
456 GL_COLOR_ATTACHMENT0,
457 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
458 params: &textureFace);
459 QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
460 GLint textureIsLayered = 0;
461 m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER,
462 GL_COLOR_ATTACHMENT0,
463 GL_FRAMEBUFFER_ATTACHMENT_LAYERED,
464 params: &textureIsLayered);
465 QCOMPARE(textureIsLayered, GL_FALSE);
466
467 // Restore state
468 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
469 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
470 }
471 }
472
473 // TargetCubeMapArray
474 {
475 // GIVEN
476 QOpenGLTexture texture(QOpenGLTexture::TargetCubeMapArray);
477 texture.setSize(width: 512, height: 512);
478 texture.setFormat(QOpenGLTexture::RGBA32F);
479 texture.setMinificationFilter(QOpenGLTexture::Linear);
480 texture.setMagnificationFilter(QOpenGLTexture::Linear);
481 texture.setWrapMode(QOpenGLTexture::ClampToEdge);
482 texture.setLayers(4);
483 if (!texture.create())
484 qWarning() << "Texture creation failed";
485 texture.allocateStorage();
486 QVERIFY(texture.isStorageAllocated());
487 GLint error = m_func->glGetError();
488 QVERIFY(error == 0);
489
490 { // Check All Faces
491
492 // GIVEN
493 GLuint fboId;
494 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
495
496 // THEN
497 QVERIFY(fboId != 0);
498
499 // WHEN
500 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
501
502 Attachment attachment;
503 attachment.m_point = QRenderTargetOutput::Color0;
504 attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces;
505
506 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
507
508 // THEN
509 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
510 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
511
512 error = m_func->glGetError();
513 QVERIFY(error == 0);
514
515 // Texture should be layered and attached to layer 0 since CubeMapArray textures
516 // are bound to entire texture, not a specific layer
517 GLint textureIsLayered = 0;
518 m_func->glGetFramebufferAttachmentParameteriv(
519 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
520 GL_FRAMEBUFFER_ATTACHMENT_LAYERED, params: &textureIsLayered);
521 QCOMPARE(textureIsLayered, GL_TRUE);
522
523 GLint textureLayer = 0;
524 m_func->glGetFramebufferAttachmentParameteriv(
525 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
526 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, params: &textureLayer);
527 QCOMPARE(textureLayer, 0);
528
529 // Restore state
530 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
531 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
532 }
533 { // Check Specific Faces
534
535 // GIVEN
536 GLuint fboId;
537 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
538
539 // THEN
540 QVERIFY(fboId != 0);
541
542 // WHEN
543 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
544
545 Attachment attachment;
546 attachment.m_point = QRenderTargetOutput::Color0;
547 attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ;
548 attachment.m_layer = 1;
549
550 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
551
552 // THEN
553 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
554 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
555
556 error = m_func->glGetError();
557 QVERIFY(error == 0);
558
559 GLint textureIsLayered = 0;
560 m_func->glGetFramebufferAttachmentParameteriv(
561 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
562 GL_FRAMEBUFFER_ATTACHMENT_LAYERED, params: &textureIsLayered);
563 QCOMPARE(textureIsLayered, GL_FALSE);
564
565 GLint textureLayer = 0;
566 m_func->glGetFramebufferAttachmentParameteriv(
567 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
568 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, params: &textureLayer);
569 // actual layer should be 6 * layer + face
570 const auto faceNo =
571 attachment.m_face - Qt3DRender::QAbstractTexture::CubeMapPositiveX;
572 QCOMPARE(textureLayer, 6 * attachment.m_layer + faceNo);
573
574 // Restore state
575 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
576 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
577 }
578 }
579 }
580
581 void bindFrameBufferObject()
582 {
583 if (!m_initializationSuccessful)
584 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
585
586 // GIVEN
587 GLuint fboId;
588 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
589
590 // THEN
591 QVERIFY(fboId != 0);
592
593 // WHEN
594 m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBODraw);
595
596 // THEN
597 GLint error = m_func->glGetError();
598 QVERIFY(error == 0);
599 GLint boundindFBOId = 0;
600 m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, params: &boundindFBOId);
601 QVERIFY(GLuint(boundindFBOId) == fboId);
602
603 // WHEN
604 m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBORead);
605
606 // THEN
607 error = m_func->glGetError();
608 QVERIFY(error == 0);
609 boundindFBOId = 0;
610 m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, params: &boundindFBOId);
611 QVERIFY(GLuint(boundindFBOId) == fboId);
612
613 // WHEN
614 m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBOReadAndDraw);
615
616 // THEN
617 error = m_func->glGetError();
618 QVERIFY(error == 0);
619 boundindFBOId = 0;
620 m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, params: &boundindFBOId);
621 QVERIFY(GLuint(boundindFBOId) == fboId);
622
623 // Cleanup
624 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
625 }
626
627 void bindImageTexture()
628 {
629 if (!m_initializationSuccessful)
630 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
631
632 // GIVEN
633 QOpenGLTexture texture(QOpenGLTexture::Target2D);
634 texture.setSize(width: 512, height: 512);
635 texture.setFormat(QOpenGLTexture::RGBA8U);
636 texture.setMinificationFilter(QOpenGLTexture::Linear);
637 texture.setMagnificationFilter(QOpenGLTexture::Linear);
638 texture.create();
639 texture.allocateStorage();
640
641 // THEN
642 QVERIFY(texture.textureId() != 0 && texture.isCreated() && texture.isStorageAllocated());
643
644 // WHEN
645 m_glHelper.bindImageTexture(imageUnit: 0,
646 texture: texture.textureId(),
647 mipLevel: 0,
648 GL_FALSE,
649 layer: 0,
650 GL_READ_WRITE,
651 GL_RGBA8UI);
652
653 // THEN
654 GLint error = m_func->glGetError();
655 QVERIFY(error == 0);
656 }
657
658 void bindShaderStorageBlock()
659 {
660 if (!m_initializationSuccessful)
661 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
662
663 // GIVEN
664 QOpenGLShaderProgram shaderProgram;
665 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Compute, source: computeShader);
666 QVERIFY(shaderProgram.link());
667
668 // WHEN
669 GLint index = m_func->glGetProgramResourceIndex(program: shaderProgram.programId(),
670 GL_SHADER_STORAGE_BLOCK,
671 name: "Particles");
672 // THEN
673 GLint binding = -1;
674 GLenum prop = GL_BUFFER_BINDING;
675 m_func->glGetProgramResourceiv(program: shaderProgram.programId(),
676 GL_SHADER_STORAGE_BLOCK,
677 index,
678 propCount: 1, props: &prop,
679 bufSize: 4, NULL, params: &binding);
680 QCOMPARE(binding, 6);
681
682 // WHEN
683 m_glHelper.bindShaderStorageBlock(programId: shaderProgram.programId(), shaderStorageBlockIndex: index, shaderStorageBlockBinding: 1);
684
685 // THEN
686 const GLint error = m_func->glGetError();
687 QVERIFY(error == 0);
688
689 m_func->glGetProgramResourceiv(program: shaderProgram.programId(),
690 GL_SHADER_STORAGE_BLOCK,
691 index,
692 propCount: 1, props: &prop,
693 bufSize: 4, NULL, params: &binding);
694 QCOMPARE(binding, 1);
695 }
696
697 void bindUniformBlock()
698 {
699 if (!m_initializationSuccessful)
700 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
701
702 // GIVEN
703 QOpenGLShaderProgram shaderProgram;
704 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCodeUniformBuffer);
705 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformBuffer);
706 QVERIFY(shaderProgram.link());
707
708 // WHEN
709 GLint index = m_func->glGetUniformBlockIndex(program: shaderProgram.programId(), uniformBlockName: "ColorArray");
710 m_glHelper.bindUniformBlock(programId: shaderProgram.programId(), uniformBlockIndex: index, uniformBlockBinding: 1);
711
712 // THEN
713 const GLint error = m_func->glGetError();
714 QVERIFY(error == 0);
715 }
716
717 void blendEquation()
718 {
719 if (!m_initializationSuccessful)
720 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
721
722 // GIVEN
723 GLint equation = 0;
724 m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, params: &equation);
725 QCOMPARE(equation, GL_FUNC_ADD);
726
727 // WHEN
728 m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT);
729
730 // THEN
731 m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, params: &equation);
732 QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT);
733 }
734
735 void blendFunci()
736 {
737 if (!m_initializationSuccessful)
738 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
739
740 // GIVEN
741 GLint destinationRgb = 0;
742 GLint destinationAlpha = 0;
743 GLint sourceRgb = 0;
744 GLint sourceAlpha = 0;
745 m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, index: 4, data: &sourceRgb);
746 m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, index: 4, data: &destinationRgb);
747 m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, index: 4, data: &sourceAlpha);
748 m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, index: 4, data: &destinationAlpha);
749
750 // THEN
751 QCOMPARE(destinationAlpha, GL_ZERO);
752 QCOMPARE(destinationRgb, GL_ZERO);
753 QCOMPARE(sourceRgb, GL_ONE);
754 QCOMPARE(sourceAlpha, GL_ONE);
755
756 // WHEN
757 m_glHelper.blendFunci(buf: 4, GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
758
759 m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, index: 4, data: &sourceRgb);
760 m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, index: 4, data: &destinationRgb);
761 m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, index: 4, data: &sourceAlpha);
762 m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, index: 4, data: &destinationAlpha);
763
764 // THEN
765 QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA);
766 QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_ALPHA);
767 QCOMPARE(sourceRgb, GL_SRC_COLOR);
768 QCOMPARE(sourceAlpha, GL_SRC_COLOR);
769
770 // Reset default
771 m_glHelper.blendFunci(buf: 4, GL_ONE, GL_ZERO);
772 }
773
774 void blendFuncSeparatei()
775 {
776 if (!m_initializationSuccessful)
777 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
778
779 // GIVEN
780 GLint destinationRgb = 0;
781 GLint destinationAlpha = 0;
782 GLint sourceRgb = 0;
783 GLint sourceAlpha = 0;
784 m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, index: 2, data: &sourceRgb);
785 m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, index: 2, data: &destinationRgb);
786 m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, index: 2, data: &sourceAlpha);
787 m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, index: 2, data: &destinationAlpha);
788
789 // THEN
790 QCOMPARE(destinationAlpha, GL_ZERO);
791 QCOMPARE(destinationRgb, GL_ZERO);
792 QCOMPARE(sourceRgb, GL_ONE);
793 QCOMPARE(sourceAlpha, GL_ONE);
794
795 // WHEN
796 m_glHelper.blendFuncSeparatei(buf: 2, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
797
798 m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, index: 2, data: &sourceRgb);
799 m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, index: 2, data: &destinationRgb);
800 m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, index: 2, data: &sourceAlpha);
801 m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, index: 2, data: &destinationAlpha);
802
803 // THEN
804 QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA);
805 QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_COLOR);
806 QCOMPARE(sourceRgb, GL_SRC_COLOR);
807 QCOMPARE(sourceAlpha, GL_SRC_ALPHA);
808
809 // Reset default
810 m_glHelper.blendFunci(buf: 4, GL_ONE, GL_ZERO);
811 }
812
813 void boundFrameBufferObject()
814 {
815 if (!m_initializationSuccessful)
816 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
817
818 // GIVEN
819 GLuint fboId;
820 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
821
822 // WHEN
823 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
824
825 // THEN
826 GLint boundBuffer = 0;
827 m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, params: &boundBuffer);
828 QCOMPARE(GLuint(boundBuffer), fboId);
829
830 // THEN
831 QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId);
832
833 // Reset state
834 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
835 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
836 }
837
838 void checkFrameBufferComplete()
839 {
840 if (!m_initializationSuccessful)
841 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
842 // GIVEN
843 GLuint fboId;
844 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
845
846 Attachment attachment;
847 attachment.m_point = QRenderTargetOutput::Color1;
848
849 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
850
851 QOpenGLTexture texture(QOpenGLTexture::Target2D);
852 texture.setSize(width: 512, height: 512);
853 texture.setFormat(QOpenGLTexture::RGBA8U);
854 texture.setMinificationFilter(QOpenGLTexture::Linear);
855 texture.setMagnificationFilter(QOpenGLTexture::Linear);
856 texture.create();
857 texture.allocateStorage();
858 m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment);
859
860 // THEN
861 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
862 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
863
864 QVERIFY(m_glHelper.checkFrameBufferComplete());
865
866 // Restore
867 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
868 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
869 }
870
871 void clearBufferf()
872 {
873 if (!m_initializationSuccessful)
874 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
875
876 // GIVEN
877 // GIVEN
878 GLuint fboId;
879 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
880
881 // THEN
882 QVERIFY(fboId != 0);
883
884 // WHEN
885 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
886 // Create 4 attachments
887 QOpenGLTexture *textures[4];
888 for (int i = 0; i < 4; ++i) {
889 Attachment attachment;
890 attachment.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(i);
891
892 QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
893 textures[i] = texture;
894 texture->setSize(width: 512, height: 512);
895 texture->setFormat(QOpenGLTexture::RGBA32F);
896 texture->setMinificationFilter(QOpenGLTexture::Linear);
897 texture->setMagnificationFilter(QOpenGLTexture::Linear);
898 texture->setWrapMode(QOpenGLTexture::ClampToEdge);
899 if (!texture->create())
900 qWarning() << "Texture creation failed";
901 texture->allocateStorage();
902 QVERIFY(texture->isStorageAllocated());
903 GLint error = m_func->glGetError();
904 QVERIFY(error == 0);
905 m_glHelper.bindFrameBufferAttachment(texture, attachment);
906 }
907
908 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
909 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
910
911 // Set Draw buffers
912 GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3;
913 m_func->glDrawBuffers(n: 1, bufs: &clearBufferEnum);
914
915 const GLint bufferIndex = 0; // index of the element in the draw buffers
916 GLint error = m_func->glGetError();
917 QVERIFY(error == 0);
918
919 // WHEN
920 const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f);
921 m_func->glClearBufferfv(GL_COLOR, drawbuffer: bufferIndex, value: reinterpret_cast<const float *>(&clearValue1));
922 error = m_func->glGetError();
923 QVERIFY(error == 0);
924
925 // THEN
926 QVector<QVector4D> colors(512 * 512);
927 textures[3]->bind();
928 m_func->glGetTexImage(GL_TEXTURE_2D, level: 0, GL_RGBA, GL_FLOAT, pixels: colors.data());
929 textures[3]->release();
930
931 for (const QVector4D c : colors) {
932 QVERIFY(c == clearValue1);
933 }
934
935 // WHEN
936 const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f);
937 m_glHelper.clearBufferf(drawbuffer: bufferIndex, values: clearValue2);
938
939 // THEN
940 textures[3]->bind();
941 m_func->glGetTexImage(GL_TEXTURE_2D, level: 0, GL_RGBA, GL_FLOAT, pixels: colors.data());
942 textures[3]->release();
943 for (const QVector4D c : colors) {
944 QVERIFY(c == clearValue2);
945 }
946 // Restore
947 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
948 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
949 for (int i = 0; i < 4; ++i)
950 delete textures[i];
951 }
952
953 void createFrameBufferObject()
954 {
955 if (!m_initializationSuccessful)
956 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
957
958 // WHEN
959 const GLuint fboId = m_glHelper.createFrameBufferObject();
960
961 // THEN
962 QVERIFY(fboId != 0);
963
964 // Restore
965 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
966 }
967
968 void depthMask()
969 {
970 if (!m_initializationSuccessful)
971 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
972
973 // GIVEN
974 GLboolean depthWritingEnabled = false;
975 m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled);
976
977 // THEN
978 QVERIFY(depthWritingEnabled);
979
980 // WHEN
981 m_glHelper.depthMask(GL_FALSE);
982
983 // THEN
984 m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled);
985 QVERIFY(!depthWritingEnabled);
986
987 // WHEN
988 m_glHelper.depthMask(GL_TRUE);
989
990 // THEN
991 m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled);
992 QVERIFY(depthWritingEnabled);
993 }
994
995 void depthTest()
996 {
997 if (!m_initializationSuccessful)
998 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
999
1000 // GIVEN
1001 m_func->glDisable(GL_DEPTH_TEST);
1002 m_func->glDepthFunc(GL_LESS);
1003
1004 // WHEN
1005 m_glHelper.depthTest(GL_LEQUAL);
1006
1007 // THEN
1008 QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST));
1009 GLint depthMode = 0;
1010 m_func->glGetIntegerv(GL_DEPTH_FUNC, params: &depthMode);
1011 QCOMPARE(depthMode, GL_LEQUAL);
1012
1013 // WHEN
1014 m_glHelper.depthTest(GL_LESS);
1015 QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST));
1016 m_func->glGetIntegerv(GL_DEPTH_FUNC, params: &depthMode);
1017 QCOMPARE(depthMode, GL_LESS);
1018 }
1019
1020 void disableClipPlane()
1021 {
1022 if (!m_initializationSuccessful)
1023 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1024
1025 // GIVEN
1026 m_func->glEnable(GL_CLIP_DISTANCE0 + 5);
1027
1028 // THEN
1029 QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5));
1030
1031 // WHEN
1032 m_glHelper.disableClipPlane(clipPlane: 5);
1033
1034 // THEN
1035 QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5));
1036 }
1037
1038 void disablei()
1039 {
1040 if (!m_initializationSuccessful)
1041 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1042
1043 // GIVEN
1044 m_func->glEnablei(GL_BLEND, index: 2);
1045
1046 // THEN
1047 QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2));
1048
1049 // WHEN
1050 m_glHelper.disablei(GL_BLEND, index: 2);
1051
1052 // THEN
1053 QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2));
1054 }
1055
1056 void disablePrimitiveRestart()
1057 {
1058 if (!m_initializationSuccessful)
1059 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1060
1061 // GIVEN
1062 m_func->glEnable(GL_PRIMITIVE_RESTART);
1063
1064 // THEN
1065 QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART));
1066
1067 // WHEN
1068 m_glHelper.disablePrimitiveRestart();
1069
1070 // THEN
1071 QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART));
1072 }
1073
1074 void drawBuffers()
1075 {
1076 if (!m_initializationSuccessful)
1077 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1078
1079 // GIVEN
1080 GLuint fboId;
1081 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
1082
1083 // THEN
1084 QVERIFY(fboId != 0);
1085
1086 // WHEN
1087 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId);
1088 QOpenGLTexture *textures[4];
1089
1090 // Create 4 attachments
1091 for (int i = 0; i < 4; ++i) {
1092 Attachment attachment;
1093 attachment.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(i);
1094
1095 QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
1096 textures[i] = texture;
1097 texture->setSize(width: 512, height: 512);
1098 texture->setFormat(QOpenGLTexture::RGBA32F);
1099 texture->setMinificationFilter(QOpenGLTexture::Linear);
1100 texture->setMagnificationFilter(QOpenGLTexture::Linear);
1101 texture->setWrapMode(QOpenGLTexture::ClampToEdge);
1102 if (!texture->create())
1103 qWarning() << "Texture creation failed";
1104 texture->allocateStorage();
1105 QVERIFY(texture->isStorageAllocated());
1106 GLint error = m_func->glGetError();
1107 QVERIFY(error == 0);
1108 m_glHelper.bindFrameBufferAttachment(texture, attachment);
1109 }
1110 // THEN
1111 GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1112 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
1113
1114 // WHEN
1115 GLenum bufferEnum = GL_COLOR_ATTACHMENT4;
1116 m_func->glDrawBuffers(n: 1, bufs: &bufferEnum);
1117
1118 // THEN
1119 GLint enumValue = -1;
1120 m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue);
1121 QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4);
1122
1123 // WHEN
1124 GLint newBufferEnum = 2;
1125 m_glHelper.drawBuffers(n: 1, bufs: &newBufferEnum);
1126
1127 // THEN
1128 m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue);
1129 QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum);
1130
1131 // WHEN
1132 newBufferEnum = 0;
1133 m_glHelper.drawBuffers(n: 1, bufs: &newBufferEnum);
1134
1135 // THEN
1136 m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue);
1137 QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum);
1138
1139 // Restore
1140 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
1141 m_func->glDeleteFramebuffers(n: 1, framebuffers: &fboId);
1142 for (int i = 0; i < 4; ++i)
1143 delete textures[i];
1144 }
1145
1146 void enableClipPlane()
1147 {
1148 if (!m_initializationSuccessful)
1149 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1150
1151 // GIVEN
1152 m_func->glDisable(GL_CLIP_DISTANCE0 + 4);
1153
1154 // THEN
1155 QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4));
1156
1157 // WHEN
1158 m_glHelper.enableClipPlane(clipPlane: 4);
1159
1160 // THEN
1161 QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4));
1162 }
1163
1164 void enablei()
1165 {
1166 if (!m_initializationSuccessful)
1167 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1168
1169 // GIVEN
1170 m_func->glDisablei(GL_BLEND, index: 4);
1171
1172 // THEN
1173 QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4));
1174
1175 // WHEN
1176 m_glHelper.enablei(GL_BLEND, index: 4);
1177
1178 // THEN
1179 QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4));
1180 }
1181
1182 void enablePrimitiveRestart()
1183 {
1184 if (!m_initializationSuccessful)
1185 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1186
1187 // GIVEN
1188 m_func->glDisable(GL_PRIMITIVE_RESTART);
1189
1190 // THEN
1191 QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART));
1192
1193 // WHEN
1194 m_glHelper.enablePrimitiveRestart(primitiveRestartIndex: 883);
1195
1196 // THEN
1197 QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART));
1198 GLint restartIndex = 0;
1199 m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, params: &restartIndex);
1200 QCOMPARE(restartIndex, 883);
1201
1202 // Restore
1203 m_func->glDisable(GL_PRIMITIVE_RESTART);
1204 }
1205
1206 void enableVertexAttribute()
1207 {
1208 if (!m_initializationSuccessful)
1209 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1210
1211 // GIVEN
1212 QOpenGLVertexArrayObject vao;
1213 vao.create();
1214 QOpenGLVertexArrayObject::Binder binder(&vao);
1215
1216 QOpenGLShaderProgram shaderProgram;
1217 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCodeUniformBuffer);
1218 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformBuffer);
1219 QVERIFY(shaderProgram.link());
1220 shaderProgram.bind();
1221
1222 // WHEN
1223 GLint positionLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexPosition");
1224 GLint texCoordLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexTexCoord");
1225 GLint colorIndexLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexColorIndex");
1226 m_glHelper.enableVertexAttributeArray(location: positionLocation);
1227 m_glHelper.enableVertexAttributeArray(location: texCoordLocation);
1228 m_glHelper.enableVertexAttributeArray(location: colorIndexLocation);
1229
1230 // THEN
1231 const GLint error = m_func->glGetError();
1232 QVERIFY(error == 0);
1233 }
1234
1235 void frontFace()
1236 {
1237 if (!m_initializationSuccessful)
1238 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1239
1240 // GIVEN
1241 m_func->glFrontFace(GL_CW);
1242
1243 // THEN
1244 GLint face = 0;
1245 m_func->glGetIntegerv(GL_FRONT_FACE, params: &face);
1246 QCOMPARE(face, GL_CW);
1247
1248 // WHEN
1249 m_glHelper.frontFace(GL_CCW);
1250
1251 // THEN
1252 m_func->glGetIntegerv(GL_FRONT_FACE, params: &face);
1253 QCOMPARE(face, GL_CCW);
1254 }
1255
1256 void getRenderBufferDimensions()
1257 {
1258 if (!m_initializationSuccessful)
1259 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1260
1261 // GIVEN
1262 GLuint renderBufferId = 0;
1263 m_func->glGenRenderbuffers(n: 1, renderbuffers: &renderBufferId);
1264 QVERIFY(renderBufferId != 0);
1265
1266 // WHEN
1267 m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: renderBufferId);
1268 m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, width: 512, height: 512);
1269 m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: 0);
1270 const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId);
1271
1272 // THEN
1273 QCOMPARE(dimensions, QSize(512, 512));
1274
1275 // Restore
1276 m_func->glDeleteRenderbuffers(n: 1, renderbuffers: &renderBufferId);
1277 }
1278
1279 void getTextureDimensions()
1280 {
1281 if (!m_initializationSuccessful)
1282 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1283
1284 // GIVEN
1285 QOpenGLTexture texture(QOpenGLTexture::Target2D);
1286 texture.setSize(width: 512, height: 512);
1287 texture.setFormat(QOpenGLTexture::RGBA8U);
1288 texture.setMinificationFilter(QOpenGLTexture::Linear);
1289 texture.setMagnificationFilter(QOpenGLTexture::Linear);
1290 texture.create();
1291 texture.allocateStorage();
1292
1293 // WHEN
1294 const QSize dimensions = m_glHelper.getTextureDimensions(textureId: texture.textureId(), GL_TEXTURE_2D);
1295
1296 // THEN
1297 QCOMPARE(dimensions, QSize(512, 512));
1298 }
1299
1300 void pointSize()
1301 {
1302 if (!m_initializationSuccessful)
1303 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1304
1305 // GIVEN
1306 m_func->glEnable(GL_PROGRAM_POINT_SIZE);
1307
1308 // THEN
1309 QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE));
1310 GLfloat size = 0;
1311 m_func->glGetFloatv(GL_POINT_SIZE, params: &size);
1312 QCOMPARE(size, 1.0f);
1313
1314 // WHEN
1315 m_glHelper.pointSize(programmable: false, value: 0.5f);
1316
1317 // THEN
1318 QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE));
1319 m_func->glGetFloatv(GL_POINT_SIZE, params: &size);
1320 QCOMPARE(size, 0.5f);
1321 }
1322
1323 void maxClipPlaneCount()
1324 {
1325 if (!m_initializationSuccessful)
1326 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1327
1328 // GIVEN
1329 GLint maxCount = -1;
1330 m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, params: &maxCount);
1331
1332 // THEN
1333 QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount());
1334 }
1335
1336 void programUniformBlock()
1337 {
1338 if (!m_initializationSuccessful)
1339 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1340
1341 // GIVEN
1342 QOpenGLShaderProgram shaderProgram;
1343 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCodeUniformBuffer);
1344 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformBuffer);
1345 QVERIFY(shaderProgram.link());
1346
1347 // WHEN
1348 const QVector<ShaderUniformBlock> activeUniformBlocks = m_glHelper.programUniformBlocks(programId: shaderProgram.programId());
1349
1350 // THEN
1351 QCOMPARE(activeUniformBlocks.size(), 1);
1352 const ShaderUniformBlock uniformBlock = activeUniformBlocks.first();
1353
1354 QCOMPARE(uniformBlock.m_activeUniformsCount, 1);
1355 QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray"));
1356 QCOMPARE(uniformBlock.m_binding, 2);
1357 }
1358
1359 void programAttributesAndLocations()
1360 {
1361 if (!m_initializationSuccessful)
1362 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1363
1364 // GIVEN
1365 QOpenGLShaderProgram shaderProgram;
1366 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1367 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeSamplers);
1368 QVERIFY(shaderProgram.link());
1369
1370 // WHEN
1371 QVector<ShaderAttribute> activeAttributes = m_glHelper.programAttributesAndLocations(programId: shaderProgram.programId());
1372
1373 // THEN
1374 QCOMPARE(activeAttributes.size(), 2);
1375 std::sort(first: activeAttributes.begin(), last: activeAttributes.end(), comp: [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_location < b.m_location; });
1376
1377 const ShaderAttribute attribute1 = activeAttributes.at(i: 0);
1378 QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition"));
1379 QCOMPARE(attribute1.m_size, 1);
1380 QCOMPARE(attribute1.m_location, 1);
1381 QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3));
1382
1383 const ShaderAttribute attribute2 = activeAttributes.at(i: 1);
1384 QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord"));
1385 QCOMPARE(attribute2.m_size, 1);
1386 QCOMPARE(attribute2.m_location, 2);
1387 QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2));
1388 }
1389
1390 void programUniformsAndLocations()
1391 {
1392 if (!m_initializationSuccessful)
1393 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1394
1395 // GIVEN
1396 QOpenGLShaderProgram shaderProgram;
1397 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1398 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat);
1399 QVERIFY(shaderProgram.link());
1400
1401 // WHEN
1402 QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(programId: shaderProgram.programId());
1403
1404 // THEN
1405 QCOMPARE(activeUniforms.size(), 4);
1406 std::sort(first: activeUniforms.begin(), last: activeUniforms.end(), comp: [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_location < b.m_location; });
1407
1408 const ShaderUniform uniform1 = activeUniforms.at(i: 0);
1409 QCOMPARE(uniform1.m_location, 1);
1410 QCOMPARE(uniform1.m_offset, -1);
1411 QCOMPARE(uniform1.m_blockIndex, -1);
1412 QCOMPARE(uniform1.m_arrayStride, -1);
1413 QCOMPARE(uniform1.m_matrixStride, -1);
1414 QCOMPARE(uniform1.m_size, 1);
1415 QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT));
1416 QCOMPARE(uniform1.m_name, QStringLiteral("multiplier"));
1417
1418 const ShaderUniform uniform2 = activeUniforms.at(i: 1);
1419 QCOMPARE(uniform2.m_location, 2);
1420 QCOMPARE(uniform2.m_offset, -1);
1421 QCOMPARE(uniform2.m_blockIndex, -1);
1422 QCOMPARE(uniform2.m_arrayStride, -1);
1423 QCOMPARE(uniform2.m_matrixStride, -1);
1424 QCOMPARE(uniform2.m_size, 1);
1425 QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2));
1426 QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2"));
1427
1428 const ShaderUniform uniform3 = activeUniforms.at(i: 2);
1429 QCOMPARE(uniform3.m_location, 3);
1430 QCOMPARE(uniform3.m_offset, -1);
1431 QCOMPARE(uniform3.m_blockIndex, -1);
1432 QCOMPARE(uniform3.m_arrayStride, -1);
1433 QCOMPARE(uniform3.m_matrixStride, -1);
1434 QCOMPARE(uniform3.m_size, 1);
1435 QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3));
1436 QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3"));
1437
1438 const ShaderUniform uniform4 = activeUniforms.at(i: 3);
1439 QCOMPARE(uniform4.m_location, 4);
1440 QCOMPARE(uniform4.m_offset, -1);
1441 QCOMPARE(uniform4.m_blockIndex, -1);
1442 QCOMPARE(uniform4.m_arrayStride, -1);
1443 QCOMPARE(uniform4.m_matrixStride, -1);
1444 QCOMPARE(uniform4.m_size, 1);
1445 QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4));
1446 QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4"));
1447 }
1448
1449 void programShaderStorageBlock()
1450 {
1451 if (!m_initializationSuccessful)
1452 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1453
1454 // GIVEN
1455 QOpenGLShaderProgram shaderProgram;
1456 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Compute, source: computeShader);
1457 QVERIFY(shaderProgram.link());
1458
1459 // WHEN
1460 const QVector<ShaderStorageBlock> activeShaderStorageBlocks = m_glHelper.programShaderStorageBlocks(programId: shaderProgram.programId());
1461
1462 // THEN
1463 QVERIFY(activeShaderStorageBlocks.size() == 1);
1464 ShaderStorageBlock block = activeShaderStorageBlocks.first();
1465 QCOMPARE(block.m_name, QStringLiteral("Particles"));
1466 QCOMPARE(block.m_activeVariablesCount, 3);
1467 QCOMPARE(block.m_index, 0);
1468 QCOMPARE(block.m_binding, 6);
1469 QCOMPARE(block.m_size, (4 + 4 + 4) * 4);
1470 }
1471
1472 void releaseFrameBufferObject()
1473 {
1474 if (!m_initializationSuccessful)
1475 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1476
1477 // GIVEN
1478 GLuint fboId;
1479 m_func->glGenFramebuffers(n: 1, framebuffers: &fboId);
1480
1481 // THEN
1482 QVERIFY(fboId != 0);
1483
1484 // WHEN
1485 m_glHelper.releaseFrameBufferObject(frameBufferId: fboId);
1486
1487 // THEN
1488 QVERIFY(!m_func->glIsFramebuffer(fboId));
1489 }
1490
1491 void setMSAAEnabled()
1492 {
1493 if (!m_initializationSuccessful)
1494 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1495
1496 // GIVEN
1497 m_func->glDisable(GL_MULTISAMPLE);
1498
1499 // THEN
1500 QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE));
1501
1502 // WHEN
1503 m_glHelper.setMSAAEnabled(true);
1504
1505 // THEN
1506 QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE));
1507
1508 // WHEN
1509 m_glHelper.setMSAAEnabled(false);
1510
1511 // THEN
1512 QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE));
1513 }
1514
1515 void setAlphaCoverageEnabled()
1516 {
1517 if (!m_initializationSuccessful)
1518 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1519
1520 // GIVEN
1521 m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1522
1523 // THEN
1524 QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE));
1525
1526 // WHEN
1527 m_glHelper.setAlphaCoverageEnabled(true);
1528
1529 // THEN
1530 QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE));
1531
1532 // WHEN
1533 m_glHelper.setAlphaCoverageEnabled(false);
1534
1535 // THEN
1536 QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE));
1537 }
1538
1539 void setClipPlane()
1540 {
1541 if (!m_initializationSuccessful)
1542 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1543 // Deprecated in GL 4
1544 }
1545
1546 void setSeamlessCubemap()
1547 {
1548 if (!m_initializationSuccessful)
1549 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1550
1551 // GIVEN
1552 m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
1553 QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1554
1555 // WHEN
1556 m_glHelper.setSeamlessCubemap(true);
1557
1558 // THEN
1559 QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1560
1561 // WHEN
1562 m_glHelper.setSeamlessCubemap(false);
1563
1564 // THEN
1565 QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1566 }
1567
1568 void setVerticesPerPatch()
1569 {
1570 if (!m_initializationSuccessful)
1571 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1572
1573 // GIVEN
1574 m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
1575
1576 // THEN
1577 QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1578
1579 // WHEN
1580 m_glHelper.setSeamlessCubemap(true);
1581
1582 // THEN
1583 QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1584
1585 // WHEN
1586 m_glHelper.setSeamlessCubemap(false);
1587
1588 // THEN
1589 QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS));
1590 }
1591
1592 void supportsFeature()
1593 {
1594 for (int i = 0; i <= GraphicsHelperInterface::Fences; ++i)
1595 QVERIFY(m_glHelper.supportsFeature(static_cast<GraphicsHelperInterface::Feature>(i)));
1596 }
1597
1598
1599#define ADD_UNIFORM_ENTRY(FragShader, Type, Location, ComponentSize, ExpectedRawSize) \
1600 QTest::newRow(#FragShader"_"#Type) << FragShader << Type << Location << ComponentSize << ExpectedRawSize;
1601
1602 void uniformsByteSize_data()
1603 {
1604 QTest::addColumn<QByteArray>(name: "fragShader");
1605 QTest::addColumn<int>(name: "type");
1606 QTest::addColumn<int>(name: "location");
1607 QTest::addColumn<int>(name: "componentSize");
1608 QTest::addColumn<int>(name: "expectedByteSize");
1609
1610 ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT, 1, 1, 4);
1611 ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC2, 2, 1, 4 * 2);
1612 ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC3, 3, 1, 4 * 3);
1613 ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC4, 4, 1, 4 * 4);
1614
1615 ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT, 1, 1, 4);
1616 ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC2, 2, 1, 4 * 2);
1617 ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC3, 3, 1, 4 * 3);
1618 ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC4, 4, 1, 4 * 4);
1619
1620 ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT, 1, 1, 4);
1621 ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC2, 2, 1, 4 * 2);
1622 ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC3, 3, 1, 4 * 3);
1623 ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC4, 4, 1, 4 * 4);
1624
1625 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2, 1, 1, 4 * 2 * 2);
1626 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x3, 2, 1, 4 * 2 * 3);
1627 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x2, 3, 1, 4 * 3 * 2);
1628 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x4, 4, 1, 4 * 2 * 4);
1629 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x2, 5, 1, 4 * 4 * 2);
1630 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3, 6, 1, 4 * 3 * 3);
1631 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x4, 7, 1, 4 * 3 * 4);
1632 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x3, 8, 1, 4 * 4 * 3);
1633 ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4, 9, 1, 4 * 4 * 4);
1634
1635 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_1D, 1, 1, 4);
1636 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D, 2, 1, 4);
1637 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_ARRAY, 3, 1, 4);
1638 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_3D, 4, 1, 4);
1639 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_CUBE, 5, 1, 4);
1640 ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_RECT, 6, 1, 4);
1641
1642 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_1D, 1, 1, 4);
1643 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D, 2, 1, 4);
1644 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_ARRAY, 3, 1, 4);
1645 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_3D, 4, 1, 4);
1646 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_CUBE, 5, 1, 4);
1647 ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_RECT, 6, 1, 4);
1648 }
1649
1650 void uniformsByteSize()
1651 {
1652 if (!m_initializationSuccessful)
1653 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1654
1655 // GIVEN
1656 QFETCH(QByteArray, fragShader);
1657 QFETCH(int, type);
1658 QFETCH(int, location);
1659 QFETCH(int, componentSize);
1660 QFETCH(int, expectedByteSize);
1661
1662 QOpenGLShaderProgram shaderProgram;
1663 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1664 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragShader);
1665 QVERIFY(shaderProgram.link());
1666
1667 // WHEN
1668 const QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(programId: shaderProgram.programId());
1669 ShaderUniform matchingUniform;
1670 for (const ShaderUniform &u : activeUniforms) {
1671 if (u.m_location == location) {
1672 matchingUniform = u;
1673 break;
1674 }
1675 }
1676
1677 // THEN
1678 QCOMPARE(matchingUniform.m_location, location);
1679 QCOMPARE(matchingUniform.m_type, GLuint(type));
1680 QCOMPARE(matchingUniform.m_size, componentSize);
1681
1682 // WHEN
1683 const int computedRawByteSize = m_glHelper.uniformByteSize(description: matchingUniform);
1684
1685 // THEN
1686 QCOMPARE(expectedByteSize, computedRawByteSize);
1687
1688 // Restore
1689 m_func->glUseProgram(program: 0);
1690 }
1691
1692 void useProgram()
1693 {
1694 if (!m_initializationSuccessful)
1695 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1696
1697 // GIVEN
1698 QOpenGLShaderProgram shaderProgram;
1699 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1700 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeFragOutputs);
1701
1702 // THEN
1703 QVERIFY(shaderProgram.link());
1704
1705 GLint currentProg = 0;
1706 m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: &currentProg);
1707 QVERIFY(currentProg == 0);
1708
1709 // WHEN
1710 m_glHelper.useProgram(programId: shaderProgram.programId());
1711
1712 // THEN
1713 m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: &currentProg);
1714 QCOMPARE(GLuint(currentProg), shaderProgram.programId());
1715
1716 // WHEN
1717 m_glHelper.useProgram(programId: 0);
1718
1719 // THEN
1720 m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: &currentProg);
1721 QVERIFY(currentProg == 0);
1722 }
1723
1724 void vertexAttribDivisor()
1725 {
1726 if (!m_initializationSuccessful)
1727 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1728 }
1729
1730 void vertexAttributePointer()
1731 {
1732 if (!m_initializationSuccessful)
1733 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1734
1735 // GIVEN
1736 QOpenGLVertexArrayObject vao;
1737 vao.create();
1738 QOpenGLVertexArrayObject::Binder binder(&vao);
1739
1740 QOpenGLShaderProgram shaderProgram;
1741 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCodeUniformBuffer);
1742 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformBuffer);
1743 QVERIFY(shaderProgram.link());
1744
1745 GLint positionLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexPosition");
1746 GLint texCoordLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexTexCoord");
1747 GLint colorIndexLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexColorIndex");
1748 GLint texCoordScaleLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexTexCoordScale");
1749
1750 const int vertexCount = 99;
1751 QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer);
1752 positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
1753 positionBuffer.create();
1754 positionBuffer.bind();
1755 positionBuffer.allocate(count: vertexCount * sizeof(QVector3D));
1756
1757 QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer);
1758 texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
1759 texCoordBuffer.create();
1760 texCoordBuffer.allocate(count: vertexCount * sizeof(QVector2D));
1761
1762 QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer);
1763 colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
1764 colorIndexBuffer.create();
1765 colorIndexBuffer.allocate(count: vertexCount * sizeof(int));
1766
1767 QOpenGLBuffer scaleBuffer(QOpenGLBuffer::VertexBuffer);
1768 scaleBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
1769 scaleBuffer.create();
1770 scaleBuffer.allocate(count: vertexCount * sizeof(double));
1771
1772 // WHEN
1773 shaderProgram.bind();
1774 positionBuffer.bind();
1775 m_glHelper.enableVertexAttributeArray(location: positionLocation);
1776 m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, index: positionLocation, size: 3, GL_FLOAT, GL_TRUE, stride: 0, pointer: 0);
1777
1778 texCoordBuffer.bind();
1779 m_glHelper.enableVertexAttributeArray(location: texCoordLocation);
1780 m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, index: texCoordLocation, size: 2, GL_FLOAT, GL_TRUE, stride: 0, pointer: 0);
1781
1782 colorIndexBuffer.bind();
1783 m_glHelper.enableVertexAttributeArray(location: colorIndexLocation);
1784 m_glHelper.vertexAttributePointer(GL_INT, index: colorIndexLocation, size: 1, GL_INT, GL_TRUE, stride: 0, pointer: 0);
1785
1786 scaleBuffer.bind();
1787 m_glHelper.enableVertexAttributeArray(location: colorIndexLocation);
1788 m_glHelper.vertexAttributePointer(GL_DOUBLE, index: texCoordScaleLocation, size: 1, GL_DOUBLE, GL_TRUE, stride: 0, pointer: 0);
1789
1790 // THEN
1791 const GLint error = m_func->glGetError();
1792 QVERIFY(error == 0);
1793 }
1794
1795 void glUniform1fv()
1796 {
1797 if (!m_initializationSuccessful)
1798 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1799
1800 // GIVEN
1801 QOpenGLShaderProgram shaderProgram;
1802 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1803 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat);
1804 QVERIFY(shaderProgram.link());
1805
1806 // WHEN
1807 m_func->glUseProgram(program: shaderProgram.programId());
1808 GLfloat value = 883.0f;
1809 m_glHelper.glUniform1fv(location: 1, count: 1, value: &value);
1810
1811 // THEN
1812 GLfloat setValue = 0.0f;
1813 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 1, params: &setValue);
1814 QCOMPARE(value, setValue);
1815
1816 // Restore
1817 m_func->glUseProgram(program: 0);
1818 }
1819
1820 void glUniform2fv()
1821 {
1822 if (!m_initializationSuccessful)
1823 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1824
1825 // GIVEN
1826 QOpenGLShaderProgram shaderProgram;
1827 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1828 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat);
1829 QVERIFY(shaderProgram.link());
1830
1831 // WHEN
1832 m_func->glUseProgram(program: shaderProgram.programId());
1833 GLfloat values[2] = { 383.0f, 427.0f };
1834 m_glHelper.glUniform2fv(location: 2, count: 1, value: values);
1835
1836 // THEN
1837 GLfloat setValues[2] = { 0.0f, 0.0f };
1838 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 2, params: setValues);
1839 for (int i = 0; i < 2; ++i)
1840 QCOMPARE(setValues[i], values[i]);
1841
1842 // Restore
1843 m_func->glUseProgram(program: 0);
1844 }
1845
1846 void glUniform3fv()
1847 {
1848 if (!m_initializationSuccessful)
1849 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1850
1851 // GIVEN
1852 QOpenGLShaderProgram shaderProgram;
1853 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1854 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat);
1855 QVERIFY(shaderProgram.link());
1856
1857 // WHEN
1858 m_func->glUseProgram(program: shaderProgram.programId());
1859 GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f };
1860 m_glHelper.glUniform3fv(location: 3, count: 1, value: values);
1861
1862 // THEN
1863 GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f };
1864 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 3, params: setValues);
1865 for (int i = 0; i < 3; ++i)
1866 QCOMPARE(setValues[i], values[i]);
1867
1868 // Restore
1869 m_func->glUseProgram(program: 0);
1870 }
1871
1872 void glUniform4fv()
1873 {
1874 if (!m_initializationSuccessful)
1875 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1876
1877 // GIVEN
1878 QOpenGLShaderProgram shaderProgram;
1879 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1880 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat);
1881 QVERIFY(shaderProgram.link());
1882
1883 // WHEN
1884 m_func->glUseProgram(program: shaderProgram.programId());
1885 GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f };
1886 m_glHelper.glUniform4fv(location: 4, count: 1, value: values);
1887
1888 // THEN
1889 GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1890 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 4, params: setValues);
1891 for (int i = 0; i < 4; ++i)
1892 QCOMPARE(setValues[i], values[i]);
1893
1894 // Restore
1895 m_func->glUseProgram(program: 0);
1896 }
1897
1898 void glUniform1iv()
1899 {
1900 if (!m_initializationSuccessful)
1901 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1902
1903 // GIVEN
1904 QOpenGLShaderProgram shaderProgram;
1905 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1906 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt);
1907 QVERIFY(shaderProgram.link());
1908
1909 // WHEN
1910 m_func->glUseProgram(program: shaderProgram.programId());
1911 GLint value = 883;
1912 m_glHelper.glUniform1iv(location: 1, count: 1, value: &value);
1913
1914 // THEN
1915 GLint setValue = 0;
1916 m_func->glGetUniformiv(program: shaderProgram.programId(), location: 1, params: &setValue);
1917 QCOMPARE(value, setValue);
1918
1919 // Restore
1920 m_func->glUseProgram(program: 0);
1921 }
1922
1923 void glUniform2iv()
1924 {
1925 if (!m_initializationSuccessful)
1926 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1927
1928 // GIVEN
1929 QOpenGLShaderProgram shaderProgram;
1930 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1931 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt);
1932 QVERIFY(shaderProgram.link());
1933
1934 // WHEN
1935 m_func->glUseProgram(program: shaderProgram.programId());
1936 GLint values[2] = { 383, 427 };
1937 m_glHelper.glUniform2iv(location: 2, count: 1, value: values);
1938
1939 // THEN
1940 GLint setValues[2] = { 0, 0 };
1941 m_func->glGetUniformiv(program: shaderProgram.programId(), location: 2, params: setValues);
1942 for (int i = 0; i < 2; ++i)
1943 QCOMPARE(values[i], setValues[i]);
1944
1945 // Restore
1946 m_func->glUseProgram(program: 0);
1947 }
1948
1949 void glUniform3iv()
1950 {
1951 if (!m_initializationSuccessful)
1952 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1953
1954 // GIVEN
1955 QOpenGLShaderProgram shaderProgram;
1956 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1957 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt);
1958 QVERIFY(shaderProgram.link());
1959
1960 // WHEN
1961 m_func->glUseProgram(program: shaderProgram.programId());
1962 GLint values[3] = { 572, 1340, 1584 };
1963 m_glHelper.glUniform3iv(location: 3, count: 1, value: values);
1964
1965 // THEN
1966 GLint setValues[3] = { 0, 0, 0 };
1967 m_func->glGetUniformiv(program: shaderProgram.programId(), location: 3, params: setValues);
1968 for (int i = 0; i < 3; ++i)
1969 QCOMPARE(values[i], setValues[i]);
1970
1971 // Restore
1972 m_func->glUseProgram(program: 0);
1973 }
1974
1975 void glUniform4iv()
1976 {
1977 if (!m_initializationSuccessful)
1978 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
1979
1980 // GIVEN
1981 QOpenGLShaderProgram shaderProgram;
1982 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
1983 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt);
1984 QVERIFY(shaderProgram.link());
1985
1986 // WHEN
1987 m_func->glUseProgram(program: shaderProgram.programId());
1988 GLint values[4] = { 454, 350, 883, 355 };
1989 m_glHelper.glUniform4iv(location: 4, count: 1, value: values);
1990
1991 // THEN
1992 GLint setValues[4] = { 0, 0, 0, 0 };
1993 m_func->glGetUniformiv(program: shaderProgram.programId(), location: 4, params: setValues);
1994 for (int i = 0; i < 4; ++i)
1995 QCOMPARE(values[i], setValues[i]);
1996
1997 // Restore
1998 m_func->glUseProgram(program: 0);
1999 }
2000
2001 void glUniform1uiv()
2002 {
2003 if (!m_initializationSuccessful)
2004 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2005
2006 // GIVEN
2007 QOpenGLShaderProgram shaderProgram;
2008 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2009 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsUInt);
2010 QVERIFY(shaderProgram.link());
2011
2012 // WHEN
2013 m_func->glUseProgram(program: shaderProgram.programId());
2014 GLuint value = 883U;
2015 m_glHelper.glUniform1uiv(location: 1, count: 1, value: &value);
2016
2017 // THEN
2018 GLuint setValue = 0U;
2019 m_func->glGetUniformuiv(program: shaderProgram.programId(), location: 1, params: &setValue);
2020 QCOMPARE(value, setValue);
2021
2022 // Restore
2023 m_func->glUseProgram(program: 0);
2024 }
2025
2026 void glUniform2uiv()
2027 {
2028 if (!m_initializationSuccessful)
2029 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2030
2031 // GIVEN
2032 QOpenGLShaderProgram shaderProgram;
2033 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2034 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsUInt);
2035 QVERIFY(shaderProgram.link());
2036
2037 // WHEN
2038 m_func->glUseProgram(program: shaderProgram.programId());
2039 GLuint values[2] = { 383U, 427U };
2040 m_glHelper.glUniform2uiv(location: 2, count: 1, value: values);
2041
2042 // THEN
2043 GLuint setValues[2] = { 0U, 0U };
2044 m_func->glGetUniformuiv(program: shaderProgram.programId(), location: 2, params: setValues);
2045 for (int i = 0; i < 2; ++i)
2046 QCOMPARE(values[i], setValues[i]);
2047
2048 // Restore
2049 m_func->glUseProgram(program: 0);
2050 }
2051
2052 void glUniform3uiv()
2053 {
2054 if (!m_initializationSuccessful)
2055 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2056
2057 // GIVEN
2058 QOpenGLShaderProgram shaderProgram;
2059 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2060 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsUInt);
2061 QVERIFY(shaderProgram.link());
2062
2063 // WHEN
2064 m_func->glUseProgram(program: shaderProgram.programId());
2065 GLuint values[3] = { 572U, 1340U, 1584U };
2066 m_glHelper.glUniform3uiv(location: 3, count: 1, value: values);
2067
2068 // THEN
2069 GLuint setValues[3] = { 0U, 0U, 0U };
2070 m_func->glGetUniformuiv(program: shaderProgram.programId(), location: 3, params: setValues);
2071 for (int i = 0; i < 3; ++i)
2072 QCOMPARE(values[i], setValues[i]);
2073
2074 // Restore
2075 m_func->glUseProgram(program: 0);
2076 }
2077
2078 void glUniform4uiv()
2079 {
2080 if (!m_initializationSuccessful)
2081 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2082
2083 // GIVEN
2084 QOpenGLShaderProgram shaderProgram;
2085 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2086 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsUInt);
2087 QVERIFY(shaderProgram.link());
2088
2089 // WHEN
2090 m_func->glUseProgram(program: shaderProgram.programId());
2091 GLuint values[4] = { 454U, 350U, 883U, 355U };
2092 m_glHelper.glUniform4uiv(location: 4, count: 1, value: values);
2093
2094 // THEN
2095 GLuint setValues[4] = { 0U, 0U, 0U, 0U };
2096 m_func->glGetUniformuiv(program: shaderProgram.programId(), location: 4, params: setValues);
2097 for (int i = 0; i < 4; ++i)
2098 QCOMPARE(values[i], setValues[i]);
2099
2100 // Restore
2101 m_func->glUseProgram(program: 0);
2102 }
2103
2104 void glUniformMatrix2fv()
2105 {
2106 if (!m_initializationSuccessful)
2107 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2108
2109 // GIVEN
2110 QOpenGLShaderProgram shaderProgram;
2111 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2112 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2113 QVERIFY(shaderProgram.link());
2114
2115 // WHEN
2116 m_func->glUseProgram(program: shaderProgram.programId());
2117 GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f };
2118 m_glHelper.glUniformMatrix2fv(location: 1, count: 1, value: values);
2119
2120 // THEN
2121 GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
2122 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 1, params: setValues);
2123 for (int i = 0; i < 4; ++i)
2124 QCOMPARE(values[i], setValues[i]);
2125
2126 // Restore
2127 m_func->glUseProgram(program: 0);
2128 }
2129
2130 void glUniformMatrix3fv()
2131 {
2132 if (!m_initializationSuccessful)
2133 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2134
2135 // GIVEN
2136 QOpenGLShaderProgram shaderProgram;
2137 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2138 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2139 QVERIFY(shaderProgram.link());
2140
2141 // WHEN
2142 m_func->glUseProgram(program: shaderProgram.programId());
2143 GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f };
2144 m_glHelper.glUniformMatrix3fv(location: 6, count: 1, value: values);
2145
2146 // THEN
2147 GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
2148 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 6, params: setValues);
2149 for (int i = 0; i < 9; ++i)
2150 QCOMPARE(values[i], setValues[i]);
2151
2152 // Restore
2153 m_func->glUseProgram(program: 0);
2154 }
2155
2156 void glUniformMatrix4fv()
2157 {
2158 if (!m_initializationSuccessful)
2159 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2160
2161 // GIVEN
2162 QOpenGLShaderProgram shaderProgram;
2163 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2164 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2165 QVERIFY(shaderProgram.link());
2166
2167 // WHEN
2168 m_func->glUseProgram(program: shaderProgram.programId());
2169 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 };
2170 m_glHelper.glUniformMatrix4fv(location: 9, count: 1, value: values);
2171
2172 // THEN
2173 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 };
2174 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 9, params: setValues);
2175 for (int i = 0; i < 16; ++i)
2176 QCOMPARE(values[i], setValues[i]);
2177
2178 // Restore
2179 m_func->glUseProgram(program: 0);
2180 }
2181
2182 void glUniformMatrix2x3fv()
2183 {
2184 if (!m_initializationSuccessful)
2185 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2186
2187 // GIVEN
2188 QOpenGLShaderProgram shaderProgram;
2189 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2190 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2191 QVERIFY(shaderProgram.link());
2192
2193 // WHEN
2194 m_func->glUseProgram(program: shaderProgram.programId());
2195 GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f};
2196 m_glHelper.glUniformMatrix2x3fv(location: 2, count: 1, value: values);
2197
2198 // THEN
2199 GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
2200 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 2, params: setValues);
2201 for (int i = 0; i < 6; ++i)
2202 QCOMPARE(values[i], setValues[i]);
2203
2204 // Restore
2205 m_func->glUseProgram(program: 0);
2206 }
2207
2208 void glUniformMatrix3x2fv()
2209 {
2210 if (!m_initializationSuccessful)
2211 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2212
2213 // GIVEN
2214 QOpenGLShaderProgram shaderProgram;
2215 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2216 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2217 QVERIFY(shaderProgram.link());
2218
2219 // WHEN
2220 m_func->glUseProgram(program: shaderProgram.programId());
2221 GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f};
2222 m_glHelper.glUniformMatrix3x2fv(location: 3, count: 1, value: values);
2223
2224 // THEN
2225 GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
2226 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 3, params: setValues);
2227 for (int i = 0; i < 6; ++i)
2228 QCOMPARE(values[i], setValues[i]);
2229
2230 // Restore
2231 m_func->glUseProgram(program: 0);
2232 }
2233
2234 void glUniformMatrix2x4fv()
2235 {
2236 if (!m_initializationSuccessful)
2237 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2238
2239 // GIVEN
2240 QOpenGLShaderProgram shaderProgram;
2241 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2242 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2243 QVERIFY(shaderProgram.link());
2244
2245 // WHEN
2246 m_func->glUseProgram(program: shaderProgram.programId());
2247 GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f};
2248 m_glHelper.glUniformMatrix2x4fv(location: 4, count: 1, value: values);
2249
2250 // THEN
2251 GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
2252 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 4, params: setValues);
2253 for (int i = 0; i < 8; ++i)
2254 QCOMPARE(values[i], setValues[i]);
2255
2256 // Restore
2257 m_func->glUseProgram(program: 0);
2258 }
2259
2260 void glUniformMatrix4x2fv()
2261 {
2262 if (!m_initializationSuccessful)
2263 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2264
2265 // GIVEN
2266 QOpenGLShaderProgram shaderProgram;
2267 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2268 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2269 QVERIFY(shaderProgram.link());
2270
2271 // WHEN
2272 m_func->glUseProgram(program: shaderProgram.programId());
2273 GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f};
2274 m_glHelper.glUniformMatrix4x2fv(location: 5, count: 1, value: values);
2275
2276 // THEN
2277 GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
2278 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 5, params: setValues);
2279 for (int i = 0; i < 8; ++i)
2280 QCOMPARE(values[i], setValues[i]);
2281
2282 // Restore
2283 m_func->glUseProgram(program: 0);
2284 }
2285
2286 void glUniformMatrix3x4fv()
2287 {
2288 if (!m_initializationSuccessful)
2289 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2290
2291 // GIVEN
2292 QOpenGLShaderProgram shaderProgram;
2293 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2294 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2295 QVERIFY(shaderProgram.link());
2296
2297 // WHEN
2298 m_func->glUseProgram(program: shaderProgram.programId());
2299 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,};
2300 m_glHelper.glUniformMatrix3x4fv(location: 7, count: 1, value: values);
2301
2302 // THEN
2303 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 };
2304 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 7, params: setValues);
2305 for (int i = 0; i < 12; ++i)
2306 QCOMPARE(values[i], setValues[i]);
2307
2308 // Restore
2309 m_func->glUseProgram(program: 0);
2310 }
2311
2312 void glUniformMatrix4x3fv()
2313 {
2314 if (!m_initializationSuccessful)
2315 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2316
2317 // GIVEN
2318 QOpenGLShaderProgram shaderProgram;
2319 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode);
2320 shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices);
2321 QVERIFY(shaderProgram.link());
2322
2323 // WHEN
2324 m_func->glUseProgram(program: shaderProgram.programId());
2325 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};
2326 m_glHelper.glUniformMatrix4x3fv(location: 8, count: 1, value: values);
2327
2328 // THEN
2329 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 };
2330 m_func->glGetUniformfv(program: shaderProgram.programId(), location: 8, params: setValues);
2331 for (int i = 0; i < 12; ++i)
2332 QCOMPARE(values[i], setValues[i]);
2333
2334 // Restore
2335 m_func->glUseProgram(program: 0);
2336 }
2337
2338
2339 void blitFramebuffer()
2340 {
2341 if (!m_initializationSuccessful)
2342 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2343
2344 // GIVEN
2345 GLuint fbos[2];
2346 GLuint fboTextures[2];
2347
2348 m_func->glGenFramebuffers(n: 2, framebuffers: fbos);
2349 m_func->glGenTextures(n: 2, textures: fboTextures);
2350
2351 m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture: fboTextures[0]);
2352 m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples: 4, GL_RGBA8, width: 10, height: 10, fixedsamplelocations: true);
2353 m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture: 0);
2354
2355 m_func->glBindTexture(GL_TEXTURE_2D, texture: fboTextures[1]);
2356 m_func->glTexImage2D(GL_TEXTURE_2D, level: 0, GL_RGBA8, width: 10, height: 10, border: 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels: nullptr);
2357 m_func->glBindTexture(GL_TEXTURE_2D, texture: 0);
2358
2359 m_func->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: fbos[1]);
2360 m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture: fboTextures[1], level: 0);
2361
2362 GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER);
2363 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
2364
2365 m_func->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: fbos[0]);
2366 m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture: fboTextures[0], level: 0);
2367
2368 status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER);
2369 QVERIFY(status == GL_FRAMEBUFFER_COMPLETE);
2370
2371 m_func->glEnable(GL_MULTISAMPLE);
2372 m_func->glClearColor(red: 0.2f, green: 0.2f, blue: 0.2f, alpha: 0.2f);
2373 m_func->glClear(GL_COLOR_BUFFER_BIT);
2374 m_func->glDisable(GL_MULTISAMPLE);
2375
2376 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fbos[1]);
2377
2378 // WHEN
2379 m_glHelper.blitFramebuffer(srcX0: 0,srcY0: 0,srcX1: 10,srcY1: 10,dstX0: 0,dstY0: 0,dstX1: 10,dstY1: 10, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2380
2381 m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer: fbos[1]);
2382
2383 GLuint result[10*10];
2384 m_func->glReadPixels(x: 0,y: 0,width: 10,height: 10,GL_RGBA, GL_UNSIGNED_BYTE, pixels: result);
2385
2386 // THEN
2387 GLuint v = (0.2f) * 255;
2388 v = v | (v<<8) | (v<<16) | (v<<24);
2389 for (GLuint value : result) {
2390 QCOMPARE(value, v);
2391 }
2392 m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0);
2393 m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer: 0);
2394
2395 m_func->glDeleteFramebuffers(n: 2, framebuffers: fbos);
2396 m_func->glDeleteTextures(n: 2, textures: fboTextures);
2397 }
2398
2399#define ADD_GL_TYPE_ENTRY(Type, Expected) \
2400 QTest::newRow(#Type) << Type << Expected;
2401
2402 void uniformTypeFromGLType_data()
2403 {
2404 QTest::addColumn<int>(name: "glType");
2405 QTest::addColumn<UniformType>(name: "expected");
2406
2407 ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float);
2408 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2);
2409 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3);
2410 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3);
2411 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2);
2412 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3);
2413 ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3);
2414 ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int);
2415 ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2);
2416 ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3);
2417 ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4);
2418 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt);
2419 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2);
2420 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3);
2421 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4);
2422 ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool);
2423 ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2);
2424 ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3);
2425 ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4);
2426 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2);
2427 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3);
2428 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4);
2429 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3);
2430 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4);
2431 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2);
2432 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2);
2433 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3);
2434 ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4);
2435 ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler);
2436 ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler);
2437 ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler);
2438 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler);
2439 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler);
2440 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler);
2441 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler);
2442 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler);
2443 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler);
2444 ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler);
2445 ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler);
2446 ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler);
2447 ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler);
2448 ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler);
2449 ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, UniformType::Sampler);
2450 ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler);
2451 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler);
2452 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler);
2453 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler);
2454 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler);
2455 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler);
2456 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler);
2457 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler);
2458 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler);
2459 ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler);
2460 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler);
2461 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler);
2462 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler);
2463 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler);
2464 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler);
2465 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler);
2466 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler);
2467 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler);
2468 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler);
2469 ADD_GL_TYPE_ENTRY(GL_IMAGE_1D, UniformType::Image);
2470 ADD_GL_TYPE_ENTRY(GL_IMAGE_2D, UniformType::Image);
2471 ADD_GL_TYPE_ENTRY(GL_IMAGE_3D, UniformType::Image);
2472 ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_RECT, UniformType::Image);
2473 ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE, UniformType::Image);
2474 ADD_GL_TYPE_ENTRY(GL_IMAGE_BUFFER, UniformType::Image);
2475 ADD_GL_TYPE_ENTRY(GL_IMAGE_1D_ARRAY, UniformType::Image);
2476 ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_ARRAY, UniformType::Image);
2477 ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
2478 ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE, UniformType::Image);
2479 ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
2480 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D, UniformType::Image);
2481 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D, UniformType::Image); ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_3D, UniformType::Image);
2482 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_RECT, UniformType::Image);
2483 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE, UniformType::Image);
2484 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_BUFFER, UniformType::Image);
2485 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D_ARRAY, UniformType::Image);
2486 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_ARRAY, UniformType::Image);
2487 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
2488 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image);
2489 ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
2490 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D, UniformType::Image);
2491 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D, UniformType::Image);
2492 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_3D, UniformType::Image);
2493 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_RECT, UniformType::Image);
2494 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE, UniformType::Image);
2495 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_BUFFER, UniformType::Image);
2496 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D_ARRAY, UniformType::Image);
2497 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_ARRAY, UniformType::Image);
2498 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
2499 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image);
2500 ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
2501 }
2502
2503 void uniformTypeFromGLType()
2504 {
2505 // GIVEN
2506 QFETCH(int, glType);
2507 QFETCH(UniformType, expected);
2508
2509 // WHEN
2510 UniformType computed = m_glHelper.uniformTypeFromGLType(glType);
2511
2512 // THEN
2513 QCOMPARE(computed, expected);
2514 }
2515
2516 void drawBuffer()
2517 {
2518 if (!m_initializationSuccessful)
2519 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2520
2521 m_func->glGetError();
2522
2523 // WHEN
2524 m_glHelper.drawBuffer(GL_FRONT);
2525 const GLint error = m_func->glGetError();
2526 QVERIFY(error == 0);
2527
2528 // THEN
2529 GLint p;
2530 m_func->glGetIntegerv(GL_DRAW_BUFFER, params: &p);
2531 QCOMPARE(p, GL_FRONT);
2532 }
2533
2534 void readBuffer()
2535 {
2536 if (!m_initializationSuccessful)
2537 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2538
2539 m_func->glGetError();
2540
2541 // WHEN
2542 m_glHelper.readBuffer(GL_FRONT);
2543
2544 // THEN
2545 const GLint error = m_func->glGetError();
2546 QVERIFY(error == 0);
2547 GLint p;
2548 m_func->glGetIntegerv(GL_READ_BUFFER, params: &p);
2549 QCOMPARE(p, GL_FRONT);
2550 }
2551
2552 void fenceSync()
2553 {
2554 if (!m_initializationSuccessful)
2555 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2556
2557 m_func->glGetError();
2558
2559 // WHEN
2560 GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync());
2561
2562 // THEN
2563 QVERIFY(sync != nullptr);
2564 QCOMPARE(m_func->glIsSync(sync), GL_TRUE);
2565 const GLint error = m_func->glGetError();
2566 QVERIFY(error == 0);
2567 }
2568
2569 void clientWaitSync()
2570 {
2571 if (!m_initializationSuccessful)
2572 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2573
2574 m_func->glGetError();
2575
2576 // WHEN
2577 QElapsedTimer t;
2578 t.start();
2579
2580 GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync());
2581
2582 m_glHelper.clientWaitSync(sync, nanoSecTimeout: 1000000);
2583
2584 // THEN
2585 const GLint error = m_func->glGetError();
2586 QVERIFY(error == 0);
2587 qDebug() << t.nsecsElapsed();
2588 }
2589
2590 void waitSync()
2591 {
2592 if (!m_initializationSuccessful)
2593 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2594
2595 m_func->glGetError();
2596
2597 // WHEN
2598 GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync());
2599 m_func->glFlush();
2600 m_glHelper.waitSync(sync);
2601
2602 // THEN
2603 const GLint error = m_func->glGetError();
2604 QVERIFY(error == 0);
2605 }
2606
2607 void wasSyncSignaled()
2608 {
2609 if (!m_initializationSuccessful)
2610 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2611
2612 m_func->glGetError();
2613
2614 // WHEN
2615 GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync());
2616 m_func->glFlush();
2617 m_glHelper.waitSync(sync);
2618
2619 // THEN
2620 const GLint error = m_func->glGetError();
2621 QVERIFY(error == 0);
2622
2623 // Shouldn't loop forever
2624 while (!m_glHelper.wasSyncSignaled(sync))
2625 ;
2626 }
2627
2628 void deleteSync()
2629 {
2630 if (!m_initializationSuccessful)
2631 QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
2632
2633 m_func->glGetError();
2634
2635 // WHEN
2636 GLsync sync = reinterpret_cast<GLsync>(m_glHelper.fenceSync());
2637 m_glHelper.clientWaitSync(sync, nanoSecTimeout: GLuint64(-1));
2638
2639 // THEN
2640 const GLint error = m_func->glGetError();
2641 QVERIFY(error == 0);
2642 QVERIFY(m_glHelper.wasSyncSignaled(sync) == true);
2643
2644 // WHEN
2645 m_glHelper.deleteSync(sync);
2646
2647 // THEN
2648 QCOMPARE(m_func->glIsSync(sync), GL_FALSE);
2649 }
2650
2651 void rasterMode()
2652 {
2653 if (!m_initializationSuccessful)
2654 QSKIP("Initialization failed, OpenGL 4.3 functions not supported");
2655
2656 m_func->glGetError();
2657 m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE);
2658
2659 // THEN
2660 const GLint error = m_func->glGetError();
2661 QVERIFY(error == 0);
2662 GLint p;
2663 m_func->glGetIntegerv(GL_POLYGON_MODE, params: &p);
2664 QCOMPARE(p, GL_LINE);
2665 }
2666
2667private:
2668 QScopedPointer<QWindow> m_window;
2669 QOpenGLContext m_glContext;
2670 GraphicsHelperGL4 m_glHelper;
2671 QOpenGLFunctions_4_3_Core *m_func = nullptr;
2672 bool m_initializationSuccessful = false;
2673};
2674
2675#endif
2676
2677int main(int argc, char *argv[])
2678{
2679#ifdef TEST_SHOULD_BE_PERFORMED
2680 QGuiApplication app(argc, argv);
2681 app.setAttribute(attribute: Qt::AA_Use96Dpi, on: true);
2682 tst_GraphicsHelperGL4 tc;
2683 QTEST_SET_MAIN_SOURCE_PATH
2684 return QTest::qExec(testObject: &tc, argc, argv);
2685#endif
2686 return 0;
2687}
2688
2689#ifdef TEST_SHOULD_BE_PERFORMED
2690#include "tst_graphicshelpergl4.moc"
2691#endif
2692

source code of qt3d/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp