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 <graphicshelpergl2_p.h> |
33 | #include <Qt3DRender/private/attachmentpack_p.h> |
34 | #include <QtOpenGLExtensions/QOpenGLExtensions> |
35 | #include <QOpenGLContext> |
36 | #include <QOpenGLBuffer> |
37 | #include <QOpenGLFunctions_2_0> |
38 | #include <QOpenGLShaderProgram> |
39 | #include <QOpenGLVertexArrayObject> |
40 | #include <QSurfaceFormat> |
41 | |
42 | #ifndef QT_OPENGL_ES_2 |
43 | |
44 | #define TEST_SHOULD_BE_PERFORMED 1 |
45 | |
46 | QT_BEGIN_NAMESPACE |
47 | |
48 | using namespace Qt3DRender; |
49 | using namespace Qt3DRender::Render; |
50 | using namespace Qt3DRender::Render::OpenGL; |
51 | |
52 | namespace { |
53 | |
54 | const QByteArray vertCode = QByteArrayLiteral( |
55 | "#version 120\n" \ |
56 | "attribute vec3 vertexPosition;\n" \ |
57 | "attribute vec2 vertexTexCoord;\n" \ |
58 | "varying vec2 texCoord;\n" \ |
59 | "void main()\n" \ |
60 | "{\n" \ |
61 | " texCoord = vertexTexCoord;\n" \ |
62 | " gl_Position = vec4(vertexPosition, 1.0);\n" \ |
63 | "}\n" ); |
64 | |
65 | const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( |
66 | "#version 120\n" \ |
67 | "uniform float multiplier;\n" \ |
68 | "uniform vec2 multiplierVec2;\n" \ |
69 | "uniform vec3 multiplierVec3;\n" \ |
70 | "uniform vec4 multiplierVec4;\n" \ |
71 | "void main()\n" \ |
72 | "{\n" \ |
73 | " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ |
74 | " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ |
75 | "}\n" ); |
76 | |
77 | const QByteArray fragCodeUniformsInt = QByteArrayLiteral( |
78 | "#version 120\n" \ |
79 | "uniform int multiplier;\n" \ |
80 | "uniform ivec2 multiplierVec2;\n" \ |
81 | "uniform ivec3 multiplierVec3;\n" \ |
82 | "uniform ivec4 multiplierVec4;\n" \ |
83 | "void main()\n" \ |
84 | "{\n" \ |
85 | " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ |
86 | " gl_FragColor = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ |
87 | "}\n" ); |
88 | |
89 | const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( |
90 | "#version 120\n" \ |
91 | "uniform mat2 m2;\n" \ |
92 | "uniform mat2x3 m23;\n" \ |
93 | "uniform mat3x2 m32;\n" \ |
94 | "uniform mat2x4 m24;\n" \ |
95 | "uniform mat4x2 m42;\n" \ |
96 | "uniform mat3 m3;\n" \ |
97 | "uniform mat3x4 m34;\n" \ |
98 | "uniform mat4x3 m43;\n" \ |
99 | "uniform mat4 m4;\n" \ |
100 | "void main()\n" \ |
101 | "{\n" \ |
102 | " 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" \ |
103 | " gl_FragColor = vec4(1, 0, 0, 1) * lengthSum;\n" \ |
104 | "}\n" ); |
105 | |
106 | |
107 | const QByteArray fragCodeSamplers = QByteArrayLiteral( |
108 | "#version 120\n" \ |
109 | "varying vec2 texCoord;\n" \ |
110 | "uniform sampler1D s1;\n" \ |
111 | "uniform sampler2D s2;\n" \ |
112 | "uniform sampler3D s3;\n" \ |
113 | "uniform samplerCube scube;\n" \ |
114 | "void main()\n" \ |
115 | "{\n" \ |
116 | " gl_FragColor = vec4(1, 0, 0, 1) *" \ |
117 | " texture1D(s1, texCoord.x) *" \ |
118 | " texture2D(s2, texCoord) *" \ |
119 | " texture3D(s3, vec3(texCoord, 0.0)) *" \ |
120 | " textureCube(scube, vec3(texCoord, 0));\n" \ |
121 | "}\n" ); |
122 | |
123 | } // anonymous |
124 | |
125 | class tst_GraphicsHelperGL2 : public QObject |
126 | { |
127 | Q_OBJECT |
128 | private Q_SLOTS: |
129 | |
130 | void init() |
131 | { |
132 | m_window.reset(other: new QWindow); |
133 | m_window->setSurfaceType(QWindow::OpenGLSurface); |
134 | m_window->setGeometry(posx: 0, posy: 0, w: 10, h: 10); |
135 | m_window->create(); |
136 | |
137 | QSurfaceFormat format; |
138 | format.setVersion(major: 2, minor: 0); |
139 | format.setProfile(QSurfaceFormat::NoProfile); |
140 | format.setDepthBufferSize(24); |
141 | format.setSamples(4); |
142 | format.setStencilBufferSize(8); |
143 | m_window->setFormat(format); |
144 | m_glContext.setFormat(format); |
145 | |
146 | if (!m_glContext.create()) { |
147 | qWarning() << "Failed to create OpenGL context" ; |
148 | return; |
149 | } |
150 | |
151 | if (!m_glContext.makeCurrent(surface: m_window.data())) { |
152 | qWarning() << "Failed to make OpenGL context current" ; |
153 | return; |
154 | } |
155 | |
156 | if ((m_func = m_glContext.versionFunctions<QOpenGLFunctions_2_0>()) != nullptr) { |
157 | if (m_glContext.hasExtension(QByteArrayLiteral("GL_ARB_framebuffer_object" ))) { |
158 | m_fboFuncs = new QOpenGLExtension_ARB_framebuffer_object(); |
159 | m_fboFuncs->initializeOpenGLFunctions(); |
160 | } |
161 | m_glHelper.initializeHelper(context: &m_glContext, functions: m_func); |
162 | m_initializationSuccessful = true; |
163 | } |
164 | } |
165 | |
166 | void cleanup() |
167 | { |
168 | m_glContext.doneCurrent(); |
169 | } |
170 | |
171 | void alphaTest() |
172 | { |
173 | if (!m_initializationSuccessful) |
174 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
175 | // Deprecated |
176 | } |
177 | |
178 | void bindBufferBase() |
179 | { |
180 | if (!m_initializationSuccessful) |
181 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
182 | |
183 | // Not supported by GL2 |
184 | } |
185 | |
186 | void bindFragDataLocation() |
187 | { |
188 | if (!m_initializationSuccessful) |
189 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
190 | // Not supported by GL2 |
191 | } |
192 | |
193 | void bindFrameBufferAttachment() |
194 | { |
195 | if (!m_initializationSuccessful) |
196 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
197 | |
198 | if (!m_fboFuncs) |
199 | QSKIP("FBO not supported by OpenGL 2.0" ); |
200 | |
201 | // GIVEN |
202 | GLuint fboId; |
203 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
204 | |
205 | Attachment attachment; |
206 | attachment.m_point = QRenderTargetOutput::Color0; |
207 | |
208 | // THEN |
209 | QVERIFY(fboId != 0); |
210 | |
211 | // WHEN |
212 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId); |
213 | |
214 | QOpenGLTexture texture(QOpenGLTexture::Target2D); |
215 | texture.setSize(width: 512, height: 512); |
216 | texture.setFormat(QOpenGLTexture::RGBA32F); |
217 | texture.setMinificationFilter(QOpenGLTexture::Linear); |
218 | texture.setMagnificationFilter(QOpenGLTexture::Linear); |
219 | texture.setWrapMode(QOpenGLTexture::ClampToEdge); |
220 | if (!texture.create()) |
221 | qWarning() << "Texture creation failed" ; |
222 | texture.allocateStorage(); |
223 | QVERIFY(texture.isStorageAllocated()); |
224 | GLint error = m_func->glGetError(); |
225 | QVERIFY(error == 0); |
226 | m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment); |
227 | |
228 | // THEN |
229 | GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); |
230 | QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); |
231 | |
232 | error = m_func->glGetError(); |
233 | QVERIFY(error == 0); |
234 | GLint textureAttachmentId = 0; |
235 | m_fboFuncs->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, |
236 | GL_COLOR_ATTACHMENT0, |
237 | GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, |
238 | params: &textureAttachmentId); |
239 | QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); |
240 | |
241 | // Restore state |
242 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0); |
243 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
244 | } |
245 | |
246 | void bindFrameBufferObject() |
247 | { |
248 | if (!m_initializationSuccessful) |
249 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
250 | if (!m_fboFuncs) |
251 | QSKIP("FBO not supported by OpenGL 2.0" ); |
252 | |
253 | // GIVEN |
254 | GLuint fboId; |
255 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
256 | |
257 | // THEN |
258 | QVERIFY(fboId != 0); |
259 | |
260 | // WHEN |
261 | m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBODraw); |
262 | |
263 | // THEN |
264 | GLint error = m_func->glGetError(); |
265 | QVERIFY(error == 0); |
266 | GLint boundindFBOId = 0; |
267 | m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, params: &boundindFBOId); |
268 | QVERIFY(GLuint(boundindFBOId) == fboId); |
269 | |
270 | // WHEN |
271 | m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBORead); |
272 | |
273 | // THEN |
274 | error = m_func->glGetError(); |
275 | QVERIFY(error == 0); |
276 | boundindFBOId = 0; |
277 | m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, params: &boundindFBOId); |
278 | QVERIFY(GLuint(boundindFBOId) == fboId); |
279 | |
280 | // WHEN |
281 | m_glHelper.bindFrameBufferObject(frameBufferId: fboId, mode: GraphicsHelperInterface::FBOReadAndDraw); |
282 | |
283 | // THEN |
284 | error = m_func->glGetError(); |
285 | QVERIFY(error == 0); |
286 | boundindFBOId = 0; |
287 | m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, params: &boundindFBOId); |
288 | QVERIFY(GLuint(boundindFBOId) == fboId); |
289 | |
290 | // Cleanup |
291 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
292 | } |
293 | |
294 | void bindShaderStorageBlock() |
295 | { |
296 | if (!m_initializationSuccessful) |
297 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
298 | // Not supported by GL2 |
299 | } |
300 | |
301 | void bindUniformBlock() |
302 | { |
303 | if (!m_initializationSuccessful) |
304 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
305 | // Not supported by GL2 |
306 | } |
307 | |
308 | void blendEquation() |
309 | { |
310 | if (!m_initializationSuccessful) |
311 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
312 | |
313 | // GIVEN |
314 | GLint equation = 0; |
315 | m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, params: &equation); |
316 | QCOMPARE(equation, GL_FUNC_ADD); |
317 | |
318 | // WHEN |
319 | m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); |
320 | |
321 | // THEN |
322 | m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, params: &equation); |
323 | QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); |
324 | } |
325 | |
326 | void blendFunci() |
327 | { |
328 | if (!m_initializationSuccessful) |
329 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
330 | // Not supported by GL2 |
331 | } |
332 | |
333 | void blendFuncSeparatei() |
334 | { |
335 | if (!m_initializationSuccessful) |
336 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
337 | // Not supported by GL2 |
338 | } |
339 | |
340 | void boundFrameBufferObject() |
341 | { |
342 | if (!m_initializationSuccessful) |
343 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
344 | if (!m_fboFuncs) |
345 | QSKIP("FBO not supported by OpenGL 2.0" ); |
346 | |
347 | // GIVEN |
348 | GLuint fboId; |
349 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
350 | |
351 | // WHEN |
352 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId); |
353 | |
354 | // THEN |
355 | GLint boundBuffer = 0; |
356 | m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, params: &boundBuffer); |
357 | QCOMPARE(GLuint(boundBuffer), fboId); |
358 | |
359 | // THEN |
360 | QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); |
361 | |
362 | // Reset state |
363 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0); |
364 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
365 | } |
366 | |
367 | void checkFrameBufferComplete() |
368 | { |
369 | if (!m_initializationSuccessful) |
370 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
371 | if (!m_fboFuncs) |
372 | QSKIP("FBO not supported by OpenGL 2.0" ); |
373 | |
374 | // GIVEN |
375 | GLuint fboId; |
376 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
377 | |
378 | Attachment attachment; |
379 | attachment.m_point = QRenderTargetOutput::Color0; |
380 | |
381 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId); |
382 | |
383 | QOpenGLTexture texture(QOpenGLTexture::Target2D); |
384 | texture.setSize(width: 512, height: 512); |
385 | texture.setFormat(QOpenGLTexture::RGBA8U); |
386 | texture.setMinificationFilter(QOpenGLTexture::Linear); |
387 | texture.setMagnificationFilter(QOpenGLTexture::Linear); |
388 | texture.create(); |
389 | texture.allocateStorage(); |
390 | m_glHelper.bindFrameBufferAttachment(texture: &texture, attachment); |
391 | |
392 | // THEN |
393 | GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); |
394 | QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); |
395 | |
396 | QVERIFY(m_glHelper.checkFrameBufferComplete()); |
397 | |
398 | // Restore |
399 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0); |
400 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
401 | } |
402 | |
403 | void clearBufferf() |
404 | { |
405 | if (!m_initializationSuccessful) |
406 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
407 | // Not supported by GL2 |
408 | } |
409 | |
410 | void createFrameBufferObject() |
411 | { |
412 | if (!m_initializationSuccessful) |
413 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
414 | if (!m_fboFuncs) |
415 | QSKIP("FBO not supported by OpenGL 2.0" ); |
416 | |
417 | // WHEN |
418 | const GLuint fboId = m_glHelper.createFrameBufferObject(); |
419 | |
420 | // THEN |
421 | QVERIFY(fboId != 0); |
422 | |
423 | // Restore |
424 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
425 | } |
426 | |
427 | void depthMask() |
428 | { |
429 | if (!m_initializationSuccessful) |
430 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
431 | |
432 | // GIVEN |
433 | GLboolean depthWritingEnabled = false; |
434 | m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled); |
435 | |
436 | // THEN |
437 | QVERIFY(depthWritingEnabled); |
438 | |
439 | // WHEN |
440 | m_glHelper.depthMask(GL_FALSE); |
441 | |
442 | // THEN |
443 | m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled); |
444 | QVERIFY(!depthWritingEnabled); |
445 | |
446 | // WHEN |
447 | m_glHelper.depthMask(GL_TRUE); |
448 | |
449 | // THEN |
450 | m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, params: &depthWritingEnabled); |
451 | QVERIFY(depthWritingEnabled); |
452 | } |
453 | |
454 | void depthTest() |
455 | { |
456 | if (!m_initializationSuccessful) |
457 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
458 | |
459 | // GIVEN |
460 | m_func->glDisable(GL_DEPTH_TEST); |
461 | m_func->glDepthFunc(GL_LESS); |
462 | |
463 | // WHEN |
464 | m_glHelper.depthTest(GL_LEQUAL); |
465 | |
466 | // THEN |
467 | QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); |
468 | GLint depthMode = 0; |
469 | m_func->glGetIntegerv(GL_DEPTH_FUNC, params: &depthMode); |
470 | QCOMPARE(depthMode, GL_LEQUAL); |
471 | |
472 | // WHEN |
473 | m_glHelper.depthTest(GL_LESS); |
474 | QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); |
475 | m_func->glGetIntegerv(GL_DEPTH_FUNC, params: &depthMode); |
476 | QCOMPARE(depthMode, GL_LESS); |
477 | } |
478 | |
479 | void disableClipPlane() |
480 | { |
481 | if (!m_initializationSuccessful) |
482 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
483 | |
484 | // GIVEN |
485 | m_func->glEnable(GL_CLIP_DISTANCE0 + 5); |
486 | |
487 | // THEN |
488 | QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); |
489 | |
490 | // WHEN |
491 | m_glHelper.disableClipPlane(clipPlane: 5); |
492 | |
493 | // THEN |
494 | QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); |
495 | } |
496 | |
497 | void disablei() |
498 | { |
499 | if (!m_initializationSuccessful) |
500 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
501 | // Not supported by GL2 |
502 | } |
503 | |
504 | void disablePrimitiveRestart() |
505 | { |
506 | if (!m_initializationSuccessful) |
507 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
508 | // Not supported by GL2 |
509 | } |
510 | |
511 | void drawBuffers() |
512 | { |
513 | if (!m_initializationSuccessful) |
514 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
515 | |
516 | if (!m_fboFuncs) |
517 | QSKIP("FBO not supported by OpenGL 2.0" ); |
518 | |
519 | // GIVEN |
520 | GLuint fboId; |
521 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
522 | |
523 | // THEN |
524 | QVERIFY(fboId != 0); |
525 | |
526 | // WHEN |
527 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: fboId); |
528 | QOpenGLTexture *textures[4]; |
529 | |
530 | // Create 4 attachments |
531 | for (int i = 0; i < 4; ++i) { |
532 | Attachment attachment; |
533 | attachment.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(i); |
534 | |
535 | QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); |
536 | textures[i] = texture; |
537 | texture->setSize(width: 512, height: 512); |
538 | texture->setFormat(QOpenGLTexture::RGBA32F); |
539 | texture->setMinificationFilter(QOpenGLTexture::Linear); |
540 | texture->setMagnificationFilter(QOpenGLTexture::Linear); |
541 | texture->setWrapMode(QOpenGLTexture::ClampToEdge); |
542 | if (!texture->create()) |
543 | qWarning() << "Texture creation failed" ; |
544 | texture->allocateStorage(); |
545 | QVERIFY(texture->isStorageAllocated()); |
546 | GLint error = m_func->glGetError(); |
547 | QVERIFY(error == 0); |
548 | m_glHelper.bindFrameBufferAttachment(texture, attachment); |
549 | } |
550 | // THEN |
551 | GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); |
552 | QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); |
553 | |
554 | // WHEN |
555 | GLenum bufferEnum = GL_COLOR_ATTACHMENT4; |
556 | m_func->glDrawBuffers(n: 1, bufs: &bufferEnum); |
557 | |
558 | // THEN |
559 | GLint enumValue = -1; |
560 | m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue); |
561 | QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); |
562 | |
563 | // WHEN |
564 | GLint newBufferEnum = 2; |
565 | m_glHelper.drawBuffers(n: 1, bufs: &newBufferEnum); |
566 | |
567 | // THEN |
568 | m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue); |
569 | QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); |
570 | |
571 | // WHEN |
572 | newBufferEnum = 0; |
573 | m_glHelper.drawBuffers(n: 1, bufs: &newBufferEnum); |
574 | |
575 | // THEN |
576 | m_func->glGetIntegerv(GL_DRAW_BUFFER0, params: &enumValue); |
577 | QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); |
578 | |
579 | // Restore |
580 | m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: 0); |
581 | m_fboFuncs->glDeleteFramebuffers(n: 1, framebuffers: &fboId); |
582 | for (int i = 0; i < 4; ++i) |
583 | delete textures[i]; |
584 | } |
585 | |
586 | void enableClipPlane() |
587 | { |
588 | if (!m_initializationSuccessful) |
589 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
590 | |
591 | // GIVEN |
592 | m_func->glDisable(GL_CLIP_DISTANCE0 + 4); |
593 | |
594 | // THEN |
595 | QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); |
596 | |
597 | // WHEN |
598 | m_glHelper.enableClipPlane(clipPlane: 4); |
599 | |
600 | // THEN |
601 | QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); |
602 | } |
603 | |
604 | void enablei() |
605 | { |
606 | if (!m_initializationSuccessful) |
607 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
608 | // Not supported by GL2 |
609 | } |
610 | |
611 | void enablePrimitiveRestart() |
612 | { |
613 | if (!m_initializationSuccessful) |
614 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
615 | // Not supported by GL2 |
616 | } |
617 | |
618 | void enableVertexAttribute() |
619 | { |
620 | if (!m_initializationSuccessful) |
621 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
622 | |
623 | // GIVEN |
624 | QOpenGLVertexArrayObject vao; |
625 | vao.create(); |
626 | QOpenGLVertexArrayObject::Binder binder(&vao); |
627 | |
628 | QOpenGLShaderProgram shaderProgram; |
629 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
630 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeSamplers); |
631 | QVERIFY(shaderProgram.link()); |
632 | shaderProgram.bind(); |
633 | |
634 | // WHEN |
635 | GLint positionLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexPosition" ); |
636 | GLint texCoordLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexTexCoord" ); |
637 | m_glHelper.enableVertexAttributeArray(location: positionLocation); |
638 | m_glHelper.enableVertexAttributeArray(location: texCoordLocation); |
639 | |
640 | // THEN |
641 | const GLint error = m_func->glGetError(); |
642 | QVERIFY(error == 0); |
643 | } |
644 | |
645 | void frontFace() |
646 | { |
647 | if (!m_initializationSuccessful) |
648 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
649 | |
650 | // GIVEN |
651 | m_func->glFrontFace(GL_CW); |
652 | |
653 | // THEN |
654 | GLint face = 0; |
655 | m_func->glGetIntegerv(GL_FRONT_FACE, params: &face); |
656 | QCOMPARE(face, GL_CW); |
657 | |
658 | // WHEN |
659 | m_glHelper.frontFace(GL_CCW); |
660 | |
661 | // THEN |
662 | m_func->glGetIntegerv(GL_FRONT_FACE, params: &face); |
663 | QCOMPARE(face, GL_CCW); |
664 | } |
665 | |
666 | void getRenderBufferDimensions() |
667 | { |
668 | if (!m_initializationSuccessful) |
669 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
670 | // Not supported by GL2 |
671 | } |
672 | |
673 | void getTextureDimensions() |
674 | { |
675 | if (!m_initializationSuccessful) |
676 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
677 | |
678 | // GIVEN |
679 | QOpenGLTexture texture(QOpenGLTexture::Target2D); |
680 | texture.setSize(width: 512, height: 512); |
681 | texture.setFormat(QOpenGLTexture::RGBA8U); |
682 | texture.setMinificationFilter(QOpenGLTexture::Linear); |
683 | texture.setMagnificationFilter(QOpenGLTexture::Linear); |
684 | texture.create(); |
685 | texture.allocateStorage(); |
686 | |
687 | // WHEN |
688 | const QSize dimensions = m_glHelper.getTextureDimensions(textureId: texture.textureId(), GL_TEXTURE_2D); |
689 | |
690 | // THEN |
691 | QCOMPARE(dimensions, QSize(512, 512)); |
692 | } |
693 | |
694 | void pointSize() |
695 | { |
696 | if (!m_initializationSuccessful) |
697 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
698 | |
699 | // WHEN |
700 | m_glHelper.pointSize(programmable: false, value: 0.5f); |
701 | // THEN |
702 | GLfloat size = 0.0f; |
703 | m_func->glGetFloatv(GL_POINT_SIZE, params: &size); |
704 | QCOMPARE(size, 0.5f); |
705 | } |
706 | |
707 | void maxClipPlaneCount() |
708 | { |
709 | if (!m_initializationSuccessful) |
710 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
711 | |
712 | // GIVEN |
713 | GLint maxCount = -1; |
714 | m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, params: &maxCount); |
715 | |
716 | // THEN |
717 | QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); |
718 | } |
719 | |
720 | void programUniformBlock() |
721 | { |
722 | if (!m_initializationSuccessful) |
723 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
724 | |
725 | // Not supported by GL2 |
726 | } |
727 | |
728 | void programAttributesAndLocations() |
729 | { |
730 | if (!m_initializationSuccessful) |
731 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
732 | |
733 | // GIVEN |
734 | QOpenGLShaderProgram shaderProgram; |
735 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
736 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeSamplers); |
737 | QVERIFY(shaderProgram.link()); |
738 | |
739 | // WHEN |
740 | QVector<ShaderAttribute> activeAttributes = m_glHelper.programAttributesAndLocations(programId: shaderProgram.programId()); |
741 | |
742 | // THEN |
743 | QCOMPARE(activeAttributes.size(), 2); |
744 | std::sort(first: activeAttributes.begin(), last: activeAttributes.end(), comp: [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); |
745 | |
746 | const ShaderAttribute attribute1 = activeAttributes.at(i: 0); |
747 | QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition" )); |
748 | QCOMPARE(attribute1.m_size, 1); |
749 | QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition" )); |
750 | QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); |
751 | |
752 | const ShaderAttribute attribute2 = activeAttributes.at(i: 1); |
753 | QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord" )); |
754 | QCOMPARE(attribute2.m_size, 1); |
755 | QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord" )); |
756 | QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); |
757 | } |
758 | |
759 | void programUniformsAndLocations() |
760 | { |
761 | if (!m_initializationSuccessful) |
762 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
763 | |
764 | // GIVEN |
765 | QOpenGLShaderProgram shaderProgram; |
766 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
767 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
768 | QVERIFY(shaderProgram.link()); |
769 | |
770 | // WHEN |
771 | QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(programId: shaderProgram.programId()); |
772 | |
773 | // THEN |
774 | QCOMPARE(activeUniforms.size(), 4); |
775 | std::sort(first: activeUniforms.begin(), last: activeUniforms.end(), comp: [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); |
776 | |
777 | const ShaderUniform uniform1 = activeUniforms.at(i: 0); |
778 | QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier" )); |
779 | QCOMPARE(uniform1.m_offset, -1); |
780 | QCOMPARE(uniform1.m_blockIndex, -1); |
781 | QCOMPARE(uniform1.m_arrayStride, -1); |
782 | QCOMPARE(uniform1.m_matrixStride, -1); |
783 | QCOMPARE(uniform1.m_size, 1); |
784 | QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); |
785 | QCOMPARE(uniform1.m_name, QStringLiteral("multiplier" )); |
786 | |
787 | const ShaderUniform uniform2 = activeUniforms.at(i: 1); |
788 | QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2" )); |
789 | QCOMPARE(uniform2.m_offset, -1); |
790 | QCOMPARE(uniform2.m_blockIndex, -1); |
791 | QCOMPARE(uniform2.m_arrayStride, -1); |
792 | QCOMPARE(uniform2.m_matrixStride, -1); |
793 | QCOMPARE(uniform2.m_size, 1); |
794 | QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); |
795 | QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2" )); |
796 | |
797 | const ShaderUniform uniform3 = activeUniforms.at(i: 2); |
798 | QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3" )); |
799 | QCOMPARE(uniform3.m_offset, -1); |
800 | QCOMPARE(uniform3.m_blockIndex, -1); |
801 | QCOMPARE(uniform3.m_arrayStride, -1); |
802 | QCOMPARE(uniform3.m_matrixStride, -1); |
803 | QCOMPARE(uniform3.m_size, 1); |
804 | QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); |
805 | QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3" )); |
806 | |
807 | const ShaderUniform uniform4 = activeUniforms.at(i: 3); |
808 | QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4" )); |
809 | QCOMPARE(uniform4.m_offset, -1); |
810 | QCOMPARE(uniform4.m_blockIndex, -1); |
811 | QCOMPARE(uniform4.m_arrayStride, -1); |
812 | QCOMPARE(uniform4.m_matrixStride, -1); |
813 | QCOMPARE(uniform4.m_size, 1); |
814 | QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); |
815 | QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4" )); |
816 | } |
817 | |
818 | void programShaderStorageBlock() |
819 | { |
820 | if (!m_initializationSuccessful) |
821 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
822 | // Not supported by GL2 |
823 | } |
824 | |
825 | void releaseFrameBufferObject() |
826 | { |
827 | if (!m_initializationSuccessful) |
828 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
829 | if (!m_fboFuncs) |
830 | QSKIP("FBO not supported by OpenGL 2.0" ); |
831 | // GIVEN |
832 | GLuint fboId; |
833 | m_fboFuncs->glGenFramebuffers(n: 1, framebuffers: &fboId); |
834 | |
835 | // THEN |
836 | QVERIFY(fboId != 0); |
837 | |
838 | // WHEN |
839 | m_glHelper.releaseFrameBufferObject(frameBufferId: fboId); |
840 | |
841 | // THEN |
842 | QVERIFY(!m_fboFuncs->glIsFramebuffer(fboId)); |
843 | } |
844 | |
845 | void setMSAAEnabled() |
846 | { |
847 | if (!m_initializationSuccessful) |
848 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
849 | |
850 | // GIVEN |
851 | m_func->glDisable(GL_MULTISAMPLE); |
852 | |
853 | // THEN |
854 | QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); |
855 | |
856 | // WHEN |
857 | m_glHelper.setMSAAEnabled(true); |
858 | |
859 | // THEN |
860 | QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); |
861 | |
862 | // WHEN |
863 | m_glHelper.setMSAAEnabled(false); |
864 | |
865 | // THEN |
866 | QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); |
867 | } |
868 | |
869 | void setAlphaCoverageEnabled() |
870 | { |
871 | if (!m_initializationSuccessful) |
872 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
873 | |
874 | // GIVEN |
875 | m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); |
876 | |
877 | // THEN |
878 | QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); |
879 | |
880 | // WHEN |
881 | m_glHelper.setAlphaCoverageEnabled(true); |
882 | |
883 | // THEN |
884 | QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); |
885 | |
886 | // WHEN |
887 | m_glHelper.setAlphaCoverageEnabled(false); |
888 | |
889 | // THEN |
890 | QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); |
891 | } |
892 | |
893 | void setClipPlane() |
894 | { |
895 | if (!m_initializationSuccessful) |
896 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
897 | |
898 | // Deprecated in 3.3 core |
899 | } |
900 | |
901 | void setSeamlessCubemap() |
902 | { |
903 | if (!m_initializationSuccessful) |
904 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
905 | // Not supported in GL2 |
906 | } |
907 | |
908 | void setVerticesPerPatch() |
909 | { |
910 | // Not supported in GL2 |
911 | } |
912 | |
913 | #define SUPPORTS_FEATURE(Feature, IsSupported) \ |
914 | QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); |
915 | |
916 | void supportsFeature() |
917 | { |
918 | SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, (m_fboFuncs != nullptr)); |
919 | SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); |
920 | SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, false); |
921 | SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, false); |
922 | SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, false); |
923 | SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); |
924 | SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); |
925 | SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); |
926 | SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); |
927 | SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); |
928 | SUPPORTS_FEATURE(GraphicsHelperInterface::Tessellation, false); |
929 | SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, false); |
930 | SUPPORTS_FEATURE(GraphicsHelperInterface::IndirectDrawing, false); |
931 | SUPPORTS_FEATURE(GraphicsHelperInterface::MapBuffer, true); |
932 | SUPPORTS_FEATURE(GraphicsHelperInterface::Fences, false); |
933 | } |
934 | |
935 | |
936 | #define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ |
937 | QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; |
938 | |
939 | void uniformsByteSize_data() |
940 | { |
941 | QTest::addColumn<QByteArray>(name: "fragShader" ); |
942 | QTest::addColumn<QString>(name: "name" ); |
943 | QTest::addColumn<int>(name: "type" ); |
944 | QTest::addColumn<int>(name: "componentSize" ); |
945 | QTest::addColumn<int>(name: "expectedByteSize" ); |
946 | |
947 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier" , GL_FLOAT, 1, 4); |
948 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2" , GL_FLOAT_VEC2, 1, 4 * 2); |
949 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3" ,GL_FLOAT_VEC3, 1, 4 * 3); |
950 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4" , GL_FLOAT_VEC4, 1, 4 * 4); |
951 | |
952 | ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier" , GL_INT, 1, 4); |
953 | ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2" , GL_INT_VEC2, 1, 4 * 2); |
954 | ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3" , GL_INT_VEC3, 1, 4 * 3); |
955 | ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4" , GL_INT_VEC4, 1, 4 * 4); |
956 | |
957 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2" , GL_FLOAT_MAT2, 1, 4 * 2 * 2); |
958 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23" , GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); |
959 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32" , GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); |
960 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24" , GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); |
961 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42" , GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); |
962 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3" , GL_FLOAT_MAT3, 1, 4 * 3 * 3); |
963 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34" , GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); |
964 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43" , GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); |
965 | ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4" , GL_FLOAT_MAT4, 1, 4 * 4 * 4); |
966 | |
967 | ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1" , GL_SAMPLER_1D, 1, 4); |
968 | ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2" , GL_SAMPLER_2D, 1, 4); |
969 | ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3" , GL_SAMPLER_3D, 1, 4); |
970 | ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube" , GL_SAMPLER_CUBE, 1, 4); |
971 | } |
972 | |
973 | void uniformsByteSize() |
974 | { |
975 | if (!m_initializationSuccessful) |
976 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
977 | |
978 | // GIVEN |
979 | QFETCH(QByteArray, fragShader); |
980 | QFETCH(QString, name); |
981 | QFETCH(int, type); |
982 | QFETCH(int, componentSize); |
983 | QFETCH(int, expectedByteSize); |
984 | |
985 | QOpenGLShaderProgram shaderProgram; |
986 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
987 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragShader); |
988 | QVERIFY(shaderProgram.link()); |
989 | |
990 | GLint location = shaderProgram.uniformLocation(name); |
991 | // WHEN |
992 | const QVector<ShaderUniform> activeUniforms = m_glHelper.programUniformsAndLocations(programId: shaderProgram.programId()); |
993 | ShaderUniform matchingUniform; |
994 | for (const ShaderUniform &u : activeUniforms) { |
995 | if (u.m_location == location) { |
996 | matchingUniform = u; |
997 | break; |
998 | } |
999 | } |
1000 | |
1001 | // THEN |
1002 | QCOMPARE(matchingUniform.m_location, location); |
1003 | QCOMPARE(matchingUniform.m_type, GLuint(type)); |
1004 | QCOMPARE(matchingUniform.m_size, componentSize); |
1005 | |
1006 | // WHEN |
1007 | const int computedRawByteSize = m_glHelper.uniformByteSize(description: matchingUniform); |
1008 | |
1009 | // THEN |
1010 | QCOMPARE(expectedByteSize, computedRawByteSize); |
1011 | |
1012 | // Restore |
1013 | m_func->glUseProgram(program: 0); |
1014 | } |
1015 | |
1016 | void useProgram() |
1017 | { |
1018 | if (!m_initializationSuccessful) |
1019 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1020 | |
1021 | // GIVEN |
1022 | QOpenGLShaderProgram shaderProgram; |
1023 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1024 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
1025 | |
1026 | // THEN |
1027 | QVERIFY(shaderProgram.link()); |
1028 | |
1029 | GLint currentProg = 0; |
1030 | m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: ¤tProg); |
1031 | QVERIFY(currentProg == 0); |
1032 | |
1033 | // WHEN |
1034 | m_glHelper.useProgram(programId: shaderProgram.programId()); |
1035 | |
1036 | // THEN |
1037 | m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: ¤tProg); |
1038 | QCOMPARE(GLuint(currentProg), shaderProgram.programId()); |
1039 | |
1040 | // WHEN |
1041 | m_glHelper.useProgram(programId: 0); |
1042 | |
1043 | // THEN |
1044 | m_func->glGetIntegerv(GL_CURRENT_PROGRAM, params: ¤tProg); |
1045 | QVERIFY(currentProg == 0); |
1046 | } |
1047 | |
1048 | void vertexAttribDivisor() |
1049 | { |
1050 | if (!m_initializationSuccessful) |
1051 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1052 | // Not available in 3.2 |
1053 | } |
1054 | |
1055 | void vertexAttributePointer() |
1056 | { |
1057 | if (!m_initializationSuccessful) |
1058 | QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported" ); |
1059 | |
1060 | // GIVEN |
1061 | QOpenGLVertexArrayObject vao; |
1062 | vao.create(); |
1063 | QOpenGLVertexArrayObject::Binder binder(&vao); |
1064 | |
1065 | QOpenGLShaderProgram shaderProgram; |
1066 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1067 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeSamplers); |
1068 | QVERIFY(shaderProgram.link()); |
1069 | |
1070 | GLint positionLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexPosition" ); |
1071 | GLint texCoordLocation = m_func->glGetAttribLocation(program: shaderProgram.programId(), name: "vertexTexCoord" ); |
1072 | |
1073 | const int vertexCount = 99; |
1074 | QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); |
1075 | positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); |
1076 | positionBuffer.create(); |
1077 | positionBuffer.bind(); |
1078 | positionBuffer.allocate(count: vertexCount * sizeof(QVector3D)); |
1079 | |
1080 | QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); |
1081 | texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); |
1082 | texCoordBuffer.create(); |
1083 | texCoordBuffer.allocate(count: vertexCount * sizeof(QVector2D)); |
1084 | |
1085 | // WHEN |
1086 | shaderProgram.bind(); |
1087 | positionBuffer.bind(); |
1088 | m_glHelper.enableVertexAttributeArray(location: positionLocation); |
1089 | m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, index: positionLocation, size: 3, GL_FLOAT, GL_TRUE, stride: 0, pointer: 0); |
1090 | |
1091 | texCoordBuffer.bind(); |
1092 | m_glHelper.enableVertexAttributeArray(location: texCoordLocation); |
1093 | m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, index: texCoordLocation, size: 2, GL_FLOAT, GL_TRUE, stride: 0, pointer: 0); |
1094 | |
1095 | // THEN |
1096 | const GLint error = m_func->glGetError(); |
1097 | QVERIFY(error == 0); |
1098 | } |
1099 | |
1100 | void glUniform1fv() |
1101 | { |
1102 | if (!m_initializationSuccessful) |
1103 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1104 | |
1105 | // GIVEN |
1106 | QOpenGLShaderProgram shaderProgram; |
1107 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1108 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
1109 | QVERIFY(shaderProgram.link()); |
1110 | |
1111 | // WHEN |
1112 | m_func->glUseProgram(program: shaderProgram.programId()); |
1113 | GLfloat value = 883.0f; |
1114 | const GLint location = shaderProgram.uniformLocation(name: "multiplier" ); |
1115 | m_glHelper.glUniform1fv(location, count: 1, value: &value); |
1116 | |
1117 | // THEN |
1118 | GLfloat setValue = 0.0f; |
1119 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: &setValue); |
1120 | QCOMPARE(value, setValue); |
1121 | |
1122 | // Restore |
1123 | m_func->glUseProgram(program: 0); |
1124 | } |
1125 | |
1126 | void glUniform2fv() |
1127 | { |
1128 | if (!m_initializationSuccessful) |
1129 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1130 | |
1131 | // GIVEN |
1132 | QOpenGLShaderProgram shaderProgram; |
1133 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1134 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
1135 | QVERIFY(shaderProgram.link()); |
1136 | |
1137 | // WHEN |
1138 | m_func->glUseProgram(program: shaderProgram.programId()); |
1139 | GLfloat values[2] = { 383.0f, 427.0f }; |
1140 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec2" ); |
1141 | m_glHelper.glUniform2fv(location, count: 1, value: values); |
1142 | |
1143 | // THEN |
1144 | GLfloat setValues[2] = { 0.0f, 0.0f }; |
1145 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1146 | for (int i = 0; i < 2; ++i) |
1147 | QCOMPARE(setValues[i], values[i]); |
1148 | |
1149 | // Restore |
1150 | m_func->glUseProgram(program: 0); |
1151 | } |
1152 | |
1153 | void glUniform3fv() |
1154 | { |
1155 | if (!m_initializationSuccessful) |
1156 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1157 | |
1158 | // GIVEN |
1159 | QOpenGLShaderProgram shaderProgram; |
1160 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1161 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
1162 | QVERIFY(shaderProgram.link()); |
1163 | |
1164 | // WHEN |
1165 | m_func->glUseProgram(program: shaderProgram.programId()); |
1166 | GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; |
1167 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec3" ); |
1168 | m_glHelper.glUniform3fv(location, count: 1, value: values); |
1169 | |
1170 | // THEN |
1171 | GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; |
1172 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1173 | for (int i = 0; i < 3; ++i) |
1174 | QCOMPARE(setValues[i], values[i]); |
1175 | |
1176 | // Restore |
1177 | m_func->glUseProgram(program: 0); |
1178 | } |
1179 | |
1180 | void glUniform4fv() |
1181 | { |
1182 | if (!m_initializationSuccessful) |
1183 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1184 | |
1185 | // GIVEN |
1186 | QOpenGLShaderProgram shaderProgram; |
1187 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1188 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloat); |
1189 | QVERIFY(shaderProgram.link()); |
1190 | |
1191 | // WHEN |
1192 | m_func->glUseProgram(program: shaderProgram.programId()); |
1193 | GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; |
1194 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec4" ); |
1195 | m_glHelper.glUniform4fv(location, count: 1, value: values); |
1196 | |
1197 | // THEN |
1198 | GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; |
1199 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1200 | for (int i = 0; i < 4; ++i) |
1201 | QCOMPARE(setValues[i], values[i]); |
1202 | |
1203 | // Restore |
1204 | m_func->glUseProgram(program: 0); |
1205 | } |
1206 | |
1207 | void glUniform1iv() |
1208 | { |
1209 | if (!m_initializationSuccessful) |
1210 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1211 | |
1212 | // GIVEN |
1213 | QOpenGLShaderProgram shaderProgram; |
1214 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1215 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt); |
1216 | QVERIFY(shaderProgram.link()); |
1217 | |
1218 | // WHEN |
1219 | m_func->glUseProgram(program: shaderProgram.programId()); |
1220 | GLint value = 883; |
1221 | const GLint location = shaderProgram.uniformLocation(name: "multiplier" ); |
1222 | m_glHelper.glUniform1iv(location, count: 1, value: &value); |
1223 | |
1224 | // THEN |
1225 | GLint setValue = 0; |
1226 | m_func->glGetUniformiv(program: shaderProgram.programId(), location, params: &setValue); |
1227 | QCOMPARE(value, setValue); |
1228 | |
1229 | // Restore |
1230 | m_func->glUseProgram(program: 0); |
1231 | } |
1232 | |
1233 | void glUniform2iv() |
1234 | { |
1235 | if (!m_initializationSuccessful) |
1236 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1237 | |
1238 | // GIVEN |
1239 | QOpenGLShaderProgram shaderProgram; |
1240 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1241 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt); |
1242 | QVERIFY(shaderProgram.link()); |
1243 | |
1244 | // WHEN |
1245 | m_func->glUseProgram(program: shaderProgram.programId()); |
1246 | GLint values[2] = { 383, 427 }; |
1247 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec2" ); |
1248 | m_glHelper.glUniform2iv(location, count: 1, value: values); |
1249 | |
1250 | // THEN |
1251 | GLint setValues[2] = { 0, 0 }; |
1252 | m_func->glGetUniformiv(program: shaderProgram.programId(), location, params: setValues); |
1253 | for (int i = 0; i < 2; ++i) |
1254 | QCOMPARE(values[i], setValues[i]); |
1255 | |
1256 | // Restore |
1257 | m_func->glUseProgram(program: 0); |
1258 | } |
1259 | |
1260 | void glUniform3iv() |
1261 | { |
1262 | if (!m_initializationSuccessful) |
1263 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1264 | |
1265 | // GIVEN |
1266 | QOpenGLShaderProgram shaderProgram; |
1267 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1268 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt); |
1269 | QVERIFY(shaderProgram.link()); |
1270 | |
1271 | // WHEN |
1272 | m_func->glUseProgram(program: shaderProgram.programId()); |
1273 | GLint values[3] = { 572, 1340, 1584 }; |
1274 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec3" ); |
1275 | m_glHelper.glUniform3iv(location, count: 1, value: values); |
1276 | |
1277 | // THEN |
1278 | GLint setValues[3] = { 0, 0, 0 }; |
1279 | m_func->glGetUniformiv(program: shaderProgram.programId(), location, params: setValues); |
1280 | for (int i = 0; i < 3; ++i) |
1281 | QCOMPARE(values[i], setValues[i]); |
1282 | |
1283 | // Restore |
1284 | m_func->glUseProgram(program: 0); |
1285 | } |
1286 | |
1287 | void glUniform4iv() |
1288 | { |
1289 | if (!m_initializationSuccessful) |
1290 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1291 | |
1292 | // GIVEN |
1293 | QOpenGLShaderProgram shaderProgram; |
1294 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1295 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsInt); |
1296 | QVERIFY(shaderProgram.link()); |
1297 | |
1298 | // WHEN |
1299 | m_func->glUseProgram(program: shaderProgram.programId()); |
1300 | GLint values[4] = { 454, 350, 883, 355 }; |
1301 | const GLint location = shaderProgram.uniformLocation(name: "multiplierVec4" ); |
1302 | m_glHelper.glUniform4iv(location, count: 1, value: values); |
1303 | |
1304 | // THEN |
1305 | GLint setValues[4] = { 0, 0, 0, 0 }; |
1306 | m_func->glGetUniformiv(program: shaderProgram.programId(), location, params: setValues); |
1307 | for (int i = 0; i < 4; ++i) |
1308 | QCOMPARE(values[i], setValues[i]); |
1309 | |
1310 | // Restore |
1311 | m_func->glUseProgram(program: 0); |
1312 | } |
1313 | |
1314 | void glUniform1uiv() |
1315 | { |
1316 | if (!m_initializationSuccessful) |
1317 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1318 | // Not supported by GL2 |
1319 | } |
1320 | |
1321 | void glUniform2uiv() |
1322 | { |
1323 | if (!m_initializationSuccessful) |
1324 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1325 | // Not supported by GL2 |
1326 | } |
1327 | |
1328 | void glUniform3uiv() |
1329 | { |
1330 | if (!m_initializationSuccessful) |
1331 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1332 | // Not supported by GL2 |
1333 | } |
1334 | |
1335 | void glUniform4uiv() |
1336 | { |
1337 | if (!m_initializationSuccessful) |
1338 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1339 | // Not supported by GL2 |
1340 | } |
1341 | |
1342 | void glUniformMatrix2fv() |
1343 | { |
1344 | if (!m_initializationSuccessful) |
1345 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1346 | |
1347 | // GIVEN |
1348 | QOpenGLShaderProgram shaderProgram; |
1349 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1350 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices); |
1351 | QVERIFY(shaderProgram.link()); |
1352 | |
1353 | // WHEN |
1354 | m_func->glUseProgram(program: shaderProgram.programId()); |
1355 | GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; |
1356 | const GLint location = shaderProgram.uniformLocation(name: "m2" ); |
1357 | m_glHelper.glUniformMatrix2fv(location, count: 1, value: values); |
1358 | |
1359 | // THEN |
1360 | GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; |
1361 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1362 | for (int i = 0; i < 4; ++i) |
1363 | QCOMPARE(values[i], setValues[i]); |
1364 | |
1365 | // Restore |
1366 | m_func->glUseProgram(program: 0); |
1367 | } |
1368 | |
1369 | void glUniformMatrix3fv() |
1370 | { |
1371 | if (!m_initializationSuccessful) |
1372 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1373 | |
1374 | // GIVEN |
1375 | QOpenGLShaderProgram shaderProgram; |
1376 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1377 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices); |
1378 | QVERIFY(shaderProgram.link()); |
1379 | |
1380 | // WHEN |
1381 | m_func->glUseProgram(program: shaderProgram.programId()); |
1382 | GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; |
1383 | const GLint location = shaderProgram.uniformLocation(name: "m3" ); |
1384 | m_glHelper.glUniformMatrix3fv(location, count: 1, value: values); |
1385 | |
1386 | // THEN |
1387 | GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; |
1388 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1389 | for (int i = 0; i < 9; ++i) |
1390 | QCOMPARE(values[i], setValues[i]); |
1391 | |
1392 | // Restore |
1393 | m_func->glUseProgram(program: 0); |
1394 | } |
1395 | |
1396 | void glUniformMatrix4fv() |
1397 | { |
1398 | if (!m_initializationSuccessful) |
1399 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1400 | |
1401 | // GIVEN |
1402 | QOpenGLShaderProgram shaderProgram; |
1403 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Vertex, source: vertCode); |
1404 | shaderProgram.addShaderFromSourceCode(type: QOpenGLShader::Fragment, source: fragCodeUniformsFloatMatrices); |
1405 | QVERIFY(shaderProgram.link()); |
1406 | |
1407 | // WHEN |
1408 | m_func->glUseProgram(program: shaderProgram.programId()); |
1409 | 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 }; |
1410 | const GLint location = shaderProgram.uniformLocation(name: "m4" ); |
1411 | m_glHelper.glUniformMatrix4fv(location, count: 1, value: values); |
1412 | |
1413 | // THEN |
1414 | 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 }; |
1415 | m_func->glGetUniformfv(program: shaderProgram.programId(), location, params: setValues); |
1416 | for (int i = 0; i < 16; ++i) |
1417 | QCOMPARE(values[i], setValues[i]); |
1418 | |
1419 | // Restore |
1420 | m_func->glUseProgram(program: 0); |
1421 | } |
1422 | |
1423 | void glUniformMatrix2x3fv() |
1424 | { |
1425 | if (!m_initializationSuccessful) |
1426 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1427 | // Not supported by GL2 |
1428 | } |
1429 | |
1430 | void glUniformMatrix3x2fv() |
1431 | { |
1432 | if (!m_initializationSuccessful) |
1433 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1434 | // Not supported by GL2 |
1435 | } |
1436 | |
1437 | void glUniformMatrix2x4fv() |
1438 | { |
1439 | if (!m_initializationSuccessful) |
1440 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1441 | // Not supported by GL2 |
1442 | } |
1443 | |
1444 | void glUniformMatrix4x2fv() |
1445 | { |
1446 | if (!m_initializationSuccessful) |
1447 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1448 | // Not supported by GL2 |
1449 | } |
1450 | |
1451 | void glUniformMatrix3x4fv() |
1452 | { |
1453 | if (!m_initializationSuccessful) |
1454 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1455 | // Not supported by GL2 |
1456 | } |
1457 | |
1458 | void glUniformMatrix4x3fv() |
1459 | { |
1460 | if (!m_initializationSuccessful) |
1461 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1462 | // Not supported by GL2 |
1463 | } |
1464 | |
1465 | void blitFramebuffer() |
1466 | { |
1467 | if (!m_initializationSuccessful) |
1468 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1469 | // Not supported by GL2 |
1470 | } |
1471 | |
1472 | #define ADD_GL_TYPE_ENTRY(Type, Expected) \ |
1473 | QTest::newRow(#Type) << Type << Expected; |
1474 | |
1475 | void uniformTypeFromGLType_data() |
1476 | { |
1477 | QTest::addColumn<int>(name: "glType" ); |
1478 | QTest::addColumn<UniformType>(name: "expected" ); |
1479 | |
1480 | ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); |
1481 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); |
1482 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); |
1483 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); |
1484 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); |
1485 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); |
1486 | ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); |
1487 | ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); |
1488 | ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); |
1489 | ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); |
1490 | ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); |
1491 | ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); |
1492 | ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); |
1493 | ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); |
1494 | ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); |
1495 | ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); |
1496 | ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); |
1497 | ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); |
1498 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); |
1499 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); |
1500 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); |
1501 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); |
1502 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); |
1503 | ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); |
1504 | } |
1505 | |
1506 | void uniformTypeFromGLType() |
1507 | { |
1508 | // GIVEN |
1509 | QFETCH(int, glType); |
1510 | QFETCH(UniformType, expected); |
1511 | |
1512 | // WHEN |
1513 | UniformType computed = m_glHelper.uniformTypeFromGLType(glType); |
1514 | |
1515 | // THEN |
1516 | QCOMPARE(computed, expected); |
1517 | } |
1518 | |
1519 | void drawBuffer() |
1520 | { |
1521 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1522 | // Not supported by GL2 |
1523 | } |
1524 | |
1525 | void readBuffer() |
1526 | { |
1527 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1528 | // Not supported by GL2 |
1529 | } |
1530 | |
1531 | void fenceSync() |
1532 | { |
1533 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1534 | // Not supported by GL2 |
1535 | } |
1536 | |
1537 | void clientWaitSync() |
1538 | { |
1539 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1540 | // Not supported by GL2 |
1541 | } |
1542 | |
1543 | void waitSync() |
1544 | { |
1545 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1546 | // Not supported by GL2 |
1547 | } |
1548 | |
1549 | void wasSyncSignaled() |
1550 | { |
1551 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1552 | // Not supported by GL2 |
1553 | } |
1554 | |
1555 | void deleteSync() |
1556 | { |
1557 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1558 | // Not supported by GL2 |
1559 | } |
1560 | |
1561 | void rasterMode() |
1562 | { |
1563 | if (!m_initializationSuccessful) |
1564 | QSKIP("Initialization failed, OpenGL 2.0 functions not supported" ); |
1565 | |
1566 | m_func->glGetError(); |
1567 | |
1568 | // WHEN |
1569 | m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); |
1570 | |
1571 | // THEN |
1572 | const GLint error = m_func->glGetError(); |
1573 | QVERIFY(error == 0); |
1574 | GLint p; |
1575 | m_func->glGetIntegerv(GL_POLYGON_MODE, params: &p); |
1576 | QCOMPARE(p, GL_LINE); |
1577 | } |
1578 | |
1579 | private: |
1580 | QScopedPointer<QWindow> m_window; |
1581 | QOpenGLContext m_glContext; |
1582 | GraphicsHelperGL2 m_glHelper; |
1583 | QOpenGLFunctions_2_0 *m_func = nullptr; |
1584 | QOpenGLExtension_ARB_framebuffer_object *m_fboFuncs = nullptr; |
1585 | bool m_initializationSuccessful = false; |
1586 | }; |
1587 | |
1588 | QT_END_NAMESPACE |
1589 | |
1590 | #endif |
1591 | |
1592 | int main(int argc, char *argv[]) |
1593 | { |
1594 | #ifdef TEST_SHOULD_BE_PERFORMED |
1595 | QGuiApplication app(argc, argv); |
1596 | app.setAttribute(attribute: Qt::AA_Use96Dpi, on: true); |
1597 | tst_GraphicsHelperGL2 tc; |
1598 | QTEST_SET_MAIN_SOURCE_PATH |
1599 | return QTest::qExec(testObject: &tc, argc, argv); |
1600 | #endif |
1601 | return 0; |
1602 | } |
1603 | |
1604 | #ifdef TEST_SHOULD_BE_PERFORMED |
1605 | #include "tst_graphicshelpergl2.moc" |
1606 | #endif |
1607 | |