1 | // Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
---|---|
2 | // Copyright (C) 2016 Svenn-Arne Dragly. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include "graphicshelperes3_p.h" |
6 | #include <private/attachmentpack_p.h> |
7 | #include <qgraphicsutils_p.h> |
8 | #include <logging_p.h> |
9 | #include <QOpenGLExtraFunctions> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | // ES 3.0+ |
14 | #ifndef GL_SAMPLER_3D |
15 | #define GL_SAMPLER_3D 0x8B5F |
16 | #endif |
17 | #ifndef GL_SAMPLER_2D_SHADOW |
18 | #define GL_SAMPLER_2D_SHADOW 0x8B62 |
19 | #endif |
20 | #ifndef GL_SAMPLER_CUBE_SHADOW |
21 | #define GL_SAMPLER_CUBE_SHADOW 0x8DC5 |
22 | #endif |
23 | #ifndef GL_SAMPLER_2D_ARRAY |
24 | #define GL_SAMPLER_2D_ARRAY 0x8DC1 |
25 | #endif |
26 | #ifndef GL_SAMPLER_2D_ARRAY_SHADOW |
27 | #define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 |
28 | #endif |
29 | #ifndef GL_FLOAT_MAT2x3 |
30 | #define GL_FLOAT_MAT2x3 0x8B65 |
31 | #endif |
32 | #ifndef GL_FLOAT_MAT2x4 |
33 | #define GL_FLOAT_MAT2x4 0x8B66 |
34 | #endif |
35 | #ifndef GL_FLOAT_MAT3x2 |
36 | #define GL_FLOAT_MAT3x2 0x8B67 |
37 | #endif |
38 | #ifndef GL_FLOAT_MAT3x4 |
39 | #define GL_FLOAT_MAT3x4 0x8B68 |
40 | #endif |
41 | #ifndef GL_FLOAT_MAT4x2 |
42 | #define GL_FLOAT_MAT4x2 0x8B69 |
43 | #endif |
44 | #ifndef GL_FLOAT_MAT4x3 |
45 | #define GL_FLOAT_MAT4x3 0x8B6A |
46 | #endif |
47 | #ifndef GL_UNSIGNED_INT_VEC2 |
48 | #define GL_UNSIGNED_INT_VEC2 0x8DC6 |
49 | #endif |
50 | #ifndef GL_UNSIGNED_INT_VEC3 |
51 | #define GL_UNSIGNED_INT_VEC3 0x8DC7 |
52 | #endif |
53 | #ifndef GL_UNSIGNED_INT_VEC4 |
54 | #define GL_UNSIGNED_INT_VEC4 0x8DC8 |
55 | #endif |
56 | #ifndef GL_INT_SAMPLER_2D |
57 | #define GL_INT_SAMPLER_2D 0x8DCA |
58 | #endif |
59 | #ifndef GL_INT_SAMPLER_3D |
60 | #define GL_INT_SAMPLER_3D 0x8DCB |
61 | #endif |
62 | #ifndef GL_INT_SAMPLER_CUBE |
63 | #define GL_INT_SAMPLER_CUBE 0x8DCC |
64 | #endif |
65 | #ifndef GL_INT_SAMPLER_2D_ARRAY |
66 | #define GL_INT_SAMPLER_2D_ARRAY 0x8DCF |
67 | #endif |
68 | #ifndef GL_UNSIGNED_INT_SAMPLER_2D |
69 | #define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 |
70 | #endif |
71 | #ifndef GL_UNSIGNED_INT_SAMPLER_3D |
72 | #define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 |
73 | #endif |
74 | #ifndef GL_UNSIGNED_INT_SAMPLER_CUBE |
75 | #define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 |
76 | #endif |
77 | #ifndef GL_UNSIGNED_INT_SAMPLER_2D_ARRAY |
78 | #define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 |
79 | #endif |
80 | |
81 | #ifndef GL_ACTIVE_UNIFORM_BLOCKS |
82 | #define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 |
83 | #endif |
84 | #ifndef GL_UNIFORM_BLOCK_INDEX |
85 | #define GL_UNIFORM_BLOCK_INDEX 0x8A3A |
86 | #endif |
87 | #ifndef GL_UNIFORM_OFFSET |
88 | #define GL_UNIFORM_OFFSET 0x8A3B |
89 | #endif |
90 | #ifndef GL_UNIFORM_ARRAY_STRIDE |
91 | #define GL_UNIFORM_ARRAY_STRIDE 0x8A3C |
92 | #endif |
93 | #ifndef GL_UNIFORM_MATRIX_STRIDE |
94 | #define GL_UNIFORM_MATRIX_STRIDE 0x8A3D |
95 | #endif |
96 | #ifndef GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS |
97 | #define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 |
98 | #endif |
99 | #ifndef GL_UNIFORM_BLOCK_BINDING |
100 | #define GL_UNIFORM_BLOCK_BINDING 0x8A3F |
101 | #endif |
102 | #ifndef GL_UNIFORM_BLOCK_DATA_SIZE |
103 | #define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 |
104 | #endif |
105 | |
106 | #ifndef GL_DRAW_FRAMEBUFFER |
107 | #define GL_DRAW_FRAMEBUFFER 0x8CA9 |
108 | #endif |
109 | |
110 | #ifndef GL_READ_FRAMEBUFFER |
111 | #define GL_READ_FRAMEBUFFER 0x8CA8 |
112 | #endif |
113 | |
114 | #ifndef GL_SIGNALED |
115 | #define GL_SIGNALED 0x9119 |
116 | #endif |
117 | |
118 | #ifndef GL_SYNC_STATUS |
119 | #define GL_SYNC_STATUS 0x9114 |
120 | #endif |
121 | |
122 | #ifndef GL_TIMEOUT_IGNORED |
123 | #define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull |
124 | #endif |
125 | |
126 | #ifndef GL_SYNC_GPU_COMMANDS_COMPLETE |
127 | #define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 |
128 | #endif |
129 | |
130 | #ifndef GL_SYNC_FLUSH_COMMANDS_BIT |
131 | #define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 |
132 | #endif |
133 | |
134 | namespace Qt3DRender { |
135 | namespace Render { |
136 | namespace OpenGL { |
137 | |
138 | GraphicsHelperES3::GraphicsHelperES3() |
139 | { |
140 | } |
141 | |
142 | GraphicsHelperES3::~GraphicsHelperES3() |
143 | { |
144 | } |
145 | |
146 | void GraphicsHelperES3::initializeHelper(QOpenGLContext *context, |
147 | QAbstractOpenGLFunctions *functions) |
148 | { |
149 | GraphicsHelperES2::initializeHelper(context, functions); |
150 | m_extraFuncs = context->extraFunctions(); |
151 | Q_ASSERT(m_extraFuncs); |
152 | } |
153 | |
154 | void GraphicsHelperES3::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, |
155 | GLsizei primitiveCount, |
156 | GLint indexType, |
157 | void *indices, |
158 | GLsizei instances, |
159 | GLint baseVertex, |
160 | GLint baseInstance) |
161 | { |
162 | if (baseInstance != 0) |
163 | qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3"; |
164 | |
165 | if (baseVertex != 0) |
166 | qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 3"; |
167 | |
168 | m_extraFuncs->glDrawElementsInstanced(mode: primitiveType, |
169 | count: primitiveCount, |
170 | type: indexType, |
171 | indices, |
172 | instancecount: instances); |
173 | } |
174 | |
175 | void GraphicsHelperES3::vertexAttribDivisor(GLuint index, GLuint divisor) |
176 | { |
177 | m_extraFuncs->glVertexAttribDivisor(index, divisor); |
178 | } |
179 | |
180 | void GraphicsHelperES3::vertexAttributePointer(GLenum shaderDataType, |
181 | GLuint index, |
182 | GLint size, |
183 | GLenum type, |
184 | GLboolean normalized, |
185 | GLsizei stride, |
186 | const GLvoid *pointer) |
187 | { |
188 | switch (shaderDataType) { |
189 | case GL_FLOAT: |
190 | case GL_FLOAT_VEC2: |
191 | case GL_FLOAT_VEC3: |
192 | case GL_FLOAT_VEC4: |
193 | case GL_FLOAT_MAT2: |
194 | case GL_FLOAT_MAT2x3: |
195 | case GL_FLOAT_MAT2x4: |
196 | case GL_FLOAT_MAT3: |
197 | case GL_FLOAT_MAT3x2: |
198 | case GL_FLOAT_MAT3x4: |
199 | case GL_FLOAT_MAT4x2: |
200 | case GL_FLOAT_MAT4x3: |
201 | case GL_FLOAT_MAT4: |
202 | m_funcs->glVertexAttribPointer(indx: index, size, type, normalized, stride, ptr: pointer); |
203 | break; |
204 | |
205 | case GL_INT: |
206 | case GL_INT_VEC2: |
207 | case GL_INT_VEC3: |
208 | case GL_INT_VEC4: |
209 | case GL_UNSIGNED_INT: |
210 | case GL_UNSIGNED_INT_VEC2: |
211 | case GL_UNSIGNED_INT_VEC3: |
212 | case GL_UNSIGNED_INT_VEC4: |
213 | m_extraFuncs->glVertexAttribIPointer(index, size, type, stride, pointer); |
214 | break; |
215 | |
216 | default: |
217 | qCWarning(Rendering) << "vertexAttribPointer: Unhandled type"; |
218 | Q_UNREACHABLE(); |
219 | } |
220 | } |
221 | |
222 | void GraphicsHelperES3::drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) |
223 | { |
224 | m_extraFuncs->glDrawArraysInstanced(mode: primitiveType, |
225 | first, |
226 | count, |
227 | instancecount: instances); |
228 | } |
229 | |
230 | void GraphicsHelperES3::drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) |
231 | { |
232 | if (baseInstance != 0) |
233 | qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 3"; |
234 | |
235 | m_extraFuncs->glDrawArraysInstanced(mode: primitiveType, |
236 | first, |
237 | count, |
238 | instancecount: instances); |
239 | } |
240 | |
241 | void GraphicsHelperES3::readBuffer(GLenum mode) |
242 | { |
243 | m_extraFuncs->glReadBuffer(src: mode); |
244 | } |
245 | |
246 | void GraphicsHelperES3::drawBuffer(GLenum mode) |
247 | { |
248 | Q_UNUSED(mode); |
249 | qWarning() << "glDrawBuffer is not supported with OpenGL ES 3"; |
250 | } |
251 | |
252 | void GraphicsHelperES3::bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) |
253 | { |
254 | GLenum attr = GL_COLOR_ATTACHMENT0; |
255 | |
256 | if (attachment.m_point <= QRenderTargetOutput::Color15) |
257 | attr = GL_COLOR_ATTACHMENT0 + attachment.m_point; |
258 | else if (attachment.m_point == QRenderTargetOutput::Depth) |
259 | attr = GL_DEPTH_ATTACHMENT; |
260 | else if (attachment.m_point == QRenderTargetOutput::Stencil) |
261 | attr = GL_STENCIL_ATTACHMENT; |
262 | else |
263 | qCritical() << "Unsupported FBO attachment OpenGL ES 3.0"; |
264 | |
265 | const QOpenGLTexture::Target target = texture->target(); |
266 | |
267 | if (target == QOpenGLTexture::TargetCubeMap && attachment.m_face == QAbstractTexture::AllFaces) { |
268 | qWarning() << "OpenGL ES 3.0 doesn't handle attaching all the faces of a cube map texture at once to an FBO"; |
269 | return; |
270 | } |
271 | |
272 | texture->bind(); |
273 | if (target == QOpenGLTexture::Target2D) |
274 | m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment: attr, textarget: target, texture: texture->textureId(), level: attachment.m_mipLevel); |
275 | else if (target == QOpenGLTexture::TargetCubeMap) |
276 | m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment: attr, textarget: attachment.m_face, texture: texture->textureId(), level: attachment.m_mipLevel); |
277 | else |
278 | qCritical() << "Unsupported Texture FBO attachment format"; |
279 | texture->release(); |
280 | } |
281 | |
282 | void GraphicsHelperES3::bindFrameBufferObject(GLuint frameBufferId, GraphicsHelperInterface::FBOBindMode mode) |
283 | { |
284 | switch (mode) { |
285 | case FBODraw: |
286 | m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer: frameBufferId); |
287 | return; |
288 | case FBORead: |
289 | m_funcs->glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer: frameBufferId); |
290 | return; |
291 | case FBOReadAndDraw: |
292 | default: |
293 | m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: frameBufferId); |
294 | return; |
295 | } |
296 | } |
297 | |
298 | bool GraphicsHelperES3::supportsFeature(GraphicsHelperInterface::Feature feature) const |
299 | { |
300 | switch (feature) { |
301 | case RenderBufferDimensionRetrieval: |
302 | case MRT: |
303 | case BlitFramebuffer: |
304 | case UniformBufferObject: |
305 | case MapBuffer: |
306 | case Fences: |
307 | return true; |
308 | default: |
309 | return false; |
310 | } |
311 | } |
312 | |
313 | void GraphicsHelperES3::drawBuffers(GLsizei n, const GLenum *bufs) |
314 | { |
315 | m_extraFuncs->glDrawBuffers(n, bufs); |
316 | } |
317 | |
318 | UniformType GraphicsHelperES3::uniformTypeFromGLType(GLenum glType) |
319 | { |
320 | switch (glType) { |
321 | case GL_SAMPLER_3D: |
322 | case GL_SAMPLER_2D_SHADOW: |
323 | case GL_SAMPLER_CUBE_SHADOW: |
324 | case GL_SAMPLER_2D_ARRAY: |
325 | case GL_SAMPLER_2D_ARRAY_SHADOW: |
326 | return UniformType::Sampler; |
327 | default: |
328 | return GraphicsHelperES2::uniformTypeFromGLType(glType); |
329 | } |
330 | } |
331 | |
332 | uint GraphicsHelperES3::uniformByteSize(const ShaderUniform &description) |
333 | { |
334 | uint rawByteSize = 0; |
335 | int arrayStride = qMax(a: description.m_arrayStride, b: 0); |
336 | int matrixStride = qMax(a: description.m_matrixStride, b: 0); |
337 | |
338 | switch (description.m_type) { |
339 | |
340 | case GL_FLOAT_VEC2: |
341 | case GL_INT_VEC2: |
342 | case GL_UNSIGNED_INT_VEC2: |
343 | rawByteSize = 8; |
344 | break; |
345 | |
346 | case GL_FLOAT_VEC3: |
347 | case GL_INT_VEC3: |
348 | case GL_UNSIGNED_INT_VEC3: |
349 | rawByteSize = 12; |
350 | break; |
351 | |
352 | case GL_FLOAT_VEC4: |
353 | case GL_INT_VEC4: |
354 | case GL_UNSIGNED_INT_VEC4: |
355 | rawByteSize = 16; |
356 | break; |
357 | |
358 | case GL_FLOAT_MAT2: |
359 | rawByteSize = matrixStride ? 2 * matrixStride : 16; |
360 | break; |
361 | |
362 | case GL_FLOAT_MAT2x4: |
363 | rawByteSize = matrixStride ? 2 * matrixStride : 32; |
364 | break; |
365 | |
366 | case GL_FLOAT_MAT4x2: |
367 | rawByteSize = matrixStride ? 4 * matrixStride : 32; |
368 | break; |
369 | |
370 | case GL_FLOAT_MAT3: |
371 | rawByteSize = matrixStride ? 3 * matrixStride : 36; |
372 | break; |
373 | |
374 | case GL_FLOAT_MAT2x3: |
375 | rawByteSize = matrixStride ? 2 * matrixStride : 24; |
376 | break; |
377 | |
378 | case GL_FLOAT_MAT3x2: |
379 | rawByteSize = matrixStride ? 3 * matrixStride : 24; |
380 | break; |
381 | |
382 | case GL_FLOAT_MAT4: |
383 | rawByteSize = matrixStride ? 4 * matrixStride : 64; |
384 | break; |
385 | |
386 | case GL_FLOAT_MAT4x3: |
387 | rawByteSize = matrixStride ? 4 * matrixStride : 48; |
388 | break; |
389 | |
390 | case GL_FLOAT_MAT3x4: |
391 | rawByteSize = matrixStride ? 3 * matrixStride : 48; |
392 | break; |
393 | |
394 | case GL_BOOL: |
395 | rawByteSize = 1; |
396 | break; |
397 | |
398 | case GL_BOOL_VEC2: |
399 | rawByteSize = 2; |
400 | break; |
401 | |
402 | case GL_BOOL_VEC3: |
403 | rawByteSize = 3; |
404 | break; |
405 | |
406 | case GL_BOOL_VEC4: |
407 | rawByteSize = 4; |
408 | break; |
409 | |
410 | case GL_INT: |
411 | case GL_FLOAT: |
412 | case GL_UNSIGNED_INT: |
413 | case GL_SAMPLER_2D: |
414 | case GL_SAMPLER_3D: |
415 | case GL_SAMPLER_CUBE: |
416 | case GL_INT_SAMPLER_2D: |
417 | case GL_INT_SAMPLER_3D: |
418 | case GL_INT_SAMPLER_CUBE: |
419 | case GL_UNSIGNED_INT_SAMPLER_2D: |
420 | case GL_UNSIGNED_INT_SAMPLER_3D: |
421 | case GL_UNSIGNED_INT_SAMPLER_CUBE: |
422 | case GL_SAMPLER_2D_SHADOW: |
423 | case GL_SAMPLER_CUBE_SHADOW: |
424 | case GL_SAMPLER_2D_ARRAY: |
425 | case GL_INT_SAMPLER_2D_ARRAY: |
426 | case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: |
427 | case GL_SAMPLER_2D_ARRAY_SHADOW: |
428 | rawByteSize = 4; |
429 | break; |
430 | } |
431 | |
432 | return arrayStride ? rawByteSize * arrayStride : rawByteSize; |
433 | } |
434 | |
435 | void *GraphicsHelperES3::fenceSync() |
436 | { |
437 | return m_extraFuncs->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, flags: 0); |
438 | } |
439 | |
440 | void GraphicsHelperES3::clientWaitSync(void *sync, GLuint64 nanoSecTimeout) |
441 | { |
442 | m_extraFuncs->glClientWaitSync(sync: static_cast<GLsync>(sync), GL_SYNC_FLUSH_COMMANDS_BIT, timeout: nanoSecTimeout); |
443 | } |
444 | |
445 | void GraphicsHelperES3::waitSync(void *sync) |
446 | { |
447 | m_extraFuncs->glWaitSync(sync: static_cast<GLsync>(sync), flags: 0, GL_TIMEOUT_IGNORED); |
448 | } |
449 | |
450 | bool GraphicsHelperES3::wasSyncSignaled(void *sync) |
451 | { |
452 | GLint v; |
453 | m_extraFuncs->glGetSynciv(sync: static_cast<GLsync>(sync), |
454 | GL_SYNC_STATUS, |
455 | bufSize: sizeof(v), |
456 | length: nullptr, |
457 | values: &v); |
458 | return v == GL_SIGNALED; |
459 | } |
460 | |
461 | void GraphicsHelperES3::deleteSync(void *sync) |
462 | { |
463 | m_extraFuncs->glDeleteSync(sync: static_cast<GLsync>(sync)); |
464 | } |
465 | |
466 | void GraphicsHelperES3::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) |
467 | { |
468 | m_extraFuncs->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); |
469 | } |
470 | |
471 | void GraphicsHelperES3::bindBufferBase(GLenum target, GLuint index, GLuint buffer) |
472 | { |
473 | m_extraFuncs->glBindBufferBase(target, index, buffer); |
474 | } |
475 | |
476 | bool GraphicsHelperES3::frameBufferNeedsRenderBuffer(const Attachment &attachment) |
477 | { |
478 | // Use a renderbuffer for combined depth+stencil attachments since this is |
479 | // problematic before GLES 3.2. Keep using textures for everything else. |
480 | return attachment.m_point == QRenderTargetOutput::DepthStencil; |
481 | } |
482 | |
483 | void GraphicsHelperES3::bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) |
484 | { |
485 | m_extraFuncs->glUniformBlockBinding(program: programId, uniformBlockIndex, uniformBlockBinding); |
486 | } |
487 | |
488 | void GraphicsHelperES3::buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) |
489 | { |
490 | char *bufferData = buffer.data(); |
491 | |
492 | switch (description.m_type) { |
493 | |
494 | case GL_FLOAT: { |
495 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 1); |
496 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 1); |
497 | break; |
498 | } |
499 | |
500 | case GL_FLOAT_VEC2: { |
501 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 2); |
502 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 2); |
503 | break; |
504 | } |
505 | |
506 | case GL_FLOAT_VEC3: { |
507 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 3); |
508 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 3); |
509 | break; |
510 | } |
511 | |
512 | case GL_FLOAT_VEC4: { |
513 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 4); |
514 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 4); |
515 | break; |
516 | } |
517 | |
518 | case GL_FLOAT_MAT2: { |
519 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 4); |
520 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 2, rows: 2); |
521 | break; |
522 | } |
523 | |
524 | case GL_FLOAT_MAT2x3: { |
525 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 6); |
526 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 2, rows: 3); |
527 | break; |
528 | } |
529 | |
530 | case GL_FLOAT_MAT2x4: { |
531 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 8); |
532 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 2, rows: 4); |
533 | break; |
534 | } |
535 | |
536 | case GL_FLOAT_MAT3: { |
537 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 9); |
538 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 3, rows: 3); |
539 | break; |
540 | } |
541 | |
542 | case GL_FLOAT_MAT3x2: { |
543 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 6); |
544 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 3, rows: 2); |
545 | break; |
546 | } |
547 | |
548 | case GL_FLOAT_MAT3x4: { |
549 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 12); |
550 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 3, rows: 4); |
551 | break; |
552 | } |
553 | |
554 | case GL_FLOAT_MAT4: { |
555 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 16); |
556 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 4, rows: 4); |
557 | break; |
558 | } |
559 | |
560 | case GL_FLOAT_MAT4x2: { |
561 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 8); |
562 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 4, rows: 2); |
563 | break; |
564 | } |
565 | |
566 | case GL_FLOAT_MAT4x3: { |
567 | const GLfloat *data = QGraphicsUtils::valueArrayFromVariant<GLfloat>(v, count: description.m_size, tupleSize: 12); |
568 | QGraphicsUtils::fillDataMatrixArray(buffer: bufferData, data, description, cols: 4, rows: 3); |
569 | break; |
570 | } |
571 | |
572 | case GL_INT: { |
573 | const GLint *data = QGraphicsUtils::valueArrayFromVariant<GLint>(v, count: description.m_size, tupleSize: 1); |
574 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 1); |
575 | break; |
576 | } |
577 | |
578 | case GL_INT_VEC2: { |
579 | const GLint *data = QGraphicsUtils::valueArrayFromVariant<GLint>(v, count: description.m_size, tupleSize: 2); |
580 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 2); |
581 | break; |
582 | } |
583 | |
584 | case GL_INT_VEC3: { |
585 | const GLint *data = QGraphicsUtils::valueArrayFromVariant<GLint>(v, count: description.m_size, tupleSize: 3); |
586 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 3); |
587 | break; |
588 | } |
589 | |
590 | case GL_INT_VEC4: { |
591 | const GLint *data = QGraphicsUtils::valueArrayFromVariant<GLint>(v, count: description.m_size, tupleSize: 4); |
592 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 4); |
593 | break; |
594 | } |
595 | |
596 | case GL_UNSIGNED_INT: { |
597 | const GLuint *data = QGraphicsUtils::valueArrayFromVariant<GLuint>(v, count: description.m_size, tupleSize: 1); |
598 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 1); |
599 | break; |
600 | } |
601 | |
602 | case GL_UNSIGNED_INT_VEC2: { |
603 | const GLuint *data = QGraphicsUtils::valueArrayFromVariant<GLuint>(v, count: description.m_size, tupleSize: 2); |
604 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 2); |
605 | break; |
606 | } |
607 | |
608 | case GL_UNSIGNED_INT_VEC3: { |
609 | const GLuint *data = QGraphicsUtils::valueArrayFromVariant<GLuint>(v, count: description.m_size, tupleSize: 3); |
610 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 3); |
611 | break; |
612 | } |
613 | |
614 | case GL_UNSIGNED_INT_VEC4: { |
615 | const GLuint *data = QGraphicsUtils::valueArrayFromVariant<GLuint>(v, count: description.m_size, tupleSize: 4); |
616 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 4); |
617 | break; |
618 | } |
619 | |
620 | case GL_BOOL: { |
621 | const GLboolean *data = QGraphicsUtils::valueArrayFromVariant<GLboolean>(v, count: description.m_size, tupleSize: 1); |
622 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 1); |
623 | break; |
624 | } |
625 | |
626 | case GL_BOOL_VEC2: { |
627 | const GLboolean *data = QGraphicsUtils::valueArrayFromVariant<GLboolean>(v, count: description.m_size, tupleSize: 2); |
628 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 2); |
629 | break; |
630 | } |
631 | |
632 | case GL_BOOL_VEC3: { |
633 | const GLboolean *data = QGraphicsUtils::valueArrayFromVariant<GLboolean>(v, count: description.m_size, tupleSize: 3); |
634 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 3); |
635 | break; |
636 | } |
637 | |
638 | case GL_BOOL_VEC4: { |
639 | const GLboolean *data = QGraphicsUtils::valueArrayFromVariant<GLboolean>(v, count: description.m_size, tupleSize: 4); |
640 | QGraphicsUtils::fillDataArray(buffer: bufferData, data, description, tupleSize: 4); |
641 | break; |
642 | } |
643 | |
644 | // note: only GLES 3.0 supported types, not the same as OpenGL proper |
645 | // (also, no MS samplers before ES 3.1) |
646 | case GL_SAMPLER_2D: |
647 | case GL_SAMPLER_3D: |
648 | case GL_SAMPLER_CUBE: |
649 | case GL_INT_SAMPLER_2D: |
650 | case GL_INT_SAMPLER_3D: |
651 | case GL_INT_SAMPLER_CUBE: |
652 | case GL_UNSIGNED_INT_SAMPLER_2D: |
653 | case GL_UNSIGNED_INT_SAMPLER_3D: |
654 | case GL_UNSIGNED_INT_SAMPLER_CUBE: |
655 | case GL_SAMPLER_2D_SHADOW: |
656 | case GL_SAMPLER_CUBE_SHADOW: |
657 | case GL_SAMPLER_2D_ARRAY: |
658 | case GL_INT_SAMPLER_2D_ARRAY: |
659 | case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: |
660 | case GL_SAMPLER_2D_ARRAY_SHADOW: |
661 | { |
662 | Q_ASSERT(description.m_size == 1); |
663 | int value = v.toInt(); |
664 | QGraphicsUtils::fillDataArray<GLint>(buffer: bufferData, data: &value, description, tupleSize: 1); |
665 | break; |
666 | } |
667 | |
668 | default: |
669 | qWarning() << Q_FUNC_INFO << "unsupported uniform type:"<< description.m_type << "for "<< description.m_name; |
670 | break; |
671 | } |
672 | } |
673 | |
674 | char *GraphicsHelperES3::mapBuffer(GLenum target, GLsizeiptr size) |
675 | { |
676 | return static_cast<char*>(m_extraFuncs->glMapBufferRange(target, offset: 0, length: size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); |
677 | } |
678 | |
679 | GLboolean GraphicsHelperES3::unmapBuffer(GLenum target) |
680 | { |
681 | return m_extraFuncs->glUnmapBuffer(target); |
682 | } |
683 | |
684 | std::vector<ShaderUniform> GraphicsHelperES3::programUniformsAndLocations(GLuint programId) |
685 | { |
686 | std::vector<ShaderUniform> uniforms; |
687 | |
688 | GLint nbrActiveUniforms = 0; |
689 | m_funcs->glGetProgramiv(program: programId, GL_ACTIVE_UNIFORMS, params: &nbrActiveUniforms); |
690 | uniforms.reserve(n: nbrActiveUniforms); |
691 | char uniformName[256]; |
692 | for (GLint i = 0; i < nbrActiveUniforms; i++) { |
693 | ShaderUniform uniform; |
694 | GLsizei uniformNameLength = 0; |
695 | // Size is 1 for scalar and more for struct or arrays |
696 | // Type is the GL Type |
697 | m_funcs->glGetActiveUniform(program: programId, index: i, bufsize: sizeof(uniformName) - 1, length: &uniformNameLength, |
698 | size: &uniform.m_size, type: &uniform.m_type, name: uniformName); |
699 | uniformName[sizeof(uniformName) - 1] = '\0'; |
700 | uniform.m_location = m_funcs->glGetUniformLocation(program: programId, name: uniformName); |
701 | uniform.m_name = QString::fromUtf8(utf8: uniformName, size: uniformNameLength); |
702 | m_extraFuncs->glGetActiveUniformsiv(program: programId, uniformCount: 1, uniformIndices: (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, params: &uniform.m_blockIndex); |
703 | m_extraFuncs->glGetActiveUniformsiv(program: programId, uniformCount: 1, uniformIndices: (GLuint*)&i, GL_UNIFORM_OFFSET, params: &uniform.m_offset); |
704 | m_extraFuncs->glGetActiveUniformsiv(program: programId, uniformCount: 1, uniformIndices: (GLuint*)&i, GL_UNIFORM_ARRAY_STRIDE, params: &uniform.m_arrayStride); |
705 | m_extraFuncs->glGetActiveUniformsiv(program: programId, uniformCount: 1, uniformIndices: (GLuint*)&i, GL_UNIFORM_MATRIX_STRIDE, params: &uniform.m_matrixStride); |
706 | uniform.m_rawByteSize = uniformByteSize(description: uniform); |
707 | uniforms.push_back(x: uniform); |
708 | qCDebug(Rendering) << uniform.m_name << "size"<< uniform.m_size |
709 | << " offset"<< uniform.m_offset |
710 | << " rawSize"<< uniform.m_rawByteSize; |
711 | } |
712 | |
713 | return uniforms; |
714 | } |
715 | |
716 | std::vector<ShaderUniformBlock> GraphicsHelperES3::programUniformBlocks(GLuint programId) |
717 | { |
718 | std::vector<ShaderUniformBlock> blocks; |
719 | GLint nbrActiveUniformsBlocks = 0; |
720 | m_extraFuncs->glGetProgramiv(program: programId, GL_ACTIVE_UNIFORM_BLOCKS, params: &nbrActiveUniformsBlocks); |
721 | blocks.reserve(n: nbrActiveUniformsBlocks); |
722 | for (GLint i = 0; i < nbrActiveUniformsBlocks; i++) { |
723 | QByteArray uniformBlockName(256, '\0'); |
724 | GLsizei length = 0; |
725 | ShaderUniformBlock uniformBlock; |
726 | m_extraFuncs->glGetActiveUniformBlockName(program: programId, uniformBlockIndex: i, bufSize: 256, length: &length, uniformBlockName: uniformBlockName.data()); |
727 | uniformBlock.m_name = QString::fromUtf8(ba: uniformBlockName.left(n: length)); |
728 | uniformBlock.m_index = i; |
729 | m_extraFuncs->glGetActiveUniformBlockiv(program: programId, uniformBlockIndex: i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, params: &uniformBlock.m_activeUniformsCount); |
730 | m_extraFuncs->glGetActiveUniformBlockiv(program: programId, uniformBlockIndex: i, GL_UNIFORM_BLOCK_BINDING, params: &uniformBlock.m_binding); |
731 | m_extraFuncs->glGetActiveUniformBlockiv(program: programId, uniformBlockIndex: i, GL_UNIFORM_BLOCK_DATA_SIZE, params: &uniformBlock.m_size); |
732 | blocks.push_back(x: uniformBlock); |
733 | } |
734 | return blocks; |
735 | } |
736 | |
737 | } // namespace OpenGL |
738 | } // namespace Render |
739 | } // namespace Qt3DRender |
740 | |
741 | QT_END_NAMESPACE |
742 |
Definitions
- GraphicsHelperES3
- ~GraphicsHelperES3
- initializeHelper
- drawElementsInstancedBaseVertexBaseInstance
- vertexAttribDivisor
- vertexAttributePointer
- drawArraysInstanced
- drawArraysInstancedBaseInstance
- readBuffer
- drawBuffer
- bindFrameBufferAttachment
- bindFrameBufferObject
- supportsFeature
- drawBuffers
- uniformTypeFromGLType
- uniformByteSize
- fenceSync
- clientWaitSync
- waitSync
- wasSyncSignaled
- deleteSync
- blitFramebuffer
- bindBufferBase
- frameBufferNeedsRenderBuffer
- bindUniformBlock
- buildUniformBuffer
- mapBuffer
- unmapBuffer
- programUniformsAndLocations
Start learning QML with our Intro Training
Find out more