1 | // Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "graphicshelperes2_p.h" |
5 | #include <private/attachmentpack_p.h> |
6 | #include <qgraphicsutils_p.h> |
7 | #include <renderbuffer_p.h> |
8 | #include <logging_p.h> |
9 | #include <QtGui/private/qopenglextensions_p.h> |
10 | |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | // ES 3.0+ |
15 | #ifndef GL_SAMPLER_3D |
16 | #define GL_SAMPLER_3D 0x8B5F |
17 | #endif |
18 | #ifndef GL_SAMPLER_2D_SHADOW |
19 | #define GL_SAMPLER_2D_SHADOW 0x8B62 |
20 | #endif |
21 | #ifndef GL_SAMPLER_CUBE_SHADOW |
22 | #define GL_SAMPLER_CUBE_SHADOW 0x8DC5 |
23 | #endif |
24 | #ifndef GL_SAMPLER_2D_ARRAY |
25 | #define GL_SAMPLER_2D_ARRAY 0x8DC1 |
26 | #endif |
27 | #ifndef GL_SAMPLER_2D_ARRAY_SHADOW |
28 | #define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 |
29 | #endif |
30 | |
31 | namespace Qt3DRender { |
32 | namespace Render { |
33 | namespace OpenGL { |
34 | |
35 | GraphicsHelperES2::GraphicsHelperES2() |
36 | : m_funcs(0) |
37 | , m_supportFramebufferBlit(false) |
38 | { |
39 | } |
40 | |
41 | GraphicsHelperES2::~GraphicsHelperES2() |
42 | { |
43 | } |
44 | |
45 | void GraphicsHelperES2::initializeHelper(QOpenGLContext *context, |
46 | QAbstractOpenGLFunctions *) |
47 | { |
48 | Q_ASSERT(context); |
49 | m_funcs = context->functions(); |
50 | Q_ASSERT(m_funcs); |
51 | m_ext.reset(other: new QOpenGLExtensions(context)); |
52 | if (m_ext->hasOpenGLExtension(extension: QOpenGLExtensions::FramebufferBlit)) |
53 | m_supportFramebufferBlit = true; |
54 | } |
55 | |
56 | void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, |
57 | GLsizei primitiveCount, |
58 | GLint indexType, |
59 | void *indices, |
60 | GLsizei instances, |
61 | GLint baseVertex, |
62 | GLint baseInstance) |
63 | { |
64 | if (baseInstance != 0) |
65 | qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2" ; |
66 | |
67 | if (baseVertex != 0) |
68 | qWarning() << "glDrawElementsInstancedBaseVertex is not supported with OpenGL ES 2" ; |
69 | |
70 | for (GLint i = 0; i < instances; i++) |
71 | drawElements(primitiveType, |
72 | primitiveCount, |
73 | indexType, |
74 | indices); |
75 | } |
76 | |
77 | void GraphicsHelperES2::drawArraysInstanced(GLenum primitiveType, |
78 | GLint first, |
79 | GLsizei count, |
80 | GLsizei instances) |
81 | { |
82 | for (GLint i = 0; i < instances; i++) |
83 | drawArrays(primitiveType, |
84 | first, |
85 | count); |
86 | } |
87 | |
88 | void GraphicsHelperES2::drawArraysInstancedBaseInstance(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances, GLsizei baseInstance) |
89 | { |
90 | if (baseInstance != 0) |
91 | qWarning() << "glDrawArraysInstancedBaseInstance is not supported with OpenGL ES 2" ; |
92 | for (GLint i = 0; i < instances; i++) |
93 | drawArrays(primitiveType, |
94 | first, |
95 | count); |
96 | } |
97 | |
98 | void GraphicsHelperES2::drawElements(GLenum primitiveType, |
99 | GLsizei primitiveCount, |
100 | GLint indexType, |
101 | void *indices, |
102 | GLint baseVertex) |
103 | { |
104 | if (baseVertex != 0) |
105 | qWarning() << "glDrawElementsBaseVertex is not supported with OpenGL ES 2" ; |
106 | QOpenGLExtensions *xfuncs = static_cast<QOpenGLExtensions *>(m_funcs); |
107 | if (indexType == GL_UNSIGNED_INT && !xfuncs->hasOpenGLExtension(extension: QOpenGLExtensions::ElementIndexUint)) { |
108 | static bool warnShown = false; |
109 | if (!warnShown) { |
110 | warnShown = true; |
111 | qWarning(msg: "GL_UNSIGNED_INT index type not supported on this system, skipping draw call." ); |
112 | } |
113 | return; |
114 | } |
115 | m_funcs->glDrawElements(mode: primitiveType, |
116 | count: primitiveCount, |
117 | type: indexType, |
118 | indices); |
119 | } |
120 | |
121 | void GraphicsHelperES2::drawArrays(GLenum primitiveType, |
122 | GLint first, |
123 | GLsizei count) |
124 | { |
125 | m_funcs->glDrawArrays(mode: primitiveType, |
126 | first, |
127 | count); |
128 | } |
129 | |
130 | void GraphicsHelperES2::drawElementsIndirect(GLenum, GLenum, void *) |
131 | { |
132 | static bool showWarning = true; |
133 | if (!showWarning) |
134 | return; |
135 | showWarning = false; |
136 | qWarning() << "Indirect Drawing is not supported with OpenGL ES 2" ; |
137 | } |
138 | |
139 | void GraphicsHelperES2::drawArraysIndirect(GLenum , void *) |
140 | { |
141 | static bool showWarning = true; |
142 | if (!showWarning) |
143 | return; |
144 | showWarning = false; |
145 | qWarning() << "Indirect Drawing is not supported with OpenGL ES 2" ; |
146 | } |
147 | |
148 | void GraphicsHelperES2::setVerticesPerPatch(GLint verticesPerPatch) |
149 | { |
150 | Q_UNUSED(verticesPerPatch); |
151 | static bool showWarning = true; |
152 | if (!showWarning) |
153 | return; |
154 | showWarning = false; |
155 | qWarning() << "Tessellation not supported with OpenGL ES 2" ; |
156 | } |
157 | |
158 | void GraphicsHelperES2::useProgram(GLuint programId) |
159 | { |
160 | m_funcs->glUseProgram(program: programId); |
161 | } |
162 | |
163 | std::vector<ShaderUniform> GraphicsHelperES2::programUniformsAndLocations(GLuint programId) |
164 | { |
165 | std::vector<ShaderUniform> uniforms; |
166 | |
167 | GLint nbrActiveUniforms = 0; |
168 | m_funcs->glGetProgramiv(program: programId, GL_ACTIVE_UNIFORMS, params: &nbrActiveUniforms); |
169 | uniforms.reserve(n: nbrActiveUniforms); |
170 | char uniformName[256]; |
171 | for (GLint i = 0; i < nbrActiveUniforms; i++) { |
172 | ShaderUniform uniform; |
173 | GLsizei uniformNameLength = 0; |
174 | // Size is 1 for scalar and more for struct or arrays |
175 | // Type is the GL Type |
176 | m_funcs->glGetActiveUniform(program: programId, index: i, bufsize: sizeof(uniformName) - 1, length: &uniformNameLength, |
177 | size: &uniform.m_size, type: &uniform.m_type, name: uniformName); |
178 | uniformName[sizeof(uniformName) - 1] = '\0'; |
179 | uniform.m_location = m_funcs->glGetUniformLocation(program: programId, name: uniformName); |
180 | uniform.m_name = QString::fromUtf8(utf8: uniformName, size: uniformNameLength); |
181 | // Work around for uniform array names that aren't returned with [0] by some drivers |
182 | if (uniform.m_size > 1 && !uniform.m_name.endsWith(s: QLatin1String("[0]" ))) |
183 | uniform.m_name.append(s: QLatin1String("[0]" )); |
184 | uniform.m_rawByteSize = uniformByteSize(description: uniform); |
185 | uniforms.push_back(x: uniform); |
186 | } |
187 | return uniforms; |
188 | } |
189 | |
190 | std::vector<ShaderAttribute> GraphicsHelperES2::programAttributesAndLocations(GLuint programId) |
191 | { |
192 | std::vector<ShaderAttribute> attributes; |
193 | GLint nbrActiveAttributes = 0; |
194 | m_funcs->glGetProgramiv(program: programId, GL_ACTIVE_ATTRIBUTES, params: &nbrActiveAttributes); |
195 | attributes.reserve(n: nbrActiveAttributes); |
196 | char attributeName[256]; |
197 | for (GLint i = 0; i < nbrActiveAttributes; i++) { |
198 | ShaderAttribute attribute; |
199 | GLsizei attributeNameLength = 0; |
200 | // Size is 1 for scalar and more for struct or arrays |
201 | // Type is the GL Type |
202 | m_funcs->glGetActiveAttrib(program: programId, index: i, bufsize: sizeof(attributeName) - 1, length: &attributeNameLength, |
203 | size: &attribute.m_size, type: &attribute.m_type, name: attributeName); |
204 | attributeName[sizeof(attributeName) - 1] = '\0'; |
205 | attribute.m_location = m_funcs->glGetAttribLocation(program: programId, name: attributeName); |
206 | attribute.m_name = QString::fromUtf8(utf8: attributeName, size: attributeNameLength); |
207 | attributes.push_back(x: attribute); |
208 | } |
209 | return attributes; |
210 | } |
211 | |
212 | std::vector<ShaderUniformBlock> GraphicsHelperES2::programUniformBlocks(GLuint programId) |
213 | { |
214 | Q_UNUSED(programId); |
215 | static bool showWarning = true; |
216 | if (!showWarning) |
217 | return {}; |
218 | showWarning = false; |
219 | qWarning() << "UBO are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
220 | return {}; |
221 | } |
222 | |
223 | std::vector<ShaderStorageBlock> GraphicsHelperES2::programShaderStorageBlocks(GLuint programId) |
224 | { |
225 | Q_UNUSED(programId); |
226 | static bool showWarning = true; |
227 | if (!showWarning) |
228 | return {}; |
229 | showWarning = false; |
230 | qWarning() << "SSBO are not supported by OpenGL ES 2.0 (since OpenGL ES 3.1)" ; |
231 | return {}; |
232 | } |
233 | |
234 | void GraphicsHelperES2::vertexAttribDivisor(GLuint index, GLuint divisor) |
235 | { |
236 | Q_UNUSED(index); |
237 | Q_UNUSED(divisor); |
238 | } |
239 | |
240 | void GraphicsHelperES2::vertexAttributePointer(GLenum shaderDataType, |
241 | GLuint index, |
242 | GLint size, |
243 | GLenum type, |
244 | GLboolean normalized, |
245 | GLsizei stride, |
246 | const GLvoid *pointer) |
247 | { |
248 | switch (shaderDataType) { |
249 | case GL_FLOAT: |
250 | case GL_FLOAT_VEC2: |
251 | case GL_FLOAT_VEC3: |
252 | case GL_FLOAT_VEC4: |
253 | case GL_FLOAT_MAT2: |
254 | case GL_FLOAT_MAT3: |
255 | case GL_FLOAT_MAT4: |
256 | m_funcs->glVertexAttribPointer(indx: index, size, type, normalized, stride, ptr: pointer); |
257 | break; |
258 | |
259 | default: |
260 | qCWarning(Rendering) << "vertexAttribPointer: Unhandled type" ; |
261 | Q_UNREACHABLE(); |
262 | } |
263 | } |
264 | |
265 | void GraphicsHelperES2::readBuffer(GLenum mode) |
266 | { |
267 | Q_UNUSED(mode); |
268 | static bool showWarning = true; |
269 | if (!showWarning) |
270 | return; |
271 | showWarning = false; |
272 | qWarning() << "glReadBuffer not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
273 | } |
274 | |
275 | void GraphicsHelperES2::drawBuffer(GLenum mode) |
276 | { |
277 | Q_UNUSED(mode); |
278 | static bool showWarning = true; |
279 | if (!showWarning) |
280 | return; |
281 | showWarning = false; |
282 | qWarning() << "glDrawBuffer is not supported with OpenGL ES 2" ; |
283 | } |
284 | |
285 | void *GraphicsHelperES2::fenceSync() |
286 | { |
287 | qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
288 | return nullptr; |
289 | } |
290 | |
291 | void GraphicsHelperES2::clientWaitSync(void *, GLuint64 ) |
292 | { |
293 | qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
294 | } |
295 | |
296 | void GraphicsHelperES2::waitSync(void *) |
297 | { |
298 | qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
299 | } |
300 | |
301 | bool GraphicsHelperES2::wasSyncSignaled(void *) |
302 | { |
303 | qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
304 | return false; |
305 | } |
306 | |
307 | void GraphicsHelperES2::deleteSync(void *) |
308 | { |
309 | qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)" ; |
310 | } |
311 | |
312 | void GraphicsHelperES2::rasterMode(GLenum faceMode, GLenum rasterMode) |
313 | { |
314 | Q_UNUSED(faceMode); |
315 | Q_UNUSED(rasterMode); |
316 | qWarning() << "glPolyonMode is not supported with OpenGL ES" ; |
317 | } |
318 | |
319 | void GraphicsHelperES2::blendEquation(GLenum mode) |
320 | { |
321 | m_funcs->glBlendEquation(mode); |
322 | } |
323 | |
324 | void GraphicsHelperES2::blendFunci(GLuint buf, GLenum sfactor, GLenum dfactor) |
325 | { |
326 | Q_UNUSED(buf); |
327 | Q_UNUSED(sfactor); |
328 | Q_UNUSED(dfactor); |
329 | |
330 | static bool showWarning = true; |
331 | if (!showWarning) |
332 | return; |
333 | showWarning = false; |
334 | qWarning() << "glBlendFunci() not supported by OpenGL ES 2.0" ; |
335 | } |
336 | |
337 | void GraphicsHelperES2::blendFuncSeparatei(GLuint buf, GLenum sRGB, GLenum dRGB, GLenum sAlpha, GLenum dAlpha) |
338 | { |
339 | Q_UNUSED(buf); |
340 | Q_UNUSED(sRGB); |
341 | Q_UNUSED(dRGB); |
342 | Q_UNUSED(sAlpha); |
343 | Q_UNUSED(dAlpha); |
344 | |
345 | static bool showWarning = true; |
346 | if (!showWarning) |
347 | return; |
348 | showWarning = false; |
349 | qWarning() << "glBlendFuncSeparatei() not supported by OpenGL ES 2.0" ; |
350 | } |
351 | |
352 | void GraphicsHelperES2::alphaTest(GLenum, GLenum) |
353 | { |
354 | qCWarning(Rendering) << Q_FUNC_INFO << "AlphaTest not available with OpenGL ES 2.0" ; |
355 | } |
356 | |
357 | void GraphicsHelperES2::depthTest(GLenum mode) |
358 | { |
359 | m_funcs->glEnable(GL_DEPTH_TEST); |
360 | m_funcs->glDepthFunc(func: mode); |
361 | } |
362 | |
363 | void GraphicsHelperES2::depthMask(GLenum mode) |
364 | { |
365 | m_funcs->glDepthMask(flag: mode); |
366 | } |
367 | |
368 | void GraphicsHelperES2::depthRange(GLdouble nearValue, GLdouble farValue) |
369 | { |
370 | m_funcs->glDepthRangef(zNear: static_cast<float>(nearValue), zFar: static_cast<float>(farValue)); |
371 | } |
372 | |
373 | void GraphicsHelperES2::frontFace(GLenum mode) |
374 | { |
375 | m_funcs->glFrontFace(mode); |
376 | } |
377 | |
378 | void GraphicsHelperES2::setMSAAEnabled(bool enabled) |
379 | { |
380 | Q_UNUSED(enabled); |
381 | static bool showWarning = true; |
382 | if (!showWarning) |
383 | return; |
384 | if (!enabled) { |
385 | showWarning = false; |
386 | qWarning() << "MSAA cannot be disabled with OpenGL ES 2.0" ; |
387 | } |
388 | } |
389 | |
390 | void GraphicsHelperES2::setAlphaCoverageEnabled(bool enabled) |
391 | { |
392 | enabled ? m_funcs->glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE) |
393 | : m_funcs->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); |
394 | } |
395 | |
396 | GLuint GraphicsHelperES2::createFrameBufferObject() |
397 | { |
398 | GLuint id; |
399 | m_funcs->glGenFramebuffers(n: 1, framebuffers: &id); |
400 | return id; |
401 | } |
402 | |
403 | void GraphicsHelperES2::releaseFrameBufferObject(GLuint frameBufferId) |
404 | { |
405 | m_funcs->glDeleteFramebuffers(n: 1, framebuffers: &frameBufferId); |
406 | } |
407 | |
408 | void GraphicsHelperES2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) |
409 | { |
410 | Q_UNUSED(mode); |
411 | // For ES2 the spec states for target: The symbolic constant must be GL_FRAMEBUFFER |
412 | // so mode is ignored and is always set to GL_FRAMEBUFFER |
413 | m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer: frameBufferId); |
414 | } |
415 | |
416 | void GraphicsHelperES2::bindImageTexture(GLuint imageUnit, GLuint texture, |
417 | GLint mipLevel, GLboolean layered, |
418 | GLint layer, GLenum access, GLenum format) |
419 | { |
420 | Q_UNUSED(imageUnit); |
421 | Q_UNUSED(texture); |
422 | Q_UNUSED(mipLevel); |
423 | Q_UNUSED(layered); |
424 | Q_UNUSED(layer); |
425 | Q_UNUSED(access); |
426 | Q_UNUSED(format); |
427 | qWarning() << "Shader Images are not supported by ES 2.0 (since ES 3.1)" ; |
428 | |
429 | } |
430 | |
431 | GLuint GraphicsHelperES2::boundFrameBufferObject() |
432 | { |
433 | GLint id = 0; |
434 | m_funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, params: &id); |
435 | return id; |
436 | } |
437 | |
438 | bool GraphicsHelperES2::checkFrameBufferComplete() |
439 | { |
440 | return (m_funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); |
441 | } |
442 | |
443 | bool GraphicsHelperES2::frameBufferNeedsRenderBuffer(const Attachment &attachment) |
444 | { |
445 | // Use a renderbuffer for depth or stencil attachments since this is |
446 | // problematic before GLES 3.2. Keep using textures for everything else. |
447 | // For ES2 individual Depth and Stencil buffers need to be an option because |
448 | // DepthStencil is an extension. |
449 | return attachment.m_point == QRenderTargetOutput::DepthStencil || |
450 | attachment.m_point == QRenderTargetOutput::Depth || |
451 | attachment.m_point == QRenderTargetOutput::Stencil; |
452 | } |
453 | |
454 | void GraphicsHelperES2::bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) |
455 | { |
456 | GLenum attr = GL_COLOR_ATTACHMENT0; |
457 | |
458 | if (attachment.m_point == QRenderTargetOutput::Color0) |
459 | attr = GL_COLOR_ATTACHMENT0; |
460 | else if (attachment.m_point == QRenderTargetOutput::Depth) |
461 | attr = GL_DEPTH_ATTACHMENT; |
462 | else if (attachment.m_point == QRenderTargetOutput::Stencil) |
463 | attr = GL_STENCIL_ATTACHMENT; |
464 | else |
465 | qCritical() << "Unsupported FBO attachment OpenGL ES 2.0" ; |
466 | |
467 | const QOpenGLTexture::Target target = texture->target(); |
468 | |
469 | if (target == QOpenGLTexture::TargetCubeMap && attachment.m_face == QAbstractTexture::AllFaces) { |
470 | qWarning() << "OpenGL ES 2.0 doesn't handle attaching all the faces of a cube map texture at once to an FBO" ; |
471 | return; |
472 | } |
473 | |
474 | texture->bind(); |
475 | if (target == QOpenGLTexture::Target2D) |
476 | m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment: attr, textarget: target, texture: texture->textureId(), level: attachment.m_mipLevel); |
477 | else if (target == QOpenGLTexture::TargetCubeMap) |
478 | m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment: attr, textarget: attachment.m_face, texture: texture->textureId(), level: attachment.m_mipLevel); |
479 | else |
480 | qCritical() << "Unsupported Texture FBO attachment format" ; |
481 | texture->release(); |
482 | } |
483 | |
484 | void GraphicsHelperES2::bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) |
485 | { |
486 | if (attachment.m_point != QRenderTargetOutput::DepthStencil && |
487 | attachment.m_point != QRenderTargetOutput::Depth && |
488 | attachment.m_point != QRenderTargetOutput::Stencil) { |
489 | qCritical() << "Renderbuffers only supported for combined depth-stencil, depth, or stencil, but got attachment point" |
490 | << attachment.m_point; |
491 | return; |
492 | } |
493 | |
494 | renderBuffer->bind(); |
495 | if (attachment.m_point == QRenderTargetOutput::DepthStencil || |
496 | attachment.m_point == QRenderTargetOutput::Depth) |
497 | m_funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer: renderBuffer->renderBufferId()); |
498 | if (attachment.m_point == QRenderTargetOutput::DepthStencil || |
499 | attachment.m_point == QRenderTargetOutput::Stencil) |
500 | m_funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer: renderBuffer->renderBufferId()); |
501 | renderBuffer->release(); |
502 | } |
503 | |
504 | bool GraphicsHelperES2::supportsFeature(GraphicsHelperInterface::Feature feature) const |
505 | { |
506 | switch (feature) { |
507 | case RenderBufferDimensionRetrieval: |
508 | return true; |
509 | case BlitFramebuffer: |
510 | return m_supportFramebufferBlit; |
511 | default: |
512 | return false; |
513 | } |
514 | } |
515 | |
516 | void GraphicsHelperES2::drawBuffers(GLsizei, const int *) |
517 | { |
518 | static bool showWarning = true; |
519 | if (!showWarning) |
520 | return; |
521 | showWarning = false; |
522 | qWarning() << "drawBuffers is not supported by ES 2.0" ; |
523 | } |
524 | |
525 | void GraphicsHelperES2::bindFragDataLocation(GLuint , const QHash<QString, int> &) |
526 | { |
527 | qCritical() << "bindFragDataLocation is not supported by ES 2.0" ; |
528 | } |
529 | |
530 | void GraphicsHelperES2::bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) |
531 | { |
532 | Q_UNUSED(programId); |
533 | Q_UNUSED(uniformBlockIndex); |
534 | Q_UNUSED(uniformBlockBinding); |
535 | static bool showWarning = true; |
536 | if (!showWarning) |
537 | return; |
538 | showWarning = false; |
539 | qWarning() << "UBO are not supported by ES 2.0 (since ES 3.0)" ; |
540 | } |
541 | |
542 | void GraphicsHelperES2::bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) |
543 | { |
544 | Q_UNUSED(programId); |
545 | Q_UNUSED(shaderStorageBlockIndex); |
546 | Q_UNUSED(shaderStorageBlockBinding); |
547 | static bool showWarning = true; |
548 | if (!showWarning) |
549 | return; |
550 | showWarning = false; |
551 | qWarning() << "SSBO are not supported by ES 2.0 (since ES 3.1)" ; |
552 | } |
553 | |
554 | void GraphicsHelperES2::bindBufferBase(GLenum target, GLuint index, GLuint buffer) |
555 | { |
556 | Q_UNUSED(target); |
557 | Q_UNUSED(index); |
558 | Q_UNUSED(buffer); |
559 | static bool showWarning = true; |
560 | if (!showWarning) |
561 | return; |
562 | showWarning = false; |
563 | qWarning() << "bindBufferBase is not supported by ES 2.0 (since ES 3.0)" ; |
564 | } |
565 | |
566 | void GraphicsHelperES2::buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer) |
567 | { |
568 | Q_UNUSED(v); |
569 | Q_UNUSED(description); |
570 | Q_UNUSED(buffer); |
571 | static bool showWarning = true; |
572 | if (!showWarning) |
573 | return; |
574 | showWarning = false; |
575 | qWarning() << "UBO are not supported by ES 2.0 (since ES 3.0)" ; |
576 | } |
577 | |
578 | uint GraphicsHelperES2::uniformByteSize(const ShaderUniform &description) |
579 | { |
580 | uint rawByteSize = 0; |
581 | int arrayStride = qMax(a: description.m_arrayStride, b: 0); |
582 | int matrixStride = qMax(a: description.m_matrixStride, b: 0); |
583 | |
584 | switch (description.m_type) { |
585 | |
586 | case GL_FLOAT_VEC2: |
587 | case GL_INT_VEC2: |
588 | rawByteSize = 8; |
589 | break; |
590 | |
591 | case GL_FLOAT_VEC3: |
592 | case GL_INT_VEC3: |
593 | rawByteSize = 12; |
594 | break; |
595 | |
596 | case GL_FLOAT_VEC4: |
597 | case GL_INT_VEC4: |
598 | rawByteSize = 16; |
599 | break; |
600 | |
601 | case GL_FLOAT_MAT2: |
602 | rawByteSize = matrixStride ? 2 * matrixStride : 16; |
603 | break; |
604 | |
605 | case GL_FLOAT_MAT3: |
606 | rawByteSize = matrixStride ? 3 * matrixStride : 36; |
607 | break; |
608 | |
609 | case GL_FLOAT_MAT4: |
610 | rawByteSize = matrixStride ? 4 * matrixStride : 64; |
611 | break; |
612 | |
613 | case GL_BOOL: |
614 | rawByteSize = 1; |
615 | break; |
616 | |
617 | case GL_BOOL_VEC2: |
618 | rawByteSize = 2; |
619 | break; |
620 | |
621 | case GL_BOOL_VEC3: |
622 | rawByteSize = 3; |
623 | break; |
624 | |
625 | case GL_BOOL_VEC4: |
626 | rawByteSize = 4; |
627 | break; |
628 | |
629 | case GL_INT: |
630 | case GL_FLOAT: |
631 | case GL_SAMPLER_2D: |
632 | case GL_SAMPLER_CUBE: |
633 | rawByteSize = 4; |
634 | break; |
635 | } |
636 | |
637 | return arrayStride ? rawByteSize * arrayStride : rawByteSize; |
638 | } |
639 | |
640 | void GraphicsHelperES2::enableClipPlane(int) |
641 | { |
642 | } |
643 | |
644 | void GraphicsHelperES2::disableClipPlane(int) |
645 | { |
646 | } |
647 | |
648 | void GraphicsHelperES2::setClipPlane(int, const QVector3D &, float) |
649 | { |
650 | static bool showWarning = true; |
651 | if (!showWarning) |
652 | return; |
653 | showWarning = false; |
654 | qWarning() << "Clip planes not supported by OpenGL ES 2.0" ; |
655 | } |
656 | |
657 | GLint GraphicsHelperES2::maxClipPlaneCount() |
658 | { |
659 | return 0; |
660 | } |
661 | |
662 | void GraphicsHelperES2::memoryBarrier(QMemoryBarrier::Operations barriers) |
663 | { |
664 | Q_UNUSED(barriers); |
665 | static bool showWarning = true; |
666 | if (!showWarning) |
667 | return; |
668 | showWarning = false; |
669 | qWarning() << "memory barrier is not supported by OpenGL ES 2.0 (since 4.3)" ; |
670 | } |
671 | |
672 | void GraphicsHelperES2::enablePrimitiveRestart(int) |
673 | { |
674 | static bool showWarning = true; |
675 | if (!showWarning) |
676 | return; |
677 | showWarning = false; |
678 | qWarning() << "primitive restart is not supported by OpenGL ES 2.0 (since GL 3.1, ES 3.0)" ; |
679 | } |
680 | |
681 | void GraphicsHelperES2::enableVertexAttributeArray(int location) |
682 | { |
683 | m_funcs->glEnableVertexAttribArray(index: location); |
684 | } |
685 | |
686 | void GraphicsHelperES2::disablePrimitiveRestart() |
687 | { |
688 | } |
689 | |
690 | void GraphicsHelperES2::clearBufferf(GLint drawbuffer, const QVector4D &values) |
691 | { |
692 | Q_UNUSED(drawbuffer); |
693 | Q_UNUSED(values); |
694 | static bool showWarning = true; |
695 | if (!showWarning) |
696 | return; |
697 | showWarning = false; |
698 | qWarning() << "glClearBuffer*() not supported by OpenGL ES 2.0" ; |
699 | } |
700 | |
701 | void GraphicsHelperES2::pointSize(bool programmable, GLfloat value) |
702 | { |
703 | // If this is not a reset to default values, print a warning |
704 | if (programmable || !qFuzzyCompare(p1: value, p2: 1.0f)) { |
705 | static bool warned = false; |
706 | if (!warned) { |
707 | qWarning() << "glPointSize() and GL_PROGRAM_POINT_SIZE are not supported by ES 2.0" ; |
708 | warned = true; |
709 | } |
710 | } |
711 | } |
712 | |
713 | void GraphicsHelperES2::enablei(GLenum cap, GLuint index) |
714 | { |
715 | Q_UNUSED(cap); |
716 | Q_UNUSED(index); |
717 | static bool showWarning = true; |
718 | if (!showWarning) |
719 | return; |
720 | showWarning = false; |
721 | qWarning() << "glEnablei() not supported by OpenGL ES 2.0" ; |
722 | } |
723 | |
724 | void GraphicsHelperES2::disablei(GLenum cap, GLuint index) |
725 | { |
726 | Q_UNUSED(cap); |
727 | Q_UNUSED(index); |
728 | static bool showWarning = true; |
729 | if (!showWarning) |
730 | return; |
731 | showWarning = false; |
732 | qWarning() << "glDisablei() not supported by OpenGL ES 2.0" ; |
733 | } |
734 | |
735 | void GraphicsHelperES2::setSeamlessCubemap(bool enable) |
736 | { |
737 | Q_UNUSED(enable); |
738 | static bool showWarning = true; |
739 | if (!showWarning) |
740 | return; |
741 | showWarning = false; |
742 | qWarning() << "GL_TEXTURE_CUBE_MAP_SEAMLESS not supported by OpenGL ES 2.0" ; |
743 | } |
744 | |
745 | QSize GraphicsHelperES2::getRenderBufferDimensions(GLuint renderBufferId) |
746 | { |
747 | GLint width = 0; |
748 | GLint height = 0; |
749 | |
750 | m_funcs->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: renderBufferId); |
751 | m_funcs->glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, params: &width); |
752 | m_funcs->glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, params: &height); |
753 | m_funcs->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer: 0); |
754 | |
755 | return QSize(width, height); |
756 | } |
757 | |
758 | QSize GraphicsHelperES2::getTextureDimensions(GLuint textureId, GLenum target, uint level) |
759 | { |
760 | Q_UNUSED(textureId); |
761 | Q_UNUSED(target); |
762 | Q_UNUSED(level); |
763 | qCritical() << "getTextureDimensions is not supported by ES 2.0" ; |
764 | return QSize(0, 0); |
765 | } |
766 | |
767 | void GraphicsHelperES2::dispatchCompute(GLuint wx, GLuint wy, GLuint wz) |
768 | { |
769 | Q_UNUSED(wx); |
770 | Q_UNUSED(wy); |
771 | Q_UNUSED(wz); |
772 | static bool showWarning = true; |
773 | if (!showWarning) |
774 | return; |
775 | showWarning = false; |
776 | qWarning() << "Compute Shaders are not supported by ES 2.0 (since ES 3.1)" ; |
777 | } |
778 | |
779 | char *GraphicsHelperES2::mapBuffer(GLenum target, GLsizeiptr size) |
780 | { |
781 | Q_UNUSED(target); |
782 | Q_UNUSED(size); |
783 | static bool showWarning = true; |
784 | if (!showWarning) |
785 | return nullptr; |
786 | showWarning = false; |
787 | qWarning() << "Map buffer is not a core requirement for ES 2.0" ; |
788 | return nullptr; |
789 | } |
790 | |
791 | GLboolean GraphicsHelperES2::unmapBuffer(GLenum target) |
792 | { |
793 | Q_UNUSED(target); |
794 | static bool showWarning = true; |
795 | if (!showWarning) |
796 | return false; |
797 | showWarning = false; |
798 | qWarning() << "unMap buffer is not a core requirement for ES 2.0" ; |
799 | return false; |
800 | } |
801 | |
802 | void GraphicsHelperES2::glUniform1fv(GLint location, GLsizei count, const GLfloat *values) |
803 | { |
804 | m_funcs->glUniform1fv(location, count, v: values); |
805 | } |
806 | |
807 | void GraphicsHelperES2::glUniform2fv(GLint location, GLsizei count, const GLfloat *values) |
808 | { |
809 | m_funcs->glUniform2fv(location, count, v: values); |
810 | } |
811 | |
812 | void GraphicsHelperES2::glUniform3fv(GLint location, GLsizei count, const GLfloat *values) |
813 | { |
814 | m_funcs->glUniform3fv(location, count, v: values); |
815 | } |
816 | |
817 | void GraphicsHelperES2::glUniform4fv(GLint location, GLsizei count, const GLfloat *values) |
818 | { |
819 | m_funcs->glUniform4fv(location, count, v: values); |
820 | } |
821 | |
822 | void GraphicsHelperES2::glUniform1iv(GLint location, GLsizei count, const GLint *values) |
823 | { |
824 | m_funcs->glUniform1iv(location, count, v: values); |
825 | } |
826 | |
827 | void GraphicsHelperES2::glUniform2iv(GLint location, GLsizei count, const GLint *values) |
828 | { |
829 | m_funcs->glUniform2iv(location, count, v: values); |
830 | } |
831 | |
832 | void GraphicsHelperES2::glUniform3iv(GLint location, GLsizei count, const GLint *values) |
833 | { |
834 | m_funcs->glUniform3iv(location, count, v: values); |
835 | } |
836 | |
837 | void GraphicsHelperES2::glUniform4iv(GLint location, GLsizei count, const GLint *values) |
838 | { |
839 | m_funcs->glUniform4iv(location, count, v: values); |
840 | } |
841 | |
842 | void GraphicsHelperES2::glUniform1uiv(GLint , GLsizei , const GLuint *) |
843 | { |
844 | static bool showWarning = true; |
845 | if (!showWarning) |
846 | return; |
847 | showWarning = false; |
848 | qWarning() << "glUniform1uiv not supported by ES 2" ; |
849 | } |
850 | |
851 | void GraphicsHelperES2::glUniform2uiv(GLint , GLsizei , const GLuint *) |
852 | { |
853 | static bool showWarning = true; |
854 | if (!showWarning) |
855 | return; |
856 | showWarning = false; |
857 | qWarning() << "glUniform2uiv not supported by ES 2" ; |
858 | } |
859 | |
860 | void GraphicsHelperES2::glUniform3uiv(GLint , GLsizei , const GLuint *) |
861 | { |
862 | static bool showWarning = true; |
863 | if (!showWarning) |
864 | return; |
865 | showWarning = false; |
866 | qWarning() << "glUniform3uiv not supported by ES 2" ; |
867 | } |
868 | |
869 | void GraphicsHelperES2::glUniform4uiv(GLint , GLsizei , const GLuint *) |
870 | { |
871 | static bool showWarning = true; |
872 | if (!showWarning) |
873 | return; |
874 | showWarning = false; |
875 | qWarning() << "glUniform4uiv not supported by ES 2" ; |
876 | } |
877 | |
878 | void GraphicsHelperES2::glUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *values) |
879 | { |
880 | m_funcs->glUniformMatrix2fv(location, count, transpose: false, value: values); |
881 | } |
882 | |
883 | void GraphicsHelperES2::glUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *values) |
884 | { |
885 | m_funcs->glUniformMatrix3fv(location, count, transpose: false, value: values); |
886 | } |
887 | |
888 | void GraphicsHelperES2::glUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *values) |
889 | { |
890 | m_funcs->glUniformMatrix4fv(location, count, transpose: false, value: values); |
891 | } |
892 | |
893 | void GraphicsHelperES2::glUniformMatrix2x3fv(GLint , GLsizei , const GLfloat *) |
894 | { |
895 | static bool showWarning = true; |
896 | if (!showWarning) |
897 | return; |
898 | showWarning = false; |
899 | qWarning() << "glUniformMatrix2x3fv not supported by ES 2" ; |
900 | } |
901 | |
902 | void GraphicsHelperES2::glUniformMatrix3x2fv(GLint , GLsizei , const GLfloat *) |
903 | { |
904 | static bool showWarning = true; |
905 | if (!showWarning) |
906 | return; |
907 | showWarning = false; |
908 | qWarning() << "glUniformMatrix3x2fv not supported by ES 2" ; |
909 | } |
910 | |
911 | void GraphicsHelperES2::glUniformMatrix2x4fv(GLint , GLsizei , const GLfloat *) |
912 | { |
913 | static bool showWarning = true; |
914 | if (!showWarning) |
915 | return; |
916 | showWarning = false; |
917 | qWarning() << "glUniformMatrix2x4fv not supported by ES 2" ; |
918 | } |
919 | |
920 | void GraphicsHelperES2::glUniformMatrix4x2fv(GLint , GLsizei , const GLfloat *) |
921 | { |
922 | static bool showWarning = true; |
923 | if (!showWarning) |
924 | return; |
925 | showWarning = false; |
926 | qWarning() << "glUniformMatrix4x2fv not supported by ES 2" ; |
927 | } |
928 | |
929 | void GraphicsHelperES2::glUniformMatrix3x4fv(GLint , GLsizei , const GLfloat *) |
930 | { |
931 | static bool showWarning = true; |
932 | if (!showWarning) |
933 | return; |
934 | showWarning = false; |
935 | qWarning() << "glUniformMatrix3x4fv not supported by ES 2" ; |
936 | } |
937 | |
938 | void GraphicsHelperES2::glUniformMatrix4x3fv(GLint , GLsizei , const GLfloat *) |
939 | { |
940 | static bool showWarning = true; |
941 | if (!showWarning) |
942 | return; |
943 | showWarning = false; |
944 | qWarning() << "glUniformMatrix4x3fv not supported by ES 2" ; |
945 | } |
946 | |
947 | UniformType GraphicsHelperES2::uniformTypeFromGLType(GLenum type) |
948 | { |
949 | switch (type) { |
950 | case GL_FLOAT: |
951 | return UniformType::Float; |
952 | case GL_FLOAT_VEC2: |
953 | return UniformType::Vec2; |
954 | case GL_FLOAT_VEC3: |
955 | return UniformType::Vec3; |
956 | case GL_FLOAT_VEC4: |
957 | return UniformType::Vec4; |
958 | case GL_FLOAT_MAT2: |
959 | return UniformType::Mat2; |
960 | case GL_FLOAT_MAT3: |
961 | return UniformType::Mat3; |
962 | case GL_FLOAT_MAT4: |
963 | return UniformType::Mat4; |
964 | case GL_INT: |
965 | return UniformType::Int; |
966 | case GL_INT_VEC2: |
967 | return UniformType::IVec2; |
968 | case GL_INT_VEC3: |
969 | return UniformType::IVec3; |
970 | case GL_INT_VEC4: |
971 | return UniformType::IVec4; |
972 | case GL_BOOL: |
973 | return UniformType::Bool; |
974 | case GL_BOOL_VEC2: |
975 | return UniformType::BVec2; |
976 | case GL_BOOL_VEC3: |
977 | return UniformType::BVec3; |
978 | case GL_BOOL_VEC4: |
979 | return UniformType::BVec4; |
980 | |
981 | case GL_SAMPLER_2D: |
982 | case GL_SAMPLER_CUBE: |
983 | return UniformType::Sampler; |
984 | default: |
985 | Q_UNREACHABLE_RETURN(UniformType::Float); |
986 | } |
987 | } |
988 | |
989 | void GraphicsHelperES2::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) |
990 | { |
991 | if (!m_supportFramebufferBlit) { |
992 | static bool showWarning = true; |
993 | if (!showWarning) |
994 | return; |
995 | showWarning = false; |
996 | qWarning() << "Framebuffer blits are not supported by ES 2.0 (since ES 3.1)" ; |
997 | } else |
998 | m_ext->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); |
999 | } |
1000 | |
1001 | } // namespace OpenGL |
1002 | } // namespace Render |
1003 | } // namespace Qt3DRender |
1004 | |
1005 | QT_END_NAMESPACE |
1006 | |