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