1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
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 General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #include <QtQuick3DRender/private/qssgrenderbackendgles2_p.h>
32 #include <QtQuick3DRender/private/qssgrenderbackendinputassemblergl_p.h>
33 #include <QtQuick3DRender/private/qssgrenderbackendrenderstatesgl_p.h>
34 #include <QtQuick3DRender/private/qssgrenderbackendshaderprogramgl_p.h>
35 #include <QtQuick3DRender/private/qssgopenglextensions_p.h>
36 
37 QT_BEGIN_NAMESPACE
38 
39 #ifdef RENDER_BACKEND_LOG_GL_ERRORS
40 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__)
41 #else
42 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError()
43 #endif
44 
45 #if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
46 #define GL_CALL_TIMER_EXT(x)                                                                                           \
47     m_QSSGExtensions->x;                                                                                             \
48     RENDER_LOG_ERROR_PARAMS(x);
49 #define GL_CALL_TESSELATION_EXT(x)                                                                                     \
50     m_QSSGExtensions->x;                                                                                             \
51     RENDER_LOG_ERROR_PARAMS(x);
52 #define GL_CALL_MULTISAMPLE_EXT(x)                                                                                     \
53     m_QSSGExtensions->x;                                                                                             \
54     RENDER_LOG_ERROR_PARAMS(x);
55 #define GL_CALL_EXTRA_FUNCTION(x)                                                                                      \
56     m_glExtraFunctions->x;                                                                                             \
57     RENDER_LOG_ERROR_PARAMS(x);
58 #define GL_CALL_EXTENSION_FUNCTION(x)                                                                                  \
59     m_QSSGExtensions->x;                                                                                             \
60     RENDER_LOG_ERROR_PARAMS(x);
61 #else
62 #define GL_CALL_TIMER_EXT(x)
63 #define GL_CALL_TESSELATION_EXT(x)
64 #define GL_CALL_MULTISAMPLE_EXT(x)
65 #define GL_CALL_EXTRA_FUNCTION(x)                                                                                      \
66     m_glExtraFunctions->x;                                                                                             \
67     RENDER_LOG_ERROR_PARAMS(x);
68 #define GL_CALL_EXTENSION_FUNCTION(x)
69 #endif
70 
71 #ifndef GL_DEPTH_STENCIL_OES
72 #define GL_DEPTH_STENCIL_OES 0x84F9
73 #endif
74 
exts3tc()75 QByteArray exts3tc()
76 {
77     return QByteArrayLiteral("GL_EXT_texture_compression_s3tc");
78 }
extsdxt()79 QByteArray extsdxt()
80 {
81     return QByteArrayLiteral("GL_EXT_texture_compression_dxt1");
82 }
extsAniso()83 QByteArray extsAniso()
84 {
85     return QByteArrayLiteral("GL_EXT_texture_filter_anisotropic");
86 }
extsTexSwizzle()87 QByteArray extsTexSwizzle()
88 {
89     return QByteArrayLiteral("GL_ARB_texture_swizzle");
90 }
extsFPRenderTarget()91 QByteArray extsFPRenderTarget()
92 {
93     return QByteArrayLiteral("GL_EXT_color_buffer_float");
94 }
extsTimerQuery()95 QByteArray extsTimerQuery()
96 {
97     return QByteArrayLiteral("GL_EXT_timer_query");
98 }
extsGpuShader5()99 QByteArray extsGpuShader5()
100 {
101     return QByteArrayLiteral("EXT_gpu_shader5");
102 }
103 
extDepthTexture()104 QByteArray extDepthTexture()
105 {
106     return QByteArrayLiteral("GL_OES_packed_depth_stencil");
107 }
extvao()108 QByteArray extvao()
109 {
110     return QByteArrayLiteral("GL_OES_vertex_array_object");
111 }
extStdDd()112 QByteArray extStdDd()
113 {
114     return QByteArrayLiteral("GL_OES_standard_derivatives");
115 }
extTexLod()116 QByteArray extTexLod()
117 {
118     return QByteArrayLiteral("GL_EXT_shader_texture_lod");
119 }
120 
121 /// constructor
QSSGRenderBackendGLES2Impl(const QSurfaceFormat & format)122 QSSGRenderBackendGLES2Impl::QSSGRenderBackendGLES2Impl(const QSurfaceFormat &format)
123     : QSSGRenderBackendGLBase(format)
124 {
125     // clear support bits
126     m_backendSupport.caps.u32Values = 0;
127 
128     const char *extensions = getExtensionString();
129     m_extensions = QByteArray(extensions).split(' ');
130 
131     // get extension count
132     GLint numExtensions = m_extensions.size();
133 
134     for (qint32 i = 0; i < numExtensions; i++) {
135 
136         const QByteArray &extensionString = m_extensions.at(i);
137 
138         // search for extension
139         if (!m_backendSupport.caps.bits.bDXTImagesSupported
140             && (exts3tc().compare(extensionString) == 0 || extsdxt().compare(extensionString) == 0)) {
141             m_backendSupport.caps.bits.bDXTImagesSupported = true;
142         } else if (!m_backendSupport.caps.bits.bAnistropySupported && extsAniso().compare(extensionString) == 0) {
143             m_backendSupport.caps.bits.bAnistropySupported = true;
144         } else if (!m_backendSupport.caps.bits.bFPRenderTargetsSupported && extsFPRenderTarget().compare(extensionString) == 0) {
145             m_backendSupport.caps.bits.bFPRenderTargetsSupported = true;
146         } else if (!m_backendSupport.caps.bits.bTimerQuerySupported && extsTimerQuery().compare(extensionString) == 0) {
147             m_backendSupport.caps.bits.bTimerQuerySupported = true;
148         } else if (!m_backendSupport.caps.bits.bGPUShader5ExtensionSupported && extsGpuShader5().compare(extensionString) == 0) {
149             m_backendSupport.caps.bits.bGPUShader5ExtensionSupported = true;
150         } else if (!m_backendSupport.caps.bits.bTextureSwizzleSupported && extsTexSwizzle().compare(extensionString) == 0) {
151             m_backendSupport.caps.bits.bTextureSwizzleSupported = true;
152         } else if (!m_backendSupport.caps.bits.bDepthStencilSupported && extDepthTexture().compare(extensionString) == 0) {
153             m_backendSupport.caps.bits.bDepthStencilSupported = true;
154         } else if (!m_backendSupport.caps.bits.bVertexArrayObjectSupported && extvao().compare(extensionString) == 0) {
155             m_backendSupport.caps.bits.bVertexArrayObjectSupported = true;
156         } else if (!m_backendSupport.caps.bits.bStandardDerivativesSupported && extStdDd().compare(extensionString) == 0) {
157             m_backendSupport.caps.bits.bStandardDerivativesSupported = true;
158         } else if (!m_backendSupport.caps.bits.bTextureLodSupported && extTexLod().compare(extensionString) == 0) {
159             m_backendSupport.caps.bits.bTextureLodSupported = true;
160         }
161     }
162 
163     qCInfo(RENDER_TRACE_INFO, "OpenGL extensions: %s", extensions);
164 
165     // constant buffers support is always not true
166     m_backendSupport.caps.bits.bConstantBufferSupported = false;
167 
168     // query hardware
169     GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_maxAttribCount));
170 
171     // internal state tracker
172     m_pCurrentMiscState = new QSSGRenderBackendMiscStateGL();
173 
174     // finally setup caps based on device
175     setAndInspectHardwareCaps();
176 
177     // Initialize extensions
178 #if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
179     m_QSSGExtensions = new QSSGOpenGLES2Extensions;
180     m_QSSGExtensions->initializeOpenGLFunctions();
181 #endif
182 }
183 /// destructor
~QSSGRenderBackendGLES2Impl()184 QSSGRenderBackendGLES2Impl::~QSSGRenderBackendGLES2Impl()
185 {
186     delete m_pCurrentMiscState;
187 #if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
188     delete m_QSSGExtensions;
189 #endif
190 }
191 
setMultisampledTextureData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 samples,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,bool fixedsamplelocations)192 void QSSGRenderBackendGLES2Impl::setMultisampledTextureData2D(QSSGRenderBackendTextureObject to,
193                                                                 QSSGRenderTextureTargetType target,
194                                                                 qint32 samples,
195                                                                 QSSGRenderTextureFormat internalFormat,
196                                                                 qint32 width,
197                                                                 qint32 height,
198                                                                 bool fixedsamplelocations)
199 {
200     Q_UNUSED(to)
201     Q_UNUSED(target)
202     Q_UNUSED(samples)
203     Q_UNUSED(internalFormat)
204     Q_UNUSED(width)
205     Q_UNUSED(height)
206     Q_UNUSED(fixedsamplelocations)
207 }
208 
setTextureData3D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 depth,qint32 border,QSSGRenderTextureFormat format,QSSGByteView hostData)209 void QSSGRenderBackendGLES2Impl::setTextureData3D(QSSGRenderBackendTextureObject to,
210                                                     QSSGRenderTextureTargetType target,
211                                                     qint32 level,
212                                                     QSSGRenderTextureFormat internalFormat,
213                                                     qint32 width,
214                                                     qint32 height,
215                                                     qint32 depth,
216                                                     qint32 border,
217                                                     QSSGRenderTextureFormat format,
218                                                     QSSGByteView hostData)
219 {
220     GLuint texID = HandleToID_cast(GLuint, quintptr, to);
221     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
222     setActiveTexture(GL_TEXTURE0);
223     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
224     bool conversionRequired = format != internalFormat;
225 
226     QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
227     internalFormat = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), internalFormat, swizzleMode);
228 
229     GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
230 
231     if (internalFormat.isUncompressedTextureFormat()) {
232         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
233     }
234 
235     if (conversionRequired) {
236         GLenum dummy;
237         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, dummy);
238     } else if (internalFormat.isCompressedTextureFormat()) {
239         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
240         glInternalFormat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
241     } else if (format.isDepthTextureFormat()) {
242         GLConversion::fromDepthTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
243     }
244 
245     GL_CALL_EXTRA_FUNCTION(
246             glTexImage3D(glTarget, level, glInternalFormat, GLsizei(width), GLsizei(height), GLsizei(depth), border, glformat, gltype, hostData));
247 
248     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
249 }
250 
setTextureData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 border,QSSGRenderTextureFormat format,QSSGByteView hostData)251 void QSSGRenderBackendGLES2Impl::setTextureData2D(QSSGRenderBackendTextureObject to,
252                                                     QSSGRenderTextureTargetType target,
253                                                     qint32 level,
254                                                     QSSGRenderTextureFormat internalFormat,
255                                                     qint32 width,
256                                                     qint32 height,
257                                                     qint32 border,
258                                                     QSSGRenderTextureFormat format,
259                                                     QSSGByteView hostData)
260 {
261     GLuint texID = HandleToID_cast(GLuint, quintptr, to);
262     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
263     setActiveTexture(GL_TEXTURE0);
264     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
265     bool conversionRequired = format != internalFormat;
266 
267     QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
268     internalFormat = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), internalFormat, swizzleMode);
269 
270     GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
271 
272     if (internalFormat.isUncompressedTextureFormat()) {
273         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
274         glInternalFormat = glformat;
275     }
276 
277     if (conversionRequired) {
278         GLenum dummy;
279         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, dummy);
280     } else if (internalFormat.isCompressedTextureFormat()) {
281         GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
282         glInternalFormat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
283     } else if (format.isDepthTextureFormat()) {
284         GLConversion::fromDepthTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
285         if (format == QSSGRenderTextureFormat::Depth24Stencil8) {
286             glformat = GL_DEPTH_STENCIL_OES;
287             gltype = GL_UNSIGNED_INT_24_8;
288         }
289         glInternalFormat = glformat;
290     }
291 
292     Q_ASSERT(glformat == glInternalFormat);
293     GL_CALL_EXTRA_FUNCTION(
294             glTexImage2D(glTarget, level, glInternalFormat, GLsizei(width), GLsizei(height), border, glformat, gltype, hostData));
295     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
296 }
297 
updateSampler(QSSGRenderBackendSamplerObject,QSSGRenderTextureTargetType target,QSSGRenderTextureMinifyingOp minFilter,QSSGRenderTextureMagnifyingOp magFilter,QSSGRenderTextureCoordOp wrapS,QSSGRenderTextureCoordOp wrapT,QSSGRenderTextureCoordOp wrapR,float minLod,float maxLod,float lodBias,QSSGRenderTextureCompareMode compareMode,QSSGRenderTextureCompareOp compareFunc,float anisotropy,float * borderColor)298 void QSSGRenderBackendGLES2Impl::updateSampler(QSSGRenderBackendSamplerObject /* so */,
299                                                  QSSGRenderTextureTargetType target,
300                                                  QSSGRenderTextureMinifyingOp minFilter,
301                                                  QSSGRenderTextureMagnifyingOp magFilter,
302                                                  QSSGRenderTextureCoordOp wrapS,
303                                                  QSSGRenderTextureCoordOp wrapT,
304                                                  QSSGRenderTextureCoordOp wrapR,
305                                                  float minLod,
306                                                  float maxLod,
307                                                  float lodBias,
308                                                  QSSGRenderTextureCompareMode compareMode,
309                                                  QSSGRenderTextureCompareOp compareFunc,
310                                                  float anisotropy,
311                                                  float *borderColor)
312 {
313 
314     // Satisfy the compiler
315     // These are not available in GLES 3 and we don't use them right now
316     Q_ASSERT(qFuzzyIsNull(lodBias));
317     Q_ASSERT(!borderColor);
318     Q_UNUSED(lodBias)
319     Q_UNUSED(borderColor)
320     Q_UNUSED(wrapR)
321     Q_UNUSED(minLod)
322     Q_UNUSED(maxLod)
323     Q_UNUSED(compareMode)
324     Q_UNUSED(compareFunc)
325 
326     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
327 
328     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MIN_FILTER, m_conversion.fromTextureMinifyingOpToGL(minFilter)));
329     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAG_FILTER, m_conversion.fromTextureMagnifyingOpToGL(magFilter)));
330     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_S, m_conversion.fromTextureCoordOpToGL(wrapS)));
331     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_T, m_conversion.fromTextureCoordOpToGL(wrapT)));
332 
333     if (m_backendSupport.caps.bits.bAnistropySupported) {
334         GL_CALL_EXTRA_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy));
335     }
336 }
337 
updateTextureObject(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 baseLevel,qint32 maxLevel)338 void QSSGRenderBackendGLES2Impl::updateTextureObject(QSSGRenderBackendTextureObject to,
339                                                        QSSGRenderTextureTargetType target,
340                                                        qint32 baseLevel,
341                                                        qint32 maxLevel)
342 {
343     Q_UNUSED(to)
344 
345     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
346 
347     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_BASE_LEVEL, baseLevel));
348     GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAX_LEVEL, maxLevel));
349 }
350 
updateTextureSwizzle(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,QSSGRenderTextureSwizzleMode swizzleMode)351 void QSSGRenderBackendGLES2Impl::updateTextureSwizzle(QSSGRenderBackendTextureObject to,
352                                                         QSSGRenderTextureTargetType target,
353                                                         QSSGRenderTextureSwizzleMode swizzleMode)
354 {
355     Q_UNUSED(to)
356     Q_UNUSED(target)
357     Q_UNUSED(swizzleMode)
358 #if defined(QT_OPENGL_ES)
359     if (m_backendSupport.caps.bits.bTextureSwizzleSupported) {
360         GLint glSwizzle[4];
361         GLenum glTarget = m_conversion.fromTextureTargetToGL(target);
362         m_conversion.NVRenderConvertSwizzleModeToGL(swizzleMode, glSwizzle);
363 
364         // since ES3 spec has no GL_TEXTURE_SWIZZLE_RGBA set it separately
365         GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_R, glSwizzle[0]));
366         GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_G, glSwizzle[1]));
367         GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_B, glSwizzle[2]));
368         GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_A, glSwizzle[3]));
369     }
370 #endif
371 }
372 
getDepthBits() const373 qint32 QSSGRenderBackendGLES2Impl::getDepthBits() const
374 {
375     qint32 depthBits;
376     GL_CALL_EXTRA_FUNCTION(
377             glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depthBits));
378 
379     return depthBits;
380 }
381 
getStencilBits() const382 qint32 QSSGRenderBackendGLES2Impl::getStencilBits() const
383 {
384     qint32 stencilBits;
385     GL_CALL_EXTRA_FUNCTION(
386             glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencilBits));
387 
388     return stencilBits;
389 }
390 
generateMipMaps(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,QSSGRenderHint)391 void QSSGRenderBackendGLES2Impl::generateMipMaps(QSSGRenderBackendTextureObject to,
392                                                    QSSGRenderTextureTargetType target,
393                                                    QSSGRenderHint /*genType*/)
394 {
395     GLuint texID = HandleToID_cast(GLuint, quintptr, to);
396     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
397     setActiveTexture(GL_TEXTURE0);
398     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
399     GL_CALL_EXTRA_FUNCTION(glGenerateMipmap(glTarget));
400     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
401 }
402 
getShadingLanguageVersion()403 QByteArray QSSGRenderBackendGLES2Impl::getShadingLanguageVersion()
404 {
405     return QByteArrayLiteral("#version 100\n");
406 }
407 
setInputAssembler(QSSGRenderBackendInputAssemblerObject iao,QSSGRenderBackendShaderProgramObject po)408 bool QSSGRenderBackendGLES2Impl::setInputAssembler(QSSGRenderBackendInputAssemblerObject iao, QSSGRenderBackendShaderProgramObject po)
409 {
410     if (iao == nullptr) {
411         // unbind and return;
412         GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(0));
413         return true;
414     }
415 
416     QSSGRenderBackendInputAssemblerGL *inputAssembler = reinterpret_cast<QSSGRenderBackendInputAssemblerGL *>(iao);
417     QSSGRenderBackendAttributeLayoutGL *attribLayout = inputAssembler->m_attribLayout;
418     QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
419     GLuint programID = static_cast<GLuint>(pProgram->m_programID);
420     QSSGDataRef<QSSGRenderBackendShaderInputEntryGL> shaderAttribBuffer;
421     if (pProgram->m_shaderInput)
422         shaderAttribBuffer = pProgram->m_shaderInput->m_shaderInputEntries;
423 
424     if (inputAssembler->m_vertexbufferHandles.size() <= attribLayout->m_maxInputSlot)
425         return false;
426 
427     if (inputAssembler->m_vaoID == 0) {
428         // generate vao
429         GL_CALL_EXTENSION_FUNCTION(glGenVertexArraysOES(1, &inputAssembler->m_vaoID));
430         Q_ASSERT(inputAssembler->m_vaoID);
431     }
432 
433     if (inputAssembler->m_cachedShaderHandle != programID) {
434         GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(inputAssembler->m_vaoID));
435         inputAssembler->m_cachedShaderHandle = programID;
436 
437         for (const auto &attrib : qAsConst(shaderAttribBuffer)) {
438             QSSGRenderBackendLayoutEntryGL *entry = attribLayout->getEntryByName(attrib.m_attribName);
439 
440             if (entry) {
441                 QSSGRenderBackendLayoutEntryGL &entryData(*entry);
442                 if (Q_UNLIKELY(entryData.m_type != attrib.m_type || entryData.m_numComponents != attrib.m_numComponents)) {
443                     qCCritical(RENDER_INVALID_OPERATION, "Attrib %s dn't match vertex layout", attrib.m_attribName.constData());
444                     Q_ASSERT(false);
445                     return false;
446                 }
447 
448                 entryData.m_attribIndex = attrib.m_attribLocation;
449             } else {
450                 qCWarning(RENDER_WARNING, "Failed to Bind attribute %s", attrib.m_attribName.constData());
451             }
452         }
453 
454         // disable max possible used first
455         // this is currently sufficient since we always re-arrange input attributes from 0
456         for (int i = 0; i < attribLayout->m_layoutAttribEntries.size(); i++)
457             GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(GLuint(i)));
458 
459         // setup all attribs
460         GLuint boundArrayBufferId = 0; // 0 means unbound
461         for (int idx = 0; idx != shaderAttribBuffer.size(); ++idx)
462         {
463             QSSGRenderBackendLayoutEntryGL *entry = attribLayout->getEntryByName(shaderAttribBuffer[idx].m_attribName);
464             if (entry) {
465                 const QSSGRenderBackendLayoutEntryGL &entryData(*entry);
466                 GLuint id = HandleToID_cast(GLuint, quintptr, inputAssembler->m_vertexbufferHandles.mData[entryData.m_inputSlot]);
467                 if (boundArrayBufferId != id) {
468                     GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ARRAY_BUFFER, id));
469                     boundArrayBufferId = id;
470                 }
471                 GL_CALL_EXTRA_FUNCTION(glEnableVertexAttribArray(entryData.m_attribIndex));
472                 GLuint offset = inputAssembler->m_offsets.at(int(entryData.m_inputSlot));
473                 GLuint stride = inputAssembler->m_strides.at(int(entryData.m_inputSlot));
474                 GL_CALL_EXTRA_FUNCTION(glVertexAttribPointer(entryData.m_attribIndex,
475                                                              GLint(entryData.m_numComponents),
476                                                              GL_FLOAT,
477                                                              GL_FALSE,
478                                                              GLsizei(stride),
479                                                              reinterpret_cast<const void *>(quintptr(entryData.m_offset + offset))));
480 
481             } else {
482                 GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(GLuint(idx)));
483             }
484         }
485 
486         // setup index buffer.
487         if (inputAssembler->m_indexbufferHandle) {
488             GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
489                                                 HandleToID_cast(GLuint, quintptr, inputAssembler->m_indexbufferHandle)));
490         } else {
491             GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
492         }
493     } else {
494         GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(inputAssembler->m_vaoID));
495     }
496 
497     return true;
498 }
499 
setDrawBuffers(QSSGRenderBackendRenderTargetObject rto,QSSGDataView<qint32> inDrawBufferSet)500 void QSSGRenderBackendGLES2Impl::setDrawBuffers(QSSGRenderBackendRenderTargetObject rto, QSSGDataView<qint32> inDrawBufferSet)
501 {
502     Q_UNUSED(rto)
503 
504     m_drawBuffersArray.clear();
505 
506     for (int idx = 0, end = inDrawBufferSet.size(); idx < end; ++idx) {
507         if (inDrawBufferSet[idx] < 0)
508             m_drawBuffersArray.push_back(GL_NONE);
509         else
510             m_drawBuffersArray.push_back(GLenum(GL_COLOR_ATTACHMENT0 + inDrawBufferSet[idx]));
511     }
512 
513     GL_CALL_EXTRA_FUNCTION(glDrawBuffers(m_drawBuffersArray.size(), m_drawBuffersArray.data()));
514 }
515 
setReadBuffer(QSSGRenderBackendRenderTargetObject rto,QSSGReadFace inReadFace)516 void QSSGRenderBackendGLES2Impl::setReadBuffer(QSSGRenderBackendRenderTargetObject rto, QSSGReadFace inReadFace)
517 {
518     Q_UNUSED(rto)
519     Q_UNUSED(inReadFace)
520 }
521 
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment attachment,QSSGRenderBackendTextureObject to,qint32 level,qint32 layer)522 void QSSGRenderBackendGLES2Impl::renderTargetAttach(QSSGRenderBackendRenderTargetObject,
523                                                       QSSGRenderFrameBufferAttachment attachment,
524                                                       QSSGRenderBackendTextureObject to,
525                                                       qint32 level,
526                                                       qint32 layer)
527 {
528     Q_UNUSED(attachment)
529     Q_UNUSED(to)
530     Q_UNUSED(level)
531     Q_UNUSED(layer)
532     Q_ASSERT(false);
533 }
534 
blitFramebuffer(qint32 srcX0,qint32 srcY0,qint32 srcX1,qint32 srcY1,qint32 dstX0,qint32 dstY0,qint32 dstX1,qint32 dstY1,QSSGRenderClearFlags flags,QSSGRenderTextureMagnifyingOp filter)535 void QSSGRenderBackendGLES2Impl::blitFramebuffer(qint32 srcX0,
536                                                    qint32 srcY0,
537                                                    qint32 srcX1,
538                                                    qint32 srcY1,
539                                                    qint32 dstX0,
540                                                    qint32 dstY0,
541                                                    qint32 dstX1,
542                                                    qint32 dstY1,
543                                                    QSSGRenderClearFlags flags,
544                                                    QSSGRenderTextureMagnifyingOp filter)
545 {
546     GL_CALL_EXTRA_FUNCTION(glBlitFramebuffer(srcX0,
547                                              srcY0,
548                                              srcX1,
549                                              srcY1,
550                                              dstX0,
551                                              dstY0,
552                                              dstX1,
553                                              dstY1,
554                                              m_conversion.fromClearFlagsToGL(flags),
555                                              m_conversion.fromTextureMagnifyingOpToGL(filter)));
556 }
557 
copyFramebufferTexture(qint32 srcX0,qint32 srcY0,qint32 width,qint32 height,qint32 dstX0,qint32 dstY0,QSSGRenderBackendTextureObject texture,QSSGRenderTextureTargetType target)558 void QSSGRenderBackendGLES2Impl::copyFramebufferTexture(qint32 srcX0,
559                                                         qint32 srcY0,
560                                                         qint32 width,
561                                                         qint32 height,
562                                                         qint32 dstX0,
563                                                         qint32 dstY0,
564                                                         QSSGRenderBackendTextureObject texture,
565                                                         QSSGRenderTextureTargetType target)
566 {
567     GLuint texID = HandleToID_cast(GLuint, quintptr, texture);
568     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
569     setActiveTexture(GL_TEXTURE0);
570     GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID))
571     GL_CALL_EXTRA_FUNCTION(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, srcX0, srcY0, dstX0, dstY0,
572                                                width, height))
573 }
574 
createRenderTarget()575 QSSGRenderBackend::QSSGRenderBackendRenderTargetObject QSSGRenderBackendGLES2Impl::createRenderTarget()
576 {
577     GLuint fboID = 0;
578     GL_CALL_EXTRA_FUNCTION(glGenFramebuffers(1, &fboID));
579     return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendRenderTargetObject>(quintptr(fboID));
580 }
581 
releaseRenderTarget(QSSGRenderBackendRenderTargetObject rto)582 void QSSGRenderBackendGLES2Impl::releaseRenderTarget(QSSGRenderBackendRenderTargetObject rto)
583 {
584     GLuint fboID = HandleToID_cast(GLuint, quintptr, rto);
585 
586     if (fboID)
587         GL_CALL_EXTRA_FUNCTION(glDeleteFramebuffers(1, &fboID));
588 }
589 
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment attachment,QSSGRenderBackendRenderbufferObject rbo)590 void QSSGRenderBackendGLES2Impl::renderTargetAttach(QSSGRenderBackendRenderTargetObject /* rto */,
591                                                       QSSGRenderFrameBufferAttachment attachment,
592                                                       QSSGRenderBackendRenderbufferObject rbo)
593 {
594     // rto must be the current render target
595     GLuint rbID = HandleToID_cast(GLuint, quintptr, rbo);
596 
597     GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
598 
599     GL_CALL_EXTRA_FUNCTION(glFramebufferRenderbuffer(GL_FRAMEBUFFER, glAttach, GL_RENDERBUFFER, rbID));
600 }
601 
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment attachment,QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target)602 void QSSGRenderBackendGLES2Impl::renderTargetAttach(QSSGRenderBackendRenderTargetObject /* rto */,
603                                                       QSSGRenderFrameBufferAttachment attachment,
604                                                       QSSGRenderBackendTextureObject to,
605                                                       QSSGRenderTextureTargetType target)
606 {
607     // rto must be the current render target
608     GLuint texID = HandleToID_cast(GLuint, quintptr, to);
609 
610     Q_ASSERT(target == QSSGRenderTextureTargetType::Texture2D || m_backendSupport.caps.bits.bMsTextureSupported);
611 
612     GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
613     GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
614 
615     if (attachment == QSSGRenderFrameBufferAttachment::DepthStencil) {
616         GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, glTarget, texID, 0));
617         GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, glTarget, texID, 0));
618     } else {
619         GL_CALL_EXTRA_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, glAttach, glTarget, texID, 0));
620     }
621 }
622 
setRenderTarget(QSSGRenderBackendRenderTargetObject rto)623 void QSSGRenderBackendGLES2Impl::setRenderTarget(QSSGRenderBackendRenderTargetObject rto)
624 {
625     GLuint fboID = HandleToID_cast(GLuint, quintptr, rto);
626 
627     GL_CALL_EXTRA_FUNCTION(glBindFramebuffer(GL_FRAMEBUFFER, fboID));
628 }
629 
setReadTarget(QSSGRenderBackendRenderTargetObject rto)630 void QSSGRenderBackendGLES2Impl::setReadTarget(QSSGRenderBackendRenderTargetObject rto)
631 {
632     GLuint fboID = HandleToID_cast(GLuint, quintptr, rto);
633 
634     GL_CALL_EXTRA_FUNCTION(glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID));
635 }
636 
renderTargetIsValid(QSSGRenderBackendRenderTargetObject)637 bool QSSGRenderBackendGLES2Impl::renderTargetIsValid(QSSGRenderBackendRenderTargetObject /* rto */)
638 {
639     GLenum completeStatus = GL_CALL_EXTRA_FUNCTION(glCheckFramebufferStatus(GL_FRAMEBUFFER));
640     switch (completeStatus) {
641 #define HANDLE_INCOMPLETE_STATUS(x)                                                                                    \
642     case x:                                                                                                            \
643         qCCritical(RENDER_INTERNAL_ERROR, "Framebuffer is not complete: %s", #x);                                             \
644         return false;
645         HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
646         HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
647         HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
648         HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_UNSUPPORTED)
649 #undef HANDLE_INCOMPLETE_STATUS
650     }
651     return true;
652 }
653 
createRenderbuffer(QSSGRenderRenderBufferFormat storageFormat,qint32 width,qint32 height)654 QSSGRenderBackend::QSSGRenderBackendRenderbufferObject QSSGRenderBackendGLES2Impl::createRenderbuffer(QSSGRenderRenderBufferFormat storageFormat,
655                                                                                                             qint32 width,
656                                                                                                             qint32 height)
657 {
658     GLuint bufID = 0;
659 
660     GL_CALL_EXTRA_FUNCTION(glGenRenderbuffers(1, &bufID));
661     GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
662     GL_CALL_EXTRA_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
663                                                  GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
664                                                  GLsizei(width),
665                                                  GLsizei(height)));
666 
667     // check for error
668     GLenum error = m_glFunctions->glGetError();
669     if (error != GL_NO_ERROR) {
670         qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(error));
671         Q_ASSERT(false);
672         GL_CALL_EXTRA_FUNCTION(glDeleteRenderbuffers(1, &bufID));
673         bufID = 0;
674     }
675 
676     GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, 0));
677 
678     return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendRenderbufferObject>(quintptr(bufID));
679 }
680 
releaseRenderbuffer(QSSGRenderBackendRenderbufferObject rbo)681 void QSSGRenderBackendGLES2Impl::releaseRenderbuffer(QSSGRenderBackendRenderbufferObject rbo)
682 {
683     GLuint bufID = HandleToID_cast(GLuint, quintptr, rbo);
684 
685     if (bufID)
686         GL_CALL_EXTRA_FUNCTION(glDeleteRenderbuffers(1, &bufID));
687 }
688 
resizeRenderbuffer(QSSGRenderBackendRenderbufferObject rbo,QSSGRenderRenderBufferFormat storageFormat,qint32 width,qint32 height)689 bool QSSGRenderBackendGLES2Impl::resizeRenderbuffer(QSSGRenderBackendRenderbufferObject rbo,
690                                                       QSSGRenderRenderBufferFormat storageFormat,
691                                                       qint32 width,
692                                                       qint32 height)
693 {
694     bool success = true;
695     GLuint bufID = HandleToID_cast(GLuint, quintptr, rbo);
696 
697     Q_ASSERT(bufID);
698 
699     GL_CALL_EXTRA_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
700     GL_CALL_EXTRA_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
701                                                  GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
702                                                  GLsizei(width),
703                                                  GLsizei(height)));
704 
705     // check for error
706     GLenum error = m_glFunctions->glGetError();
707     if (error != GL_NO_ERROR) {
708         qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(error));
709         Q_ASSERT(false);
710         success = false;
711     }
712 
713     return success;
714 }
715 
mapBuffer(QSSGRenderBackendBufferObject,QSSGRenderBufferType bindFlags,size_t offset,size_t length,QSSGRenderBufferAccessFlags accessFlags)716 void *QSSGRenderBackendGLES2Impl::mapBuffer(QSSGRenderBackendBufferObject,
717                                               QSSGRenderBufferType bindFlags,
718                                               size_t offset,
719                                               size_t length,
720                                               QSSGRenderBufferAccessFlags accessFlags)
721 {
722     void *ret = nullptr;
723     ret = GL_CALL_EXTRA_FUNCTION(glMapBufferRange(m_conversion.fromBindBufferFlagsToGL(bindFlags),
724                                                   GLintptr(offset),
725                                                   GLsizeiptr(length),
726                                                   m_conversion.fromBufferAccessBitToGL(accessFlags)));
727 
728     return ret;
729 }
730 
unmapBuffer(QSSGRenderBackendBufferObject,QSSGRenderBufferType bindFlags)731 bool QSSGRenderBackendGLES2Impl::unmapBuffer(QSSGRenderBackendBufferObject, QSSGRenderBufferType bindFlags)
732 {
733     const GLboolean ret = GL_CALL_EXTRA_FUNCTION(glUnmapBuffer(m_conversion.fromBindBufferFlagsToGL(bindFlags)));
734     return (ret != 0);
735 }
736 
getConstantBufferCount(QSSGRenderBackendShaderProgramObject po)737 qint32 QSSGRenderBackendGLES2Impl::getConstantBufferCount(QSSGRenderBackendShaderProgramObject po)
738 {
739     Q_ASSERT(po);
740     GLint numUniformBuffers = 0;
741     if (getRenderBackendCap(QSSGRenderBackendCaps::ConstantBuffer)) {
742         QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
743         GLuint programID = static_cast<GLuint>(pProgram->m_programID);
744 
745         GL_CALL_EXTRA_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBuffers));
746     }
747     return numUniformBuffers;
748 }
749 
getConstantBufferInfoByID(QSSGRenderBackendShaderProgramObject po,quint32 id,quint32 nameBufSize,qint32 * paramCount,qint32 * bufferSize,qint32 * length,char * nameBuf)750 qint32 QSSGRenderBackendGLES2Impl::getConstantBufferInfoByID(QSSGRenderBackendShaderProgramObject po,
751                                                                quint32 id,
752                                                                quint32 nameBufSize,
753                                                                qint32 *paramCount,
754                                                                qint32 *bufferSize,
755                                                                qint32 *length,
756                                                                char *nameBuf)
757 {
758     Q_ASSERT(po);
759     Q_ASSERT(length);
760     Q_ASSERT(nameBuf);
761 
762     QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
763     GLuint programID = static_cast<GLuint>(pProgram->m_programID);
764     GLuint blockIndex = GL_INVALID_INDEX;
765 
766     GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockName(programID, id, GLsizei(nameBufSize), length, nameBuf));
767 
768     if (*length > 0) {
769         blockIndex = GL_CALL_EXTRA_FUNCTION(glGetUniformBlockIndex(programID, nameBuf));
770         if (blockIndex != GL_INVALID_INDEX) {
771             GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, bufferSize));
772             GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, paramCount));
773         }
774     }
775 
776     return qint32(blockIndex);
777 }
778 
getConstantBufferParamIndices(QSSGRenderBackendShaderProgramObject po,quint32 id,qint32 * indices)779 void QSSGRenderBackendGLES2Impl::getConstantBufferParamIndices(QSSGRenderBackendShaderProgramObject po, quint32 id, qint32 *indices)
780 {
781     Q_ASSERT(po);
782     Q_ASSERT(indices);
783 
784     QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
785     GLuint programID = static_cast<GLuint>(pProgram->m_programID);
786 
787     if (indices) {
788         GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, id, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices));
789     }
790 }
791 
getConstantBufferParamInfoByIndices(QSSGRenderBackendShaderProgramObject po,quint32 count,quint32 * indices,QSSGRenderShaderDataType * type,qint32 * size,qint32 * offset)792 void QSSGRenderBackendGLES2Impl::getConstantBufferParamInfoByIndices(QSSGRenderBackendShaderProgramObject po,
793                                                                        quint32 count,
794                                                                        quint32 *indices,
795                                                                        QSSGRenderShaderDataType *type,
796                                                                        qint32 *size,
797                                                                        qint32 *offset)
798 {
799     Q_ASSERT(po);
800     Q_ASSERT(count);
801     Q_ASSERT(indices);
802 
803     QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
804     GLuint programID = static_cast<GLuint>(pProgram->m_programID);
805 
806     if (count && indices) {
807         if (type) {
808             QVarLengthArray<qint32, 1024> glTypes(count);
809             GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, GLsizei(count), indices, GL_UNIFORM_TYPE, glTypes.data()));
810             // convert to UIC types
811             for (int idx = 0; idx != int(count); ++idx)
812                 type[idx] = GLConversion::fromShaderGLToPropertyDataTypes(GLenum(glTypes[idx]));
813         }
814         if (size) {
815             GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, GLsizei(count), indices, GL_UNIFORM_SIZE, size));
816         }
817         if (offset) {
818             GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, GLsizei(count), indices, GL_UNIFORM_OFFSET, offset));
819         }
820     }
821 }
822 
programSetConstantBlock(QSSGRenderBackendShaderProgramObject po,quint32 blockIndex,quint32 binding)823 void QSSGRenderBackendGLES2Impl::programSetConstantBlock(QSSGRenderBackendShaderProgramObject po, quint32 blockIndex, quint32 binding)
824 {
825     QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
826     GLuint programID = static_cast<GLuint>(pProgram->m_programID);
827 
828     GL_CALL_EXTRA_FUNCTION(glUniformBlockBinding(programID, blockIndex, binding));
829 }
830 
programSetConstantBuffer(quint32 index,QSSGRenderBackendBufferObject bo)831 void QSSGRenderBackendGLES2Impl::programSetConstantBuffer(quint32 index, QSSGRenderBackendBufferObject bo)
832 {
833     Q_ASSERT(bo);
834 
835     GLuint bufID = HandleToID_cast(GLuint, quintptr, bo);
836     GL_CALL_EXTRA_FUNCTION(glBindBufferBase(GL_UNIFORM_BUFFER, index, bufID));
837 }
838 
createQuery()839 QSSGRenderBackend::QSSGRenderBackendQueryObject QSSGRenderBackendGLES2Impl::createQuery()
840 {
841     quint32 glQueryID = 0;
842 
843     return reinterpret_cast<QSSGRenderBackendQueryObject>(quintptr(glQueryID));
844 }
845 
releaseQuery(QSSGRenderBackendQueryObject)846 void QSSGRenderBackendGLES2Impl::releaseQuery(QSSGRenderBackendQueryObject) {}
847 
beginQuery(QSSGRenderBackendQueryObject,QSSGRenderQueryType)848 void QSSGRenderBackendGLES2Impl::beginQuery(QSSGRenderBackendQueryObject, QSSGRenderQueryType) {}
849 
endQuery(QSSGRenderBackendQueryObject,QSSGRenderQueryType)850 void QSSGRenderBackendGLES2Impl::endQuery(QSSGRenderBackendQueryObject, QSSGRenderQueryType) {}
851 
getQueryResult(QSSGRenderBackendQueryObject,QSSGRenderQueryResultType,quint32 *)852 void QSSGRenderBackendGLES2Impl::getQueryResult(QSSGRenderBackendQueryObject, QSSGRenderQueryResultType, quint32 *)
853 {
854 }
855 
getQueryResult(QSSGRenderBackendQueryObject,QSSGRenderQueryResultType,quint64 *)856 void QSSGRenderBackendGLES2Impl::getQueryResult(QSSGRenderBackendQueryObject, QSSGRenderQueryResultType, quint64 *)
857 {
858 }
859 
setQueryTimer(QSSGRenderBackendQueryObject)860 void QSSGRenderBackendGLES2Impl::setQueryTimer(QSSGRenderBackendQueryObject) {}
861 
createSync(QSSGRenderSyncType,QSSGRenderSyncFlags)862 QSSGRenderBackend::QSSGRenderBackendSyncObject QSSGRenderBackendGLES2Impl::createSync(QSSGRenderSyncType, QSSGRenderSyncFlags)
863 {
864     GLsync syncID = nullptr;
865     return QSSGRenderBackendSyncObject(syncID);
866 }
867 
releaseSync(QSSGRenderBackendSyncObject)868 void QSSGRenderBackendGLES2Impl::releaseSync(QSSGRenderBackendSyncObject) {}
869 
waitSync(QSSGRenderBackendSyncObject,QSSGRenderCommandFlushFlags,quint64)870 void QSSGRenderBackendGLES2Impl::waitSync(QSSGRenderBackendSyncObject, QSSGRenderCommandFlushFlags, quint64) {}
871 
872 QT_END_NAMESPACE
873