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

source code of qt3d/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp