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