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

source code of qt3d/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp