| 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 |  |