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/qssgrenderbackendglbase_p.h>
32 #include <QtQuick3DRender/private/qssgrenderbackendinputassemblergl_p.h>
33 #include <QtQuick3DRender/private/qssgrenderbackendshaderprogramgl_p.h>
34 #include <QtQuick3DRender/private/qssgrenderbackendrenderstatesgl_p.h>
35
36 QT_BEGIN_NAMESPACE
37
38 #ifdef RENDER_BACKEND_LOG_GL_ERRORS
39 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__)
40 #else
41 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError()
42 #endif
43
44 #define GL_CALL_FUNCTION(x) \
45 m_glFunctions->x; \
46 RENDER_LOG_ERROR_PARAMS(x);
47 #define GL_CALL_EXTRA_FUNCTION(x) \
48 m_glExtraFunctions->x; \
49 RENDER_LOG_ERROR_PARAMS(x);
50
51 #ifndef GL_PROGRAM_SEPARABLE
52 #define GL_PROGRAM_SEPARABLE 0x8258
53 #endif
54
55 #ifndef GL_UNSIGNED_INT_IMAGE_2D
56 #define GL_UNSIGNED_INT_IMAGE_2D 0x9063
57 #endif
58
59 #ifndef GL_UNSIGNED_INT_ATOMIC_COUNTER
60 #define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
61 #endif
62
63 #ifndef GL_PROGRAM_BINARY_LENGTH
64 #define GL_PROGRAM_BINARY_LENGTH 0x8741
65 #endif
66
67 namespace QSSGGlExtStrings {
exts3tc()68 QByteArray exts3tc()
69 {
70 return QByteArrayLiteral("GL_EXT_texture_compression_s3tc");
71 }
extsdxt()72 QByteArray extsdxt()
73 {
74 return QByteArrayLiteral("GL_EXT_texture_compression_dxt1");
75 }
extsAniso()76 QByteArray extsAniso()
77 {
78 return QByteArrayLiteral("GL_EXT_texture_filter_anisotropic");
79 }
extsTexSwizzle()80 QByteArray extsTexSwizzle()
81 {
82 return QByteArrayLiteral("GL_ARB_texture_swizzle");
83 }
extsFPRenderTarget()84 QByteArray extsFPRenderTarget()
85 {
86 return QByteArrayLiteral("GL_EXT_color_buffer_float");
87 }
extsTimerQuery()88 QByteArray extsTimerQuery()
89 {
90 return QByteArrayLiteral("GL_EXT_timer_query");
91 }
extsGpuShader5()92 QByteArray extsGpuShader5()
93 {
94 return QByteArrayLiteral("EXT_gpu_shader5");
95 }
96 }
97
98 /// constructor
QSSGRenderBackendGLBase(const QSurfaceFormat & format)99 QSSGRenderBackendGLBase::QSSGRenderBackendGLBase(const QSurfaceFormat &format)
100 : m_conversion(), m_maxAttribCount(0), m_format(format)
101 {
102 m_glFunctions = new QOpenGLFunctions;
103 m_glFunctions->initializeOpenGLFunctions();
104 m_glExtraFunctions = new QOpenGLExtraFunctions;
105 m_glExtraFunctions->initializeOpenGLFunctions();
106
107 const QByteArray languageVersion = getShadingLanguageVersionString();
108 qCInfo(RENDER_TRACE_INFO, "GLSL version: %s", languageVersion.constData());
109
110 const QByteArray apiVersion(getVersionString());
111 qCInfo(RENDER_TRACE_INFO, "GL version: %s", apiVersion.constData());
112
113 const QByteArray apiVendor(getVendorString());
114 qCInfo(RENDER_TRACE_INFO, "HW vendor: %s", apiVendor.constData());
115
116 const QByteArray apiRenderer(getRendererString());
117 qCInfo(RENDER_TRACE_INFO, "Vendor renderer: %s", apiRenderer.constData());
118
119 // internal state tracker
120 m_currentRasterizerState = new QSSGRenderBackendRasterizerStateGL();
121 m_currentDepthStencilState = new QSSGRenderBackendDepthStencilStateGL();
122 }
123 /// destructor
~QSSGRenderBackendGLBase()124 QSSGRenderBackendGLBase::~QSSGRenderBackendGLBase()
125 {
126 delete m_currentRasterizerState;
127 delete m_currentDepthStencilState;
128 delete m_glFunctions;
129 delete m_glExtraFunctions;
130 }
131
getRenderContextType() const132 QSSGRenderContextType QSSGRenderBackendGLBase::getRenderContextType() const
133 {
134 if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
135 if (m_format.majorVersion() == 2)
136 return QSSGRenderContextType::GLES2;
137
138 if (m_format.majorVersion() == 3) {
139 if (m_format.minorVersion() >= 1)
140 return QSSGRenderContextType::GLES3PLUS;
141 return QSSGRenderContextType::GLES3;
142 }
143 } else if (m_format.majorVersion() == 2) {
144 return QSSGRenderContextType::GL2;
145 } else if (m_format.majorVersion() == 3) {
146 return QSSGRenderContextType::GL3;
147 } else if (m_format.majorVersion() == 4) {
148 return QSSGRenderContextType::GL4;
149 }
150
151 return QSSGRenderContextType::NullContext;
152 }
153
isESCompatible() const154 bool QSSGRenderBackendGLBase::isESCompatible() const
155 {
156 return m_format.renderableType() == QSurfaceFormat::OpenGLES;
157 }
158
getShadingLanguageVersion()159 QByteArray QSSGRenderBackendGLBase::getShadingLanguageVersion()
160 {
161 QByteArray ver;
162 QTextStream stream(&ver);
163 stream << "#version ";
164 const int minor = m_format.minorVersion();
165 switch (getRenderContextType()) {
166 case QSSGRenderContextType::GLES2:
167 stream << "1" << minor << "0\n";
168 break;
169 case QSSGRenderContextType::GL2:
170 stream << "1" << minor << "0\n";
171 break;
172 case QSSGRenderContextType::GLES3PLUS:
173 case QSSGRenderContextType::GLES3:
174 stream << "3" << minor << "0 es\n";
175 break;
176 case QSSGRenderContextType::GL3:
177 if (minor == 3)
178 stream << "3" << minor << "0\n";
179 else
180 stream << "1" << 3 + minor << "0\n";
181 break;
182 case QSSGRenderContextType::GL4:
183 stream << "4" << minor << "0\n";
184 break;
185 default:
186 Q_ASSERT(false);
187 break;
188 }
189
190 return ver;
191 }
192
getMaxCombinedTextureUnits()193 qint32 QSSGRenderBackendGLBase::getMaxCombinedTextureUnits()
194 {
195 qint32 maxUnits;
196 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits));
197 return maxUnits;
198 }
199
getRenderBackendCap(QSSGRenderBackend::QSSGRenderBackendCaps inCap) const200 bool QSSGRenderBackendGLBase::getRenderBackendCap(QSSGRenderBackend::QSSGRenderBackendCaps inCap) const
201 {
202 bool bSupported = false;
203
204 switch (inCap) {
205 case QSSGRenderBackendCaps::FpRenderTarget:
206 bSupported = m_backendSupport.caps.bits.bFPRenderTargetsSupported;
207 break;
208 case QSSGRenderBackendCaps::DepthStencilTexture:
209 bSupported = m_backendSupport.caps.bits.bDepthStencilSupported;
210 break;
211 case QSSGRenderBackendCaps::ConstantBuffer:
212 bSupported = m_backendSupport.caps.bits.bConstantBufferSupported;
213 break;
214 case QSSGRenderBackendCaps::DxtImages:
215 bSupported = m_backendSupport.caps.bits.bDXTImagesSupported;
216 break;
217 case QSSGRenderBackendCaps::MsTexture:
218 bSupported = m_backendSupport.caps.bits.bMsTextureSupported;
219 break;
220 case QSSGRenderBackendCaps::TexSwizzle:
221 bSupported = m_backendSupport.caps.bits.bTextureSwizzleSupported;
222 break;
223 case QSSGRenderBackendCaps::FastBlits:
224 bSupported = m_backendSupport.caps.bits.bFastBlitsSupported;
225 break;
226 case QSSGRenderBackendCaps::Tessellation:
227 bSupported = m_backendSupport.caps.bits.bTessellationSupported;
228 break;
229 case QSSGRenderBackendCaps::Compute:
230 bSupported = m_backendSupport.caps.bits.bComputeSupported;
231 break;
232 case QSSGRenderBackendCaps::Geometry:
233 bSupported = m_backendSupport.caps.bits.bGeometrySupported;
234 break;
235 case QSSGRenderBackendCaps::SampleQuery: {
236 // On the following context sample query is not supported
237 QSSGRenderContextTypes noSamplesQuerySupportedContextFlags(QSSGRenderContextType::GL2 | QSSGRenderContextType::GLES2);
238 QSSGRenderContextType ctxType = getRenderContextType();
239 bSupported = !(noSamplesQuerySupportedContextFlags & ctxType);
240 } break;
241 case QSSGRenderBackendCaps::TimerQuery:
242 bSupported = m_backendSupport.caps.bits.bTimerQuerySupported;
243 break;
244 case QSSGRenderBackendCaps::CommandSync: {
245 // On the following context sync objects are not supported
246 QSSGRenderContextTypes noSyncObjectSupportedContextFlags(QSSGRenderContextType::GL2 | QSSGRenderContextType::GLES2);
247 QSSGRenderContextType ctxType = getRenderContextType();
248 bSupported = !(noSyncObjectSupportedContextFlags & ctxType);
249 } break;
250 case QSSGRenderBackendCaps::TextureArray: {
251 // On the following context texture arrays are not supported
252 QSSGRenderContextTypes noTextureArraySupportedContextFlags(QSSGRenderContextType::GL2 | QSSGRenderContextType::GLES2);
253 QSSGRenderContextType ctxType = getRenderContextType();
254 bSupported = !(noTextureArraySupportedContextFlags& ctxType);
255 } break;
256 case QSSGRenderBackendCaps::StorageBuffer:
257 bSupported = m_backendSupport.caps.bits.bStorageBufferSupported;
258 break;
259 case QSSGRenderBackendCaps::ShaderImageLoadStore:
260 bSupported = m_backendSupport.caps.bits.bShaderImageLoadStoreSupported;
261 break;
262 case QSSGRenderBackendCaps::ProgramPipeline:
263 bSupported = m_backendSupport.caps.bits.bProgramPipelineSupported;
264 break;
265 case QSSGRenderBackendCaps::AdvancedBlend:
266 bSupported = m_backendSupport.caps.bits.bNVAdvancedBlendSupported | m_backendSupport.caps.bits.bKHRAdvancedBlendSupported;
267 break;
268 case QSSGRenderBackendCaps::AdvancedBlendKHR:
269 bSupported = m_backendSupport.caps.bits.bKHRAdvancedBlendSupported;
270 break;
271 case QSSGRenderBackendCaps::BlendCoherency:
272 bSupported = m_backendSupport.caps.bits.bNVBlendCoherenceSupported | m_backendSupport.caps.bits.bKHRBlendCoherenceSupported;
273 break;
274 case QSSGRenderBackendCaps::gpuShader5:
275 bSupported = m_backendSupport.caps.bits.bGPUShader5ExtensionSupported;
276 break;
277 case QSSGRenderBackendCaps::VertexArrayObject:
278 bSupported = m_backendSupport.caps.bits.bVertexArrayObjectSupported;
279 break;
280 case QSSGRenderBackendCaps::StandardDerivatives:
281 bSupported = m_backendSupport.caps.bits.bStandardDerivativesSupported;
282 break;
283 case QSSGRenderBackendCaps::TextureLod:
284 bSupported = m_backendSupport.caps.bits.bTextureLodSupported;
285 break;
286 default:
287 Q_ASSERT(false);
288 bSupported = false;
289 break;
290 }
291
292 return bSupported;
293 }
294
getRenderBackendValue(QSSGRenderBackendQuery inQuery,qint32 * params) const295 void QSSGRenderBackendGLBase::getRenderBackendValue(QSSGRenderBackendQuery inQuery, qint32 *params) const
296 {
297 if (params) {
298 switch (inQuery) {
299 case QSSGRenderBackendQuery::MaxTextureSize:
300 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_TEXTURE_SIZE, params));
301 break;
302 case QSSGRenderBackendQuery::MaxTextureArrayLayers: {
303 QSSGRenderContextTypes noTextureArraySupportedContextFlags(QSSGRenderContextType::GL2
304 | QSSGRenderContextType::GLES2);
305 QSSGRenderContextType ctxType = getRenderContextType();
306 if (!(noTextureArraySupportedContextFlags & ctxType)) {
307 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, params));
308 } else {
309 *params = 0;
310 }
311 } break;
312 case QSSGRenderBackendQuery::MaxConstantBufferSlots: {
313 QSSGRenderContextTypes noConstantBufferSupportedContextFlags(QSSGRenderContextType::GL2
314 | QSSGRenderContextType::GLES2);
315 QSSGRenderContextType ctxType = getRenderContextType();
316 if (!(noConstantBufferSupportedContextFlags & ctxType)) {
317 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, params));
318 } else {
319 *params = 0;
320 }
321 } break;
322 case QSSGRenderBackendQuery::MaxConstantBufferBlockSize: {
323 QSSGRenderContextTypes noConstantBufferSupportedContextFlags(QSSGRenderContextType::GL2
324 | QSSGRenderContextType::GLES2);
325 QSSGRenderContextType ctxType = getRenderContextType();
326 if (!(noConstantBufferSupportedContextFlags & ctxType)) {
327 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, params));
328 } else {
329 *params = 0;
330 }
331 } break;
332 default:
333 Q_ASSERT(false);
334 *params = 0;
335 break;
336 }
337 }
338 }
339
getDepthBits() const340 qint32 QSSGRenderBackendGLBase::getDepthBits() const
341 {
342 qint32 depthBits;
343 GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_BITS, &depthBits));
344 return depthBits;
345 }
346
getStencilBits() const347 qint32 QSSGRenderBackendGLBase::getStencilBits() const
348 {
349 qint32 stencilBits;
350 GL_CALL_FUNCTION(glGetIntegerv(GL_STENCIL_BITS, &stencilBits));
351 return stencilBits;
352 }
353
getMaxSamples() const354 qint32 QSSGRenderBackendGLBase::getMaxSamples() const
355 {
356 qint32 maxSamples;
357 GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_SAMPLES, &maxSamples));
358 return maxSamples;
359 }
360
setMultisample(bool bEnable)361 void QSSGRenderBackendGLBase::setMultisample(bool bEnable)
362 {
363 Q_ASSERT(m_backendSupport.caps.bits.bMsTextureSupported || !bEnable);
364 // For GL ES explicit multisample enabling is not needed
365 // and does not exist
366 QSSGRenderContextTypes noMsaaEnableContextFlags(QSSGRenderContextType::GLES2 | QSSGRenderContextType::GLES3
367 | QSSGRenderContextType::GLES3PLUS);
368 QSSGRenderContextType ctxType = getRenderContextType();
369 if (!(noMsaaEnableContextFlags & ctxType)) {
370 setRenderState(bEnable, QSSGRenderState::Multisample);
371 }
372 }
373
setRenderState(bool bEnable,const QSSGRenderState value)374 void QSSGRenderBackendGLBase::setRenderState(bool bEnable, const QSSGRenderState value)
375 {
376 if (value == QSSGRenderState::DepthWrite) {
377 GL_CALL_FUNCTION(glDepthMask(bEnable));
378 } else {
379 if (bEnable) {
380 GL_CALL_FUNCTION(glEnable(m_conversion.fromRenderStateToGL(value)));
381 } else {
382 GL_CALL_FUNCTION(glDisable(m_conversion.fromRenderStateToGL(value)));
383 }
384 }
385 }
386
createDepthStencilState(bool enableDepth,bool depthMask,QSSGRenderBoolOp depthFunc,bool enableStencil,QSSGRenderStencilFunction & stencilFuncFront,QSSGRenderStencilFunction & stencilFuncBack,QSSGRenderStencilOperation & depthStencilOpFront,QSSGRenderStencilOperation & depthStencilOpBack)387 QSSGRenderBackend::QSSGRenderBackendDepthStencilStateObject QSSGRenderBackendGLBase::createDepthStencilState(
388 bool enableDepth,
389 bool depthMask,
390 QSSGRenderBoolOp depthFunc,
391 bool enableStencil,
392 QSSGRenderStencilFunction &stencilFuncFront,
393 QSSGRenderStencilFunction &stencilFuncBack,
394 QSSGRenderStencilOperation &depthStencilOpFront,
395 QSSGRenderStencilOperation &depthStencilOpBack)
396 {
397 QSSGRenderBackendDepthStencilStateGL *retval = new QSSGRenderBackendDepthStencilStateGL(enableDepth,
398 depthMask,
399 depthFunc,
400 enableStencil,
401 stencilFuncFront,
402 stencilFuncBack,
403 depthStencilOpFront,
404 depthStencilOpBack);
405
406 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendDepthStencilStateObject>(retval);
407 }
408
releaseDepthStencilState(QSSGRenderBackendDepthStencilStateObject inDepthStencilState)409 void QSSGRenderBackendGLBase::releaseDepthStencilState(QSSGRenderBackendDepthStencilStateObject inDepthStencilState)
410 {
411 QSSGRenderBackendDepthStencilStateGL *inputState = reinterpret_cast<QSSGRenderBackendDepthStencilStateGL *>(inDepthStencilState);
412 delete inputState;
413 }
414
createRasterizerState(float depthBias,float depthScale)415 QSSGRenderBackend::QSSGRenderBackendRasterizerStateObject QSSGRenderBackendGLBase::createRasterizerState(float depthBias,
416 float depthScale)
417 {
418 QSSGRenderBackendRasterizerStateGL *retval = new QSSGRenderBackendRasterizerStateGL(depthBias, depthScale);
419
420 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendRasterizerStateObject>(retval);
421 }
422
releaseRasterizerState(QSSGRenderBackendRasterizerStateObject rasterizerState)423 void QSSGRenderBackendGLBase::releaseRasterizerState(QSSGRenderBackendRasterizerStateObject rasterizerState)
424 {
425 delete reinterpret_cast<QSSGRenderBackendRasterizerStateGL *>(rasterizerState);
426 }
427
setDepthStencilState(QSSGRenderBackendDepthStencilStateObject inDepthStencilState)428 void QSSGRenderBackendGLBase::setDepthStencilState(QSSGRenderBackendDepthStencilStateObject inDepthStencilState)
429 {
430 QSSGRenderBackendDepthStencilStateGL *inputState = reinterpret_cast<QSSGRenderBackendDepthStencilStateGL *>(inDepthStencilState);
431 if (inputState && !(*m_currentDepthStencilState == *inputState)) {
432 // we check on a per single state base
433 if (inputState->m_depthEnable != m_currentDepthStencilState->m_depthEnable) {
434 setRenderState(inputState->m_depthEnable, QSSGRenderState::DepthTest);
435 m_currentDepthStencilState->m_depthEnable = inputState->m_depthEnable;
436 }
437 if (inputState->m_stencilEnable != m_currentDepthStencilState->m_stencilEnable) {
438 setRenderState(inputState->m_stencilEnable, QSSGRenderState::StencilTest);
439 m_currentDepthStencilState->m_stencilEnable = inputState->m_stencilEnable;
440 }
441
442 if (inputState->m_depthMask != m_currentDepthStencilState->m_depthMask) {
443 GL_CALL_FUNCTION(glDepthMask(inputState->m_depthMask));
444 m_currentDepthStencilState->m_depthMask = inputState->m_depthMask;
445 }
446
447 if (inputState->m_depthFunc != m_currentDepthStencilState->m_depthFunc) {
448 GL_CALL_FUNCTION(glDepthFunc(m_conversion.fromBoolOpToGL(inputState->m_depthFunc)));
449 m_currentDepthStencilState->m_depthFunc = inputState->m_depthFunc;
450 }
451
452 if (!(inputState->m_depthStencilOpFront == m_currentDepthStencilState->m_depthStencilOpFront)) {
453 GL_CALL_FUNCTION(
454 glStencilOpSeparate(GL_FRONT,
455 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpFront.m_stencilFail),
456 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpFront.m_depthFail),
457 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpFront.m_depthPass)));
458 m_currentDepthStencilState->m_depthStencilOpFront = inputState->m_depthStencilOpFront;
459 }
460
461 if (!(inputState->m_depthStencilOpBack == m_currentDepthStencilState->m_depthStencilOpBack)) {
462 GL_CALL_FUNCTION(glStencilOpSeparate(GL_BACK,
463 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpBack.m_stencilFail),
464 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpBack.m_depthFail),
465 m_conversion.fromStencilOpToGL(inputState->m_depthStencilOpBack.m_depthPass)));
466 m_currentDepthStencilState->m_depthStencilOpBack = inputState->m_depthStencilOpBack;
467 }
468
469 if (!(inputState->m_stencilFuncFront == m_currentDepthStencilState->m_stencilFuncFront)) {
470 GL_CALL_FUNCTION(glStencilFuncSeparate(GL_FRONT,
471 m_conversion.fromBoolOpToGL(inputState->m_stencilFuncFront.m_function),
472 inputState->m_stencilFuncFront.m_referenceValue,
473 inputState->m_stencilFuncFront.m_mask));
474 m_currentDepthStencilState->m_stencilFuncFront = inputState->m_stencilFuncFront;
475 }
476
477 if (!(inputState->m_stencilFuncBack == m_currentDepthStencilState->m_stencilFuncBack)) {
478 GL_CALL_FUNCTION(glStencilFuncSeparate(GL_BACK,
479 m_conversion.fromBoolOpToGL(inputState->m_stencilFuncBack.m_function),
480 inputState->m_stencilFuncBack.m_referenceValue,
481 inputState->m_stencilFuncBack.m_mask));
482 m_currentDepthStencilState->m_stencilFuncBack = inputState->m_stencilFuncBack;
483 }
484 }
485 }
486
setRasterizerState(QSSGRenderBackendRasterizerStateObject rasterizerState)487 void QSSGRenderBackendGLBase::setRasterizerState(QSSGRenderBackendRasterizerStateObject rasterizerState)
488 {
489 QSSGRenderBackendRasterizerStateGL *inputState = (QSSGRenderBackendRasterizerStateGL *)rasterizerState;
490 if (inputState && !(*m_currentRasterizerState == *inputState)) {
491 // store current state
492 *m_currentRasterizerState = *inputState;
493
494 if (m_currentRasterizerState->m_depthBias != 0.0f || m_currentRasterizerState->m_depthScale != 0.0f) {
495 GL_CALL_FUNCTION(glEnable(GL_POLYGON_OFFSET_FILL));
496 } else {
497 GL_CALL_FUNCTION(glDisable(GL_POLYGON_OFFSET_FILL));
498 }
499
500 GL_CALL_FUNCTION(glPolygonOffset(m_currentRasterizerState->m_depthBias, m_currentRasterizerState->m_depthScale));
501 }
502 }
503
getRenderState(const QSSGRenderState value)504 bool QSSGRenderBackendGLBase::getRenderState(const QSSGRenderState value)
505 {
506 bool enabled = GL_CALL_FUNCTION(glIsEnabled(m_conversion.fromRenderStateToGL(value)));
507 return enabled;
508 }
509
getDepthFunc()510 QSSGRenderBoolOp QSSGRenderBackendGLBase::getDepthFunc()
511 {
512 qint32 value;
513 GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_FUNC, &value));
514 return GLConversion::fromGLToBoolOp(value);
515 }
516
setDepthFunc(const QSSGRenderBoolOp func)517 void QSSGRenderBackendGLBase::setDepthFunc(const QSSGRenderBoolOp func)
518 {
519 GL_CALL_FUNCTION(glDepthFunc(m_conversion.fromBoolOpToGL(func)));
520 }
521
getDepthWrite()522 bool QSSGRenderBackendGLBase::getDepthWrite()
523 {
524 qint32 value;
525 GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_WRITEMASK, reinterpret_cast<GLint *>(&value)));
526 return (value != 0);
527 }
528
setDepthWrite(bool bEnable)529 void QSSGRenderBackendGLBase::setDepthWrite(bool bEnable)
530 {
531 GL_CALL_FUNCTION(glDepthMask(bEnable));
532 }
533
setColorWrites(bool bRed,bool bGreen,bool bBlue,bool bAlpha)534 void QSSGRenderBackendGLBase::setColorWrites(bool bRed, bool bGreen, bool bBlue, bool bAlpha)
535 {
536 GL_CALL_FUNCTION(glColorMask(bRed, bGreen, bBlue, bAlpha));
537 }
538
getBlendFunc(QSSGRenderBlendFunctionArgument * pBlendFuncArg)539 void QSSGRenderBackendGLBase::getBlendFunc(QSSGRenderBlendFunctionArgument *pBlendFuncArg)
540 {
541 Q_ASSERT(pBlendFuncArg);
542 qint32_4 values;
543
544 GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_SRC_RGB, reinterpret_cast<GLint *>(&values.x)));
545 GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_SRC_ALPHA, reinterpret_cast<GLint *>(&values.y)));
546 GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_DST_RGB, reinterpret_cast<GLint *>(&values.z)));
547 GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_DST_ALPHA, reinterpret_cast<GLint *>(&values.w)));
548
549 pBlendFuncArg->m_srcRgb = GLConversion::fromGLToSrcBlendFunc(values.x);
550 pBlendFuncArg->m_srcAlpha = GLConversion::fromGLToSrcBlendFunc(values.y);
551 pBlendFuncArg->m_dstRgb = GLConversion::fromGLToDstBlendFunc(values.z);
552 pBlendFuncArg->m_dstAlpha = GLConversion::fromGLToDstBlendFunc(values.w);
553 }
554
setBlendFunc(const QSSGRenderBlendFunctionArgument & blendFuncArg)555 void QSSGRenderBackendGLBase::setBlendFunc(const QSSGRenderBlendFunctionArgument &blendFuncArg)
556 {
557 qint32_4 values;
558
559 values.x = GLConversion::fromSrcBlendFuncToGL(blendFuncArg.m_srcRgb);
560 values.y = GLConversion::fromDstBlendFuncToGL(blendFuncArg.m_dstRgb);
561 values.z = GLConversion::fromSrcBlendFuncToGL(blendFuncArg.m_srcAlpha);
562 values.w = GLConversion::fromDstBlendFuncToGL(blendFuncArg.m_dstAlpha);
563
564 GL_CALL_FUNCTION(glBlendFuncSeparate(values.x, values.y, values.z, values.w));
565 }
566
setBlendEquation(const QSSGRenderBlendEquationArgument &)567 void QSSGRenderBackendGLBase::setBlendEquation(const QSSGRenderBlendEquationArgument &)
568 {
569 // needs GL4 / GLES 3.1
570 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
571 }
572
setBlendBarrier()573 void QSSGRenderBackendGLBase::setBlendBarrier()
574 {
575 // needs GL4 / GLES 3.1
576 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
577 }
578
getCullFaceMode()579 QSSGCullFaceMode QSSGRenderBackendGLBase::getCullFaceMode()
580 {
581 GLint value;
582 GL_CALL_FUNCTION(glGetIntegerv(GL_CULL_FACE_MODE, &value));
583 return GLConversion::fromGLToCullFaceMode(static_cast<GLenum>(value));
584 }
585
setCullFaceMode(const QSSGCullFaceMode cullFaceMode)586 void QSSGRenderBackendGLBase::setCullFaceMode(const QSSGCullFaceMode cullFaceMode)
587 {
588 GL_CALL_FUNCTION(glCullFace(GLConversion::fromCullFaceModeToGL(cullFaceMode)));
589 }
590
getScissorRect(QRect * pRect)591 void QSSGRenderBackendGLBase::getScissorRect(QRect *pRect)
592 {
593 Q_ASSERT(pRect);
594 GL_CALL_FUNCTION(glGetIntegerv(GL_SCISSOR_BOX, reinterpret_cast<GLint *>(pRect)));
595 }
596
setScissorRect(const QRect & rect)597 void QSSGRenderBackendGLBase::setScissorRect(const QRect &rect)
598 {
599 GL_CALL_FUNCTION(glScissor(rect.x(), rect.y(), rect.width(), rect.height()));
600 }
601
getViewportRect(QRect * pRect)602 void QSSGRenderBackendGLBase::getViewportRect(QRect *pRect)
603 {
604 Q_ASSERT(pRect);
605 GL_CALL_FUNCTION(glGetIntegerv(GL_VIEWPORT, reinterpret_cast<GLint *>(pRect)));
606 }
607
setViewportRect(const QRect & rect)608 void QSSGRenderBackendGLBase::setViewportRect(const QRect &rect)
609 {
610 GL_CALL_FUNCTION(glViewport(rect.x(), rect.y(), rect.width(), rect.height()););
611 }
612
setClearColor(const QVector4D * pClearColor)613 void QSSGRenderBackendGLBase::setClearColor(const QVector4D *pClearColor)
614 {
615 Q_ASSERT(pClearColor);
616
617 GL_CALL_FUNCTION(glClearColor(pClearColor->x(), pClearColor->y(), pClearColor->z(), pClearColor->w()));
618 }
619
clear(QSSGRenderClearFlags flags)620 void QSSGRenderBackendGLBase::clear(QSSGRenderClearFlags flags)
621 {
622 GL_CALL_FUNCTION(glClear(m_conversion.fromClearFlagsToGL(flags)));
623 }
624
createBuffer(QSSGRenderBufferType bindFlags,QSSGRenderBufferUsageType usage,QSSGByteView hostData)625 QSSGRenderBackend::QSSGRenderBackendBufferObject QSSGRenderBackendGLBase::createBuffer(QSSGRenderBufferType bindFlags,
626 QSSGRenderBufferUsageType usage,
627 QSSGByteView hostData)
628 {
629 GLuint bufID = 0;
630
631 GL_CALL_FUNCTION(glGenBuffers(1, &bufID));
632
633 if (bufID && hostData.size()) {
634 GLenum target = GLConversion::fromBindBufferFlagsToGL(bindFlags);
635 if (target != GL_INVALID_ENUM) {
636 GL_CALL_FUNCTION(glBindBuffer(target, bufID));
637 GL_CALL_FUNCTION(glBufferData(target, hostData.size(), hostData, m_conversion.fromBufferUsageTypeToGL(usage)));
638 } else {
639 GL_CALL_FUNCTION(glDeleteBuffers(1, &bufID));
640 bufID = 0;
641 qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(target));
642 }
643 }
644
645 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendBufferObject>(quintptr(bufID));
646 }
647
bindBuffer(QSSGRenderBackendBufferObject bo,QSSGRenderBufferType bindFlags)648 void QSSGRenderBackendGLBase::bindBuffer(QSSGRenderBackendBufferObject bo, QSSGRenderBufferType bindFlags)
649 {
650 GLuint bufID = HandleToID_cast(GLuint, quintptr, bo);
651 GL_CALL_FUNCTION(glBindBuffer(m_conversion.fromBindBufferFlagsToGL(bindFlags), bufID));
652 }
653
releaseBuffer(QSSGRenderBackendBufferObject bo)654 void QSSGRenderBackendGLBase::releaseBuffer(QSSGRenderBackendBufferObject bo)
655 {
656 GLuint bufID = HandleToID_cast(GLuint, quintptr, bo);
657 GL_CALL_FUNCTION(glDeleteBuffers(1, &bufID));
658 }
659
updateBuffer(QSSGRenderBackendBufferObject bo,QSSGRenderBufferType bindFlags,QSSGRenderBufferUsageType usage,QSSGByteView data)660 void QSSGRenderBackendGLBase::updateBuffer(QSSGRenderBackendBufferObject bo,
661 QSSGRenderBufferType bindFlags,
662 QSSGRenderBufferUsageType usage,
663 QSSGByteView data)
664 {
665 GLuint bufID = HandleToID_cast(GLuint, quintptr, bo);
666 GLenum target = GLConversion::fromBindBufferFlagsToGL(bindFlags);
667 GL_CALL_FUNCTION(glBindBuffer(target, bufID));
668 GL_CALL_FUNCTION(glBufferData(target, data.size(), data, m_conversion.fromBufferUsageTypeToGL(usage)));
669 }
670
updateBufferRange(QSSGRenderBackendBufferObject bo,QSSGRenderBufferType bindFlags,size_t offset,QSSGByteView data)671 void QSSGRenderBackendGLBase::updateBufferRange(QSSGRenderBackendBufferObject bo,
672 QSSGRenderBufferType bindFlags,
673 size_t offset,
674 QSSGByteView data)
675 {
676 GLuint bufID = HandleToID_cast(GLuint, quintptr, bo);
677 GLenum target = GLConversion::fromBindBufferFlagsToGL(bindFlags);
678 GL_CALL_FUNCTION(glBindBuffer(target, bufID));
679 GL_CALL_FUNCTION(glBufferSubData(target, offset, data.size(), data));
680 }
681
mapBuffer(QSSGRenderBackendBufferObject,QSSGRenderBufferType,size_t,size_t,QSSGRenderBufferAccessFlags)682 void *QSSGRenderBackendGLBase::mapBuffer(QSSGRenderBackendBufferObject, QSSGRenderBufferType, size_t, size_t, QSSGRenderBufferAccessFlags)
683 {
684 // needs GL 3 context
685 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
686
687 return nullptr;
688 }
689
unmapBuffer(QSSGRenderBackendBufferObject,QSSGRenderBufferType)690 bool QSSGRenderBackendGLBase::unmapBuffer(QSSGRenderBackendBufferObject, QSSGRenderBufferType)
691 {
692 // needs GL 3 context
693 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
694
695 return true;
696 }
697
setMemoryBarrier(QSSGRenderBufferBarrierFlags)698 void QSSGRenderBackendGLBase::setMemoryBarrier(QSSGRenderBufferBarrierFlags)
699 {
700 // needs GL 4 context
701 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
702 }
703
createQuery()704 QSSGRenderBackend::QSSGRenderBackendQueryObject QSSGRenderBackendGLBase::createQuery()
705 {
706 // needs GL 3 context
707 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
708
709 return QSSGRenderBackendQueryObject(nullptr);
710 }
711
releaseQuery(QSSGRenderBackendQueryObject)712 void QSSGRenderBackendGLBase::releaseQuery(QSSGRenderBackendQueryObject)
713 {
714 // needs GL 3 context
715 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
716 }
717
beginQuery(QSSGRenderBackendQueryObject,QSSGRenderQueryType)718 void QSSGRenderBackendGLBase::beginQuery(QSSGRenderBackendQueryObject, QSSGRenderQueryType)
719 {
720 // needs GL 3 context
721 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
722 }
723
endQuery(QSSGRenderBackendQueryObject,QSSGRenderQueryType)724 void QSSGRenderBackendGLBase::endQuery(QSSGRenderBackendQueryObject, QSSGRenderQueryType)
725 {
726 // needs GL 3 context
727 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
728 }
729
getQueryResult(QSSGRenderBackendQueryObject,QSSGRenderQueryResultType,quint32 *)730 void QSSGRenderBackendGLBase::getQueryResult(QSSGRenderBackendQueryObject, QSSGRenderQueryResultType, quint32 *)
731 {
732 // needs GL 3 context
733 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
734 }
735
getQueryResult(QSSGRenderBackendQueryObject,QSSGRenderQueryResultType,quint64 *)736 void QSSGRenderBackendGLBase::getQueryResult(QSSGRenderBackendQueryObject, QSSGRenderQueryResultType, quint64 *)
737 {
738 // needs GL 3 context
739 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
740 }
741
setQueryTimer(QSSGRenderBackendQueryObject)742 void QSSGRenderBackendGLBase::setQueryTimer(QSSGRenderBackendQueryObject)
743 {
744 // needs GL 3 context
745 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
746 }
747
createSync(QSSGRenderSyncType,QSSGRenderSyncFlags)748 QSSGRenderBackend::QSSGRenderBackendSyncObject QSSGRenderBackendGLBase::createSync(QSSGRenderSyncType, QSSGRenderSyncFlags)
749 {
750 // needs GL 3 context
751 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
752
753 return QSSGRenderBackendSyncObject(nullptr);
754 }
755
releaseSync(QSSGRenderBackendSyncObject)756 void QSSGRenderBackendGLBase::releaseSync(QSSGRenderBackendSyncObject)
757 {
758 // needs GL 3 context
759 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
760 }
761
waitSync(QSSGRenderBackendSyncObject,QSSGRenderCommandFlushFlags,quint64)762 void QSSGRenderBackendGLBase::waitSync(QSSGRenderBackendSyncObject, QSSGRenderCommandFlushFlags, quint64)
763 {
764 // needs GL 3 context
765 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
766 }
767
createRenderTarget()768 QSSGRenderBackend::QSSGRenderBackendRenderTargetObject QSSGRenderBackendGLBase::createRenderTarget()
769 {
770 GLuint fboID = 0;
771
772 GL_CALL_FUNCTION(glGenFramebuffers(1, &fboID));
773
774 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendRenderTargetObject>(quintptr(fboID));
775 }
776
releaseRenderTarget(QSSGRenderBackendRenderTargetObject rto)777 void QSSGRenderBackendGLBase::releaseRenderTarget(QSSGRenderBackendRenderTargetObject rto)
778 {
779 GLuint fboID = HandleToID_cast(GLuint, quintptr, rto);
780
781 if (fboID) {
782 GL_CALL_FUNCTION(glDeleteFramebuffers(1, &fboID));
783 }
784 }
785
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment attachment,QSSGRenderBackendRenderbufferObject rbo)786 void QSSGRenderBackendGLBase::renderTargetAttach(QSSGRenderBackendRenderTargetObject /* rto */,
787 QSSGRenderFrameBufferAttachment attachment,
788 QSSGRenderBackendRenderbufferObject rbo)
789 {
790 // rto must be the current render target
791 GLuint rbID = HandleToID_cast(GLuint, quintptr, rbo);
792
793 GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
794
795 GL_CALL_FUNCTION(glFramebufferRenderbuffer(GL_FRAMEBUFFER, glAttach, GL_RENDERBUFFER, rbID));
796 }
797
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment attachment,QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target)798 void QSSGRenderBackendGLBase::renderTargetAttach(QSSGRenderBackendRenderTargetObject /* rto */,
799 QSSGRenderFrameBufferAttachment attachment,
800 QSSGRenderBackendTextureObject to,
801 QSSGRenderTextureTargetType target)
802 {
803 // rto must be the current render target
804 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
805
806 Q_ASSERT(target == QSSGRenderTextureTargetType::Texture2D || m_backendSupport.caps.bits.bMsTextureSupported);
807
808 GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
809 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
810
811 GL_CALL_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, glAttach, glTarget, texID, 0))
812 }
813
renderTargetAttach(QSSGRenderBackendRenderTargetObject,QSSGRenderFrameBufferAttachment,QSSGRenderBackendTextureObject,qint32,qint32)814 void QSSGRenderBackendGLBase::renderTargetAttach(QSSGRenderBackendRenderTargetObject,
815 QSSGRenderFrameBufferAttachment,
816 QSSGRenderBackendTextureObject,
817 qint32,
818 qint32)
819 {
820 // Needs GL3 or GLES 3
821 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
822 }
823
setRenderTarget(QSSGRenderBackendRenderTargetObject rto)824 void QSSGRenderBackendGLBase::setRenderTarget(QSSGRenderBackendRenderTargetObject rto)
825 {
826 GLuint fboID = HandleToID_cast(GLuint, quintptr, rto);
827
828 GL_CALL_FUNCTION(glBindFramebuffer(GL_FRAMEBUFFER, fboID));
829 }
830
renderTargetIsValid(QSSGRenderBackendRenderTargetObject)831 bool QSSGRenderBackendGLBase::renderTargetIsValid(QSSGRenderBackendRenderTargetObject /* rto */)
832 {
833 // rto must be the current render target
834 GLenum completeStatus = GL_CALL_FUNCTION(glCheckFramebufferStatus(GL_FRAMEBUFFER));
835 switch (completeStatus) {
836 #define HANDLE_INCOMPLETE_STATUS(x) \
837 case x: \
838 qCCritical(RENDER_INTERNAL_ERROR, "Framebuffer is not complete: %s", #x); \
839 return false;
840 HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
841 HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
842 HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
843 HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_UNSUPPORTED)
844 #undef HANDLE_INCOMPLETE_STATUS
845 }
846 return true;
847 }
848
createRenderbuffer(QSSGRenderRenderBufferFormat storageFormat,qint32 width,qint32 height)849 QSSGRenderBackend::QSSGRenderBackendRenderbufferObject QSSGRenderBackendGLBase::createRenderbuffer(QSSGRenderRenderBufferFormat storageFormat,
850 qint32 width,
851 qint32 height)
852 {
853 GLuint bufID = 0;
854
855 GL_CALL_FUNCTION(glGenRenderbuffers(1, &bufID));
856 GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
857 GL_CALL_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
858 GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
859 GLsizei(width),
860 GLsizei(height)));
861
862 // check for error
863 GLenum error = m_glFunctions->glGetError();
864 if (error != GL_NO_ERROR) {
865 qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(error));
866 Q_ASSERT(false);
867 GL_CALL_FUNCTION(glDeleteRenderbuffers(1, &bufID));
868 bufID = 0;
869 }
870
871 GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, 0));
872
873 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendRenderbufferObject>(quintptr(bufID));
874 }
875
releaseRenderbuffer(QSSGRenderBackendRenderbufferObject rbo)876 void QSSGRenderBackendGLBase::releaseRenderbuffer(QSSGRenderBackendRenderbufferObject rbo)
877 {
878 GLuint bufID = HandleToID_cast(GLuint, quintptr, rbo);
879
880 if (bufID) {
881 GL_CALL_FUNCTION(glDeleteRenderbuffers(1, &bufID));
882 }
883 }
884
resizeRenderbuffer(QSSGRenderBackendRenderbufferObject rbo,QSSGRenderRenderBufferFormat storageFormat,qint32 width,qint32 height)885 bool QSSGRenderBackendGLBase::resizeRenderbuffer(QSSGRenderBackendRenderbufferObject rbo,
886 QSSGRenderRenderBufferFormat storageFormat,
887 qint32 width,
888 qint32 height)
889 {
890 bool success = true;
891 GLuint bufID = HandleToID_cast(GLuint, quintptr, rbo);
892
893 Q_ASSERT(bufID);
894
895 GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
896 GL_CALL_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
897 GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
898 GLsizei(width),
899 GLsizei(height)));
900
901 // check for error
902 GLenum error = m_glFunctions->glGetError();
903 if (error != GL_NO_ERROR) {
904 qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(error));
905 Q_ASSERT(false);
906 success = false;
907 }
908
909 return success;
910 }
911
createTexture()912 QSSGRenderBackend::QSSGRenderBackendTextureObject QSSGRenderBackendGLBase::createTexture()
913 {
914 GLuint texID = 0;
915
916 GL_CALL_FUNCTION(glGenTextures(1, &texID));
917 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendTextureObject>(quintptr(texID));
918 }
919
bindTexture(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 unit)920 void QSSGRenderBackendGLBase::bindTexture(QSSGRenderBackendTextureObject to,
921 QSSGRenderTextureTargetType target,
922 qint32 unit)
923 {
924 Q_ASSERT(unit >= 0);
925 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
926 setActiveTexture(GL_TEXTURE0 + GLenum(unit));
927
928 GL_CALL_FUNCTION(glBindTexture(m_conversion.fromTextureTargetToGL(target), texID));
929 }
930
setActiveTexture(qint32 unit)931 void QSSGRenderBackendGLBase::setActiveTexture(qint32 unit)
932 {
933 if (unit != m_activatedTextureUnit) {
934 GL_CALL_FUNCTION(glActiveTexture(GLenum(unit)))
935 m_activatedTextureUnit = unit;
936 }
937 }
938
bindImageTexture(QSSGRenderBackendTextureObject,quint32,qint32,bool,qint32,QSSGRenderImageAccessType,QSSGRenderTextureFormat)939 void QSSGRenderBackendGLBase::bindImageTexture(QSSGRenderBackendTextureObject,
940 quint32,
941 qint32,
942 bool,
943 qint32,
944 QSSGRenderImageAccessType,
945 QSSGRenderTextureFormat)
946 {
947 // needs GL 4 context
948 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
949 }
950
releaseTexture(QSSGRenderBackendTextureObject to)951 void QSSGRenderBackendGLBase::releaseTexture(QSSGRenderBackendTextureObject to)
952 {
953 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
954 GL_CALL_FUNCTION(glDeleteTextures(1, &texID));
955 }
956
setTextureData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 border,QSSGRenderTextureFormat format,QSSGByteView hostData)957 void QSSGRenderBackendGLBase::setTextureData2D(QSSGRenderBackendTextureObject to,
958 QSSGRenderTextureTargetType target,
959 qint32 level,
960 QSSGRenderTextureFormat internalFormat,
961 qint32 width,
962 qint32 height,
963 qint32 border,
964 QSSGRenderTextureFormat format,
965 QSSGByteView hostData)
966 {
967 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
968 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
969 setActiveTexture(GL_TEXTURE0);
970 GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
971 bool conversionRequired = format != internalFormat;
972
973 QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
974 internalFormat = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), internalFormat, swizzleMode);
975
976 GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
977
978 if (internalFormat.isUncompressedTextureFormat())
979 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
980
981 if (conversionRequired) {
982 GLenum dummy;
983 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, dummy);
984 } else if (internalFormat.isCompressedTextureFormat()) {
985 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
986 glInternalFormat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
987 } else if (format.isDepthTextureFormat()) {
988 GLConversion::fromDepthTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
989 }
990
991 GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, GLsizei(width), GLsizei(height), border, glformat, gltype, hostData));
992
993 GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
994 }
995
996 // This will look very SetTextureData2D, but the target for glBindTexture will be different from
997 // the target for
998 // glTexImage2D.
setTextureDataCubeFace(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 border,QSSGRenderTextureFormat format,QSSGByteView hostData)999 void QSSGRenderBackendGLBase::setTextureDataCubeFace(QSSGRenderBackendTextureObject to,
1000 QSSGRenderTextureTargetType target,
1001 qint32 level,
1002 QSSGRenderTextureFormat internalFormat,
1003 qint32 width,
1004 qint32 height,
1005 qint32 border,
1006 QSSGRenderTextureFormat format,
1007 QSSGByteView hostData)
1008 {
1009 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1010 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1011 GLenum glTexTarget = GLConversion::fromTextureTargetToGL(QSSGRenderTextureTargetType::TextureCube);
1012 setActiveTexture(GL_TEXTURE0);
1013 GL_CALL_FUNCTION(glBindTexture(glTexTarget, texID));
1014 bool conversionRequired = format != internalFormat;
1015
1016 QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
1017 internalFormat = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), internalFormat, swizzleMode);
1018
1019 GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
1020
1021 if (internalFormat.isUncompressedTextureFormat())
1022 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
1023
1024 if (conversionRequired) {
1025 GLenum dummy;
1026 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, dummy);
1027 } else if (internalFormat.isCompressedTextureFormat()) {
1028 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
1029 glInternalFormat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
1030 } else if (format.isDepthTextureFormat()) {
1031 GLConversion::fromDepthTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
1032 }
1033
1034 // for es2 internal format must be same as format
1035 if (getRenderContextType() == QSSGRenderContextType::GLES2)
1036 glInternalFormat = glformat;
1037
1038 GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, GLsizei(width), GLsizei(height), border, glformat, gltype, hostData));
1039
1040 GL_CALL_FUNCTION(glBindTexture(glTexTarget, 0));
1041 }
1042
createTextureStorage2D(QSSGRenderBackendTextureObject,QSSGRenderTextureTargetType,qint32,QSSGRenderTextureFormat,qint32,qint32)1043 void QSSGRenderBackendGLBase::createTextureStorage2D(QSSGRenderBackendTextureObject,
1044 QSSGRenderTextureTargetType,
1045 qint32,
1046 QSSGRenderTextureFormat,
1047 qint32,
1048 qint32)
1049 {
1050 // you need GL 4.2 or GLES 3.1
1051 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1052 }
1053
setTextureSubData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,qint32 xOffset,qint32 yOffset,qint32 width,qint32 height,QSSGRenderTextureFormat format,QSSGByteView hostData)1054 void QSSGRenderBackendGLBase::setTextureSubData2D(QSSGRenderBackendTextureObject to,
1055 QSSGRenderTextureTargetType target,
1056 qint32 level,
1057 qint32 xOffset,
1058 qint32 yOffset,
1059 qint32 width,
1060 qint32 height,
1061 QSSGRenderTextureFormat format,
1062 QSSGByteView hostData)
1063 {
1064 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1065 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1066 setActiveTexture(GL_TEXTURE0);
1067 GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
1068
1069 QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
1070 format = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), format, swizzleMode);
1071
1072 GLenum glformat = 0, glInternalFormat = 0, gltype = 0;
1073 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), format, glformat, gltype, glInternalFormat);
1074 GL_CALL_FUNCTION(glTexSubImage2D(glTarget, level, xOffset, yOffset, GLsizei(width), GLsizei(height), glformat, gltype, hostData));
1075
1076 GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
1077 }
1078
setCompressedTextureData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 border,QSSGByteView hostData)1079 void QSSGRenderBackendGLBase::setCompressedTextureData2D(QSSGRenderBackendTextureObject to,
1080 QSSGRenderTextureTargetType target,
1081 qint32 level,
1082 QSSGRenderTextureFormat internalFormat,
1083 qint32 width,
1084 qint32 height,
1085 qint32 border,
1086 QSSGByteView hostData)
1087 {
1088 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1089 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1090 setActiveTexture(GL_TEXTURE0);
1091 GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
1092
1093 GLenum glformat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
1094 GL_CALL_FUNCTION(glCompressedTexImage2D(glTarget, level, glformat, GLsizei(width), GLsizei(height), border, GLsizei(hostData.size()), hostData));
1095
1096 GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
1097 }
1098
setCompressedTextureDataCubeFace(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,qint32 border,QSSGByteView hostData)1099 void QSSGRenderBackendGLBase::setCompressedTextureDataCubeFace(QSSGRenderBackendTextureObject to,
1100 QSSGRenderTextureTargetType target,
1101 qint32 level,
1102 QSSGRenderTextureFormat internalFormat,
1103 qint32 width,
1104 qint32 height,
1105 qint32 border,
1106 QSSGByteView hostData)
1107 {
1108 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1109 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1110 GLenum glTexTarget = GLConversion::fromTextureTargetToGL(QSSGRenderTextureTargetType::TextureCube);
1111 setActiveTexture(GL_TEXTURE0);
1112 GL_CALL_FUNCTION(glBindTexture(glTexTarget, texID));
1113
1114 GLenum glformat = GLConversion::fromCompressedTextureFormatToGL(internalFormat);
1115 GL_CALL_FUNCTION(glCompressedTexImage2D(glTarget, level, glformat, GLsizei(width), GLsizei(height), border, GLsizei(hostData.size()), hostData));
1116
1117 GL_CALL_FUNCTION(glBindTexture(glTexTarget, 0));
1118 }
1119
setCompressedTextureSubData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 level,qint32 xOffset,qint32 yOffset,qint32 width,qint32 height,QSSGRenderTextureFormat format,QSSGByteView hostData)1120 void QSSGRenderBackendGLBase::setCompressedTextureSubData2D(QSSGRenderBackendTextureObject to,
1121 QSSGRenderTextureTargetType target,
1122 qint32 level,
1123 qint32 xOffset,
1124 qint32 yOffset,
1125 qint32 width,
1126 qint32 height,
1127 QSSGRenderTextureFormat format,
1128 QSSGByteView hostData)
1129 {
1130 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1131 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1132 setActiveTexture(GL_TEXTURE0);
1133 GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
1134
1135 GLenum glformat = GLConversion::fromCompressedTextureFormatToGL(format);
1136 GL_CALL_FUNCTION(
1137 glCompressedTexSubImage2D(glTarget, level, xOffset, yOffset, GLsizei(width), GLsizei(height), glformat, GLsizei(hostData.size()), hostData));
1138
1139 GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
1140 }
1141
setTextureData3D(QSSGRenderBackendTextureObject,QSSGRenderTextureTargetType,qint32,QSSGRenderTextureFormat,qint32,qint32,qint32,qint32,QSSGRenderTextureFormat,QSSGByteView)1142 void QSSGRenderBackendGLBase::setTextureData3D(QSSGRenderBackendTextureObject,
1143 QSSGRenderTextureTargetType,
1144 qint32,
1145 QSSGRenderTextureFormat,
1146 qint32,
1147 qint32,
1148 qint32,
1149 qint32,
1150 QSSGRenderTextureFormat,
1151 QSSGByteView)
1152 {
1153 // needs GL3 or GLES3
1154 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1155 }
1156
generateMipMaps(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,QSSGRenderHint genType)1157 void QSSGRenderBackendGLBase::generateMipMaps(QSSGRenderBackendTextureObject to,
1158 QSSGRenderTextureTargetType target,
1159 QSSGRenderHint genType)
1160 {
1161 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
1162 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1163 setActiveTexture(GL_TEXTURE0);
1164 GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
1165
1166 GLenum glValue = GLConversion::fromHintToGL(genType);
1167 GL_CALL_FUNCTION(glHint(GL_GENERATE_MIPMAP_HINT, glValue));
1168 GL_CALL_FUNCTION(glGenerateMipmap(glTarget));
1169
1170 GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
1171 }
1172
getTextureSwizzleMode(const QSSGRenderTextureFormat inFormat) const1173 QSSGRenderTextureSwizzleMode QSSGRenderBackendGLBase::getTextureSwizzleMode(const QSSGRenderTextureFormat inFormat) const
1174 {
1175 QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
1176 GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), inFormat, swizzleMode);
1177
1178 return swizzleMode;
1179 }
1180
createSampler(QSSGRenderTextureMinifyingOp minFilter,QSSGRenderTextureMagnifyingOp magFilter,QSSGRenderTextureCoordOp wrapS,QSSGRenderTextureCoordOp wrapT,QSSGRenderTextureCoordOp wrapR,qint32 minLod,qint32 maxLod,float lodBias,QSSGRenderTextureCompareMode compareMode,QSSGRenderTextureCompareOp compareFunc,float anisotropy,float * borderColor)1181 QSSGRenderBackend::QSSGRenderBackendSamplerObject QSSGRenderBackendGLBase::createSampler(
1182 QSSGRenderTextureMinifyingOp minFilter,
1183 QSSGRenderTextureMagnifyingOp magFilter,
1184 QSSGRenderTextureCoordOp wrapS,
1185 QSSGRenderTextureCoordOp wrapT,
1186 QSSGRenderTextureCoordOp wrapR,
1187 qint32 minLod,
1188 qint32 maxLod,
1189 float lodBias,
1190 QSSGRenderTextureCompareMode compareMode,
1191 QSSGRenderTextureCompareOp compareFunc,
1192 float anisotropy,
1193 float *borderColor)
1194 {
1195 // Satisfy the compiler
1196 // We don"t setup the state here for GL
1197 // but we need to pass on the variables here
1198 // to satisfy the interface
1199 Q_UNUSED(minFilter)
1200 Q_UNUSED(magFilter)
1201 Q_UNUSED(wrapS)
1202 Q_UNUSED(wrapT)
1203 Q_UNUSED(wrapR)
1204 Q_UNUSED(minLod)
1205 Q_UNUSED(maxLod)
1206 Q_UNUSED(lodBias)
1207 Q_UNUSED(compareMode)
1208 Q_UNUSED(compareFunc)
1209 Q_UNUSED(anisotropy)
1210 Q_UNUSED(borderColor)
1211
1212 // return a dummy handle
1213 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendSamplerObject>(0x0001);
1214 }
1215
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)1216 void QSSGRenderBackendGLBase::updateSampler(QSSGRenderBackendSamplerObject /* so */,
1217 QSSGRenderTextureTargetType target,
1218 QSSGRenderTextureMinifyingOp minFilter,
1219 QSSGRenderTextureMagnifyingOp magFilter,
1220 QSSGRenderTextureCoordOp wrapS,
1221 QSSGRenderTextureCoordOp wrapT,
1222 QSSGRenderTextureCoordOp wrapR,
1223 float minLod,
1224 float maxLod,
1225 float lodBias,
1226 QSSGRenderTextureCompareMode compareMode,
1227 QSSGRenderTextureCompareOp compareFunc,
1228 float anisotropy,
1229 float *borderColor)
1230 {
1231 // Satisfy the compiler
1232 // These are not available in GLES 2 and we don't use them right now
1233 Q_UNUSED(wrapR)
1234 Q_UNUSED(lodBias)
1235 Q_UNUSED(minLod)
1236 Q_UNUSED(maxLod)
1237 Q_UNUSED(compareMode)
1238 Q_UNUSED(compareFunc)
1239 Q_UNUSED(borderColor)
1240
1241 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
1242
1243 GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MIN_FILTER, m_conversion.fromTextureMinifyingOpToGL(minFilter)));
1244 GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAG_FILTER, m_conversion.fromTextureMagnifyingOpToGL(magFilter)));
1245 GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_S, m_conversion.fromTextureCoordOpToGL(wrapS)));
1246 GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_T, m_conversion.fromTextureCoordOpToGL(wrapT)));
1247 if (m_backendSupport.caps.bits.bAnistropySupported) {
1248 GL_CALL_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy));
1249 }
1250 }
1251
updateTextureObject(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 baseLevel,qint32 maxLevel)1252 void QSSGRenderBackendGLBase::updateTextureObject(QSSGRenderBackendTextureObject to,
1253 QSSGRenderTextureTargetType target,
1254 qint32 baseLevel,
1255 qint32 maxLevel)
1256 {
1257 Q_UNUSED(to)
1258 Q_UNUSED(target)
1259 Q_UNUSED(baseLevel)
1260 Q_UNUSED(maxLevel)
1261 }
1262
updateTextureSwizzle(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,QSSGRenderTextureSwizzleMode swizzleMode)1263 void QSSGRenderBackendGLBase::updateTextureSwizzle(QSSGRenderBackendTextureObject to,
1264 QSSGRenderTextureTargetType target,
1265 QSSGRenderTextureSwizzleMode swizzleMode)
1266 {
1267 Q_UNUSED(to)
1268 Q_UNUSED(target)
1269
1270 // Nothing to do here still might be called
1271 Q_ASSERT(swizzleMode == QSSGRenderTextureSwizzleMode::NoSwizzle);
1272
1273 Q_UNUSED(swizzleMode)
1274 }
1275
releaseSampler(QSSGRenderBackendSamplerObject so)1276 void QSSGRenderBackendGLBase::releaseSampler(QSSGRenderBackendSamplerObject so)
1277 {
1278 GLuint samplerID = HandleToID_cast(GLuint, quintptr, so);
1279 if (!samplerID)
1280 return;
1281 // otherwise nothing to do
1282 }
1283
createAttribLayout(QSSGDataView<QSSGRenderVertexBufferEntry> attribs)1284 QSSGRenderBackend::QSSGRenderBackendAttribLayoutObject QSSGRenderBackendGLBase::createAttribLayout(
1285 QSSGDataView<QSSGRenderVertexBufferEntry> attribs)
1286 {
1287 quint32 attribLayoutSize = sizeof(QSSGRenderBackendAttributeLayoutGL);
1288 quint32 entrySize = sizeof(QSSGRenderBackendLayoutEntryGL) * attribs.size();
1289 quint8 *newMem = static_cast<quint8 *>(::malloc(attribLayoutSize + entrySize));
1290 QSSGDataRef<QSSGRenderBackendLayoutEntryGL> entryRef = PtrAtOffset<QSSGRenderBackendLayoutEntryGL>(newMem, attribLayoutSize, entrySize);
1291 quint32 maxInputSlot = 0;
1292
1293 // copy data
1294 for (int idx = 0; idx != attribs.size(); ++idx) {
1295 new (&entryRef[idx]) QSSGRenderBackendLayoutEntryGL();
1296 entryRef[idx].m_attribName = attribs.mData[idx].m_name;
1297 entryRef[idx].m_normalize = 0;
1298 entryRef[idx].m_attribIndex = 0; // will be set later
1299 entryRef[idx].m_type = GLConversion::fromComponentTypeAndNumCompsToAttribGL(attribs.mData[idx].m_componentType,
1300 attribs.mData[idx].m_numComponents);
1301 entryRef[idx].m_numComponents = attribs.mData[idx].m_numComponents;
1302 entryRef[idx].m_inputSlot = attribs.mData[idx].m_inputSlot;
1303 entryRef[idx].m_offset = attribs.mData[idx].m_firstItemOffset;
1304
1305 if (maxInputSlot < entryRef[idx].m_inputSlot)
1306 maxInputSlot = entryRef[idx].m_inputSlot;
1307 }
1308
1309 QSSGRenderBackendAttributeLayoutGL *retval = new (newMem) QSSGRenderBackendAttributeLayoutGL(entryRef, maxInputSlot);
1310
1311 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendAttribLayoutObject>(retval);
1312 }
1313
releaseAttribLayout(QSSGRenderBackendAttribLayoutObject ao)1314 void QSSGRenderBackendGLBase::releaseAttribLayout(QSSGRenderBackendAttribLayoutObject ao)
1315 {
1316 QSSGRenderBackendAttributeLayoutGL *attribLayout = reinterpret_cast<QSSGRenderBackendAttributeLayoutGL *>(ao);
1317 if (attribLayout) { // Created with malloc, so release with free!
1318 attribLayout->~QSSGRenderBackendAttributeLayoutGL();
1319 ::free(attribLayout);
1320 attribLayout = nullptr;
1321 }
1322 };
1323
createInputAssembler(QSSGRenderBackendAttribLayoutObject attribLayout,QSSGDataView<QSSGRenderBackendBufferObject> buffers,const QSSGRenderBackendBufferObject indexBuffer,QSSGDataView<quint32> strides,QSSGDataView<quint32> offsets,quint32 patchVertexCount)1324 QSSGRenderBackend::QSSGRenderBackendInputAssemblerObject QSSGRenderBackendGLBase::createInputAssembler(
1325 QSSGRenderBackendAttribLayoutObject attribLayout,
1326 QSSGDataView<QSSGRenderBackendBufferObject> buffers,
1327 const QSSGRenderBackendBufferObject indexBuffer,
1328 QSSGDataView<quint32> strides,
1329 QSSGDataView<quint32> offsets,
1330 quint32 patchVertexCount)
1331 {
1332 QSSGRenderBackendAttributeLayoutGL *attribLayoutGL = reinterpret_cast<QSSGRenderBackendAttributeLayoutGL *>(attribLayout);
1333
1334 QSSGRenderBackendInputAssemblerGL *retval = new QSSGRenderBackendInputAssemblerGL(attribLayoutGL,
1335 buffers,
1336 indexBuffer,
1337 strides,
1338 offsets,
1339 patchVertexCount);
1340
1341 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendInputAssemblerObject>(retval);
1342 }
1343
releaseInputAssembler(QSSGRenderBackendInputAssemblerObject iao)1344 void QSSGRenderBackendGLBase::releaseInputAssembler(QSSGRenderBackendInputAssemblerObject iao)
1345 {
1346 QSSGRenderBackendInputAssemblerGL *inputAssembler = reinterpret_cast<QSSGRenderBackendInputAssemblerGL *>(iao);
1347 delete inputAssembler;
1348 }
1349
resetStates()1350 void QSSGRenderBackendGLBase::resetStates()
1351 {
1352 m_usedAttribCount = m_maxAttribCount;
1353 m_activatedTextureUnit = ACTIVATED_TEXTURE_UNIT_UNKNOWN;
1354 }
1355
compileSource(GLuint shaderID,QSSGByteView source,QByteArray & errorMessage,bool binary)1356 bool QSSGRenderBackendGLBase::compileSource(GLuint shaderID, QSSGByteView source, QByteArray &errorMessage, bool binary)
1357 {
1358 GLint shaderSourceSize = static_cast<GLint>(source.size());
1359 const char *shaderSourceData = reinterpret_cast<const char *>(source.begin());
1360 GLint shaderStatus = GL_TRUE;
1361
1362 if (!binary) {
1363
1364 GL_CALL_FUNCTION(glShaderSource(shaderID, 1, &shaderSourceData, &shaderSourceSize));
1365 GL_CALL_FUNCTION(glCompileShader(shaderID));
1366
1367 GLint logLen;
1368 GL_CALL_FUNCTION(glGetShaderiv(shaderID, GL_COMPILE_STATUS, &shaderStatus));
1369 GL_CALL_FUNCTION(glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLen));
1370
1371 // Check if some log exists. We also write warnings here
1372 // Should at least contain more than the null termination
1373 if (logLen > 2) {
1374 errorMessage.resize(logLen + 1);
1375
1376 GLint lenWithoutNull;
1377 GL_CALL_FUNCTION(glGetShaderInfoLog(shaderID, logLen, &lenWithoutNull, errorMessage.data()));
1378 }
1379 } else {
1380 GL_CALL_FUNCTION(glShaderBinary(1, &shaderID, GL_NVIDIA_PLATFORM_BINARY_NV, shaderSourceData, shaderSourceSize));
1381 GLenum binaryError = m_glFunctions->glGetError();
1382 if (binaryError != GL_NO_ERROR) {
1383 errorMessage = QByteArrayLiteral("Binary shader compilation failed");
1384 shaderStatus = GL_FALSE;
1385 qCCritical(RENDER_GL_ERROR, "%s", GLConversion::processGLError(binaryError));
1386 }
1387 }
1388
1389 return (shaderStatus == GL_TRUE);
1390 }
1391
createVertexShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1392 QSSGRenderBackend::QSSGRenderBackendVertexShaderObject QSSGRenderBackendGLBase::createVertexShader(QSSGByteView source,
1393 QByteArray &errorMessage,
1394 bool binary)
1395 {
1396 GLuint shaderID = GL_CALL_FUNCTION(glCreateShader(GL_VERTEX_SHADER));
1397
1398 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
1399 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1400 shaderID = 0;
1401 }
1402
1403 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendVertexShaderObject>(quintptr(shaderID));
1404 }
1405
createFragmentShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1406 QSSGRenderBackend::QSSGRenderBackendFragmentShaderObject QSSGRenderBackendGLBase::createFragmentShader(QSSGByteView source,
1407 QByteArray &errorMessage,
1408 bool binary)
1409 {
1410 GLuint shaderID = GL_CALL_FUNCTION(glCreateShader(GL_FRAGMENT_SHADER));
1411
1412 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
1413 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1414 shaderID = 0;
1415 }
1416
1417 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendFragmentShaderObject>(quintptr(shaderID));
1418 }
1419
createTessControlShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1420 QSSGRenderBackend::QSSGRenderBackendTessControlShaderObject QSSGRenderBackendGLBase::createTessControlShader(
1421 QSSGByteView source,
1422 QByteArray &errorMessage,
1423 bool binary)
1424 {
1425 // needs GL 4 or GLES EXT_tessellation_shader support
1426 Q_UNUSED(source)
1427 Q_UNUSED(errorMessage)
1428 Q_UNUSED(binary)
1429
1430 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1431
1432 return nullptr;
1433 }
1434
createTessEvaluationShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1435 QSSGRenderBackend::QSSGRenderBackendTessEvaluationShaderObject QSSGRenderBackendGLBase::createTessEvaluationShader(
1436 QSSGByteView source,
1437 QByteArray &errorMessage,
1438 bool binary)
1439 {
1440 // needs GL 4 or GLES EXT_tessellation_shader support
1441 Q_UNUSED(source)
1442 Q_UNUSED(errorMessage)
1443 Q_UNUSED(binary)
1444
1445 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1446
1447 return nullptr;
1448 }
1449
createGeometryShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1450 QSSGRenderBackend::QSSGRenderBackendGeometryShaderObject QSSGRenderBackendGLBase::createGeometryShader(QSSGByteView source,
1451 QByteArray &errorMessage,
1452 bool binary)
1453 {
1454 // needs GL 4 or GLES EXT_geometry_shader support
1455 Q_UNUSED(source)
1456 Q_UNUSED(errorMessage)
1457 Q_UNUSED(binary)
1458
1459 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1460
1461 return nullptr;
1462 }
1463
createComputeShader(QSSGByteView source,QByteArray & errorMessage,bool binary)1464 QSSGRenderBackend::QSSGRenderBackendComputeShaderObject QSSGRenderBackendGLBase::createComputeShader(QSSGByteView source,
1465 QByteArray &errorMessage,
1466 bool binary)
1467 {
1468 // needs GL 4.3 or GLES3.1 support
1469 Q_UNUSED(source)
1470 Q_UNUSED(errorMessage)
1471 Q_UNUSED(binary)
1472
1473 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1474
1475 return nullptr;
1476 }
1477
releaseVertexShader(QSSGRenderBackendVertexShaderObject vso)1478 void QSSGRenderBackendGLBase::releaseVertexShader(QSSGRenderBackendVertexShaderObject vso)
1479 {
1480 GLuint shaderID = HandleToID_cast(GLuint, quintptr, vso);
1481
1482 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1483 }
1484
releaseFragmentShader(QSSGRenderBackendFragmentShaderObject fso)1485 void QSSGRenderBackendGLBase::releaseFragmentShader(QSSGRenderBackendFragmentShaderObject fso)
1486 {
1487 GLuint shaderID = HandleToID_cast(GLuint, quintptr, fso);
1488
1489 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1490 }
1491
releaseTessControlShader(QSSGRenderBackendTessControlShaderObject tcso)1492 void QSSGRenderBackendGLBase::releaseTessControlShader(QSSGRenderBackendTessControlShaderObject tcso)
1493 {
1494 GLuint shaderID = HandleToID_cast(GLuint, quintptr, tcso);
1495
1496 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1497 }
1498
releaseTessEvaluationShader(QSSGRenderBackendTessEvaluationShaderObject teso)1499 void QSSGRenderBackendGLBase::releaseTessEvaluationShader(QSSGRenderBackendTessEvaluationShaderObject teso)
1500 {
1501 GLuint shaderID = HandleToID_cast(GLuint, quintptr, teso);
1502
1503 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1504 }
1505
releaseGeometryShader(QSSGRenderBackendGeometryShaderObject gso)1506 void QSSGRenderBackendGLBase::releaseGeometryShader(QSSGRenderBackendGeometryShaderObject gso)
1507 {
1508 GLuint shaderID = HandleToID_cast(GLuint, quintptr, gso);
1509
1510 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1511 }
1512
releaseComputeShader(QSSGRenderBackendComputeShaderObject cso)1513 void QSSGRenderBackendGLBase::releaseComputeShader(QSSGRenderBackendComputeShaderObject cso)
1514 {
1515 GLuint shaderID = HandleToID_cast(GLuint, quintptr, cso);
1516
1517 GL_CALL_FUNCTION(glDeleteShader(shaderID));
1518 }
1519
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendVertexShaderObject vso)1520 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendVertexShaderObject vso)
1521 {
1522 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1523 GLuint shaderID = HandleToID_cast(GLuint, quintptr, vso);
1524
1525 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1526 }
1527
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendFragmentShaderObject fso)1528 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendFragmentShaderObject fso)
1529 {
1530 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1531 GLuint shaderID = HandleToID_cast(GLuint, quintptr, fso);
1532
1533 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1534 }
1535
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendTessControlShaderObject tcso)1536 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendTessControlShaderObject tcso)
1537 {
1538 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1539 GLuint shaderID = HandleToID_cast(GLuint, quintptr, tcso);
1540
1541 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1542 }
1543
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendTessEvaluationShaderObject teso)1544 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendTessEvaluationShaderObject teso)
1545 {
1546 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1547 GLuint shaderID = HandleToID_cast(GLuint, quintptr, teso);
1548
1549 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1550 }
1551
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendGeometryShaderObject gso)1552 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendGeometryShaderObject gso)
1553 {
1554 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1555 GLuint shaderID = HandleToID_cast(GLuint, quintptr, gso);
1556
1557 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1558 }
1559
attachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendComputeShaderObject cso)1560 void QSSGRenderBackendGLBase::attachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendComputeShaderObject cso)
1561 {
1562 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1563 GLuint shaderID = HandleToID_cast(GLuint, quintptr, cso);
1564
1565 GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1566 }
1567
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendVertexShaderObject vso)1568 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendVertexShaderObject vso)
1569 {
1570 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1571 GLuint shaderID = HandleToID_cast(GLuint, quintptr, vso);
1572
1573 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1574 }
1575
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendFragmentShaderObject fso)1576 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendFragmentShaderObject fso)
1577 {
1578 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1579 GLuint shaderID = HandleToID_cast(GLuint, quintptr, fso);
1580
1581 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1582 }
1583
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendTessControlShaderObject tcso)1584 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendTessControlShaderObject tcso)
1585 {
1586 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1587 GLuint shaderID = HandleToID_cast(GLuint, quintptr, tcso);
1588
1589 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1590 }
1591
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendTessEvaluationShaderObject teso)1592 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendTessEvaluationShaderObject teso)
1593 {
1594 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1595 GLuint shaderID = HandleToID_cast(GLuint, quintptr, teso);
1596
1597 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1598 }
1599
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendGeometryShaderObject gso)1600 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendGeometryShaderObject gso)
1601 {
1602 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1603 GLuint shaderID = HandleToID_cast(GLuint, quintptr, gso);
1604
1605 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1606 }
1607
detachShader(QSSGRenderBackendShaderProgramObject po,QSSGRenderBackendComputeShaderObject cso)1608 void QSSGRenderBackendGLBase::detachShader(QSSGRenderBackendShaderProgramObject po, QSSGRenderBackendComputeShaderObject cso)
1609 {
1610 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1611 GLuint shaderID = HandleToID_cast(GLuint, quintptr, cso);
1612
1613 GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_programID), shaderID));
1614 }
1615
createShaderProgram(bool isSeparable)1616 QSSGRenderBackend::QSSGRenderBackendShaderProgramObject QSSGRenderBackendGLBase::createShaderProgram(bool isSeparable)
1617 {
1618 QSSGRenderBackendShaderProgramGL *theProgram = nullptr;
1619 GLuint programID = GL_CALL_FUNCTION(glCreateProgram());
1620
1621 if (programID) {
1622 theProgram = new QSSGRenderBackendShaderProgramGL(programID);
1623
1624 if (!theProgram) {
1625 GL_CALL_FUNCTION(glDeleteProgram(programID));
1626 } else if (isSeparable && m_backendSupport.caps.bits.bProgramPipelineSupported) {
1627 GL_CALL_EXTRA_FUNCTION(glProgramParameteri(programID, GL_PROGRAM_SEPARABLE, GL_TRUE));
1628 }
1629 }
1630
1631 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendShaderProgramObject>(theProgram);
1632 }
1633
releaseShaderProgram(QSSGRenderBackendShaderProgramObject po)1634 void QSSGRenderBackendGLBase::releaseShaderProgram(QSSGRenderBackendShaderProgramObject po)
1635 {
1636 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1637 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1638
1639 GL_CALL_FUNCTION(glDeleteProgram(programID));
1640
1641 delete pProgram;
1642 }
1643
getAttributes(QSSGRenderBackendShaderProgramGL * pProgram)1644 void QSSGRenderBackendGLBase::getAttributes(QSSGRenderBackendShaderProgramGL *pProgram)
1645 {
1646 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1647 // release old stuff
1648 if (pProgram->m_shaderInput) {
1649 delete pProgram->m_shaderInput;
1650 pProgram->m_shaderInput = nullptr;
1651 }
1652
1653 GLint numAttribs;
1654 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_ATTRIBUTES, &numAttribs));
1655
1656 if (numAttribs) {
1657 QSSGRenderBackendShaderInputEntryGL *tempShaderInputEntry = static_cast<QSSGRenderBackendShaderInputEntryGL *>(
1658 ::malloc(sizeof(QSSGRenderBackendShaderInputEntryGL) * size_t(m_maxAttribCount)));
1659
1660 GLint maxLength;
1661 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength));
1662 qint8 *nameBuf = static_cast<qint8 *>(::malloc(size_t(maxLength)));
1663
1664 // fill in data
1665 qint32 count = 0;
1666 for (int idx = 0; idx != numAttribs; ++idx) {
1667 GLint size = 0;
1668 GLenum glType;
1669 QSSGRenderComponentType compType = QSSGRenderComponentType::Unknown;
1670 quint32 numComps = 0;
1671
1672 GL_CALL_FUNCTION(glGetActiveAttrib(programID, idx, maxLength, nullptr, &size, &glType, (char *)nameBuf));
1673 // Skip anything named with gl_
1674 if (memcmp(nameBuf, "gl_", 3) == 0)
1675 continue;
1676
1677 GLConversion::fromAttribGLToComponentTypeAndNumComps(glType, compType, numComps);
1678
1679 new (&tempShaderInputEntry[count]) QSSGRenderBackendShaderInputEntryGL();
1680 tempShaderInputEntry[count].m_attribName = QByteArray(reinterpret_cast<const char *>(nameBuf));
1681 tempShaderInputEntry[count].m_attribLocation = GL_CALL_FUNCTION(glGetAttribLocation(programID, (char *)nameBuf));
1682 tempShaderInputEntry[count].m_type = glType;
1683 tempShaderInputEntry[count].m_numComponents = numComps;
1684
1685 ++count;
1686 }
1687
1688 // Now allocate space for the actuall entries
1689 quint32 shaderInputSize = sizeof(QSSGRenderBackendShaderInputGL);
1690 quint32 entrySize = sizeof(QSSGRenderBackendShaderInputEntryGL) * count;
1691 quint8 *newMem = static_cast<quint8 *>(::malloc(shaderInputSize + entrySize));
1692 QSSGDataRef<QSSGRenderBackendShaderInputEntryGL> entryRef = PtrAtOffset<QSSGRenderBackendShaderInputEntryGL>(newMem, shaderInputSize, entrySize);
1693 // fill data
1694 for (int idx = 0; idx != count; ++idx) {
1695 new (&entryRef[idx]) QSSGRenderBackendShaderInputEntryGL();
1696 entryRef[idx].m_attribName = tempShaderInputEntry[idx].m_attribName;
1697 entryRef[idx].m_attribLocation = tempShaderInputEntry[idx].m_attribLocation;
1698 entryRef[idx].m_type = tempShaderInputEntry[idx].m_type;
1699 entryRef[idx].m_numComponents = tempShaderInputEntry[idx].m_numComponents;
1700 // Re-set the entry to release the QByteArray, we can do the plane free later
1701 tempShaderInputEntry[idx] = QSSGRenderBackendShaderInputEntryGL();
1702 }
1703
1704 // placement new
1705 QSSGRenderBackendShaderInputGL *shaderInput = new (newMem) QSSGRenderBackendShaderInputGL(entryRef);
1706 // set the pointer
1707 pProgram->m_shaderInput = shaderInput;
1708
1709 ::free(nameBuf);
1710 ::free(tempShaderInputEntry);
1711 }
1712 }
1713
linkProgram(QSSGRenderBackendShaderProgramObject po,QByteArray & errorMessage)1714 bool QSSGRenderBackendGLBase::linkProgram(QSSGRenderBackendShaderProgramObject po, QByteArray &errorMessage)
1715 {
1716 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1717 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1718
1719 GL_CALL_FUNCTION(glLinkProgram(programID));
1720
1721 GLint linkStatus, logLen;
1722 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus));
1723 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLen));
1724
1725 // if successfully linked get the attribute information
1726 if (linkStatus)
1727 getAttributes(pProgram);
1728
1729 // Check if some log exists. We also write warnings here
1730 // Should at least contain more than the null termination
1731 if (logLen > 2) {
1732 errorMessage.resize(logLen + 1);
1733
1734 GLint lenWithoutNull;
1735 GL_CALL_FUNCTION(glGetProgramInfoLog(programID, logLen, &lenWithoutNull, errorMessage.data()));
1736 }
1737
1738 return (linkStatus == GL_TRUE);
1739 }
1740
linkProgram(QSSGRenderBackendShaderProgramObject po,QByteArray & errorMessage,quint32 format,const QByteArray & binary)1741 bool QSSGRenderBackendGLBase::linkProgram(QSSGRenderBackendShaderProgramObject po,
1742 QByteArray &errorMessage,
1743 quint32 format, const QByteArray &binary)
1744 {
1745 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1746 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1747
1748 GL_CALL_EXTRA_FUNCTION(glProgramBinary(programID, GLenum(format), binary.constData(), binary.size()));
1749
1750 GLint linkStatus, logLen;
1751 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus));
1752 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLen));
1753
1754 // if successfully linked get the attribute information
1755 if (linkStatus)
1756 getAttributes(pProgram);
1757
1758 // Check if some log exists. We also write warnings here
1759 // Should at least contain more than the null termination
1760 if (logLen > 2) {
1761 errorMessage.resize(logLen + 1);
1762
1763 GLint lenWithoutNull;
1764 GL_CALL_FUNCTION(glGetProgramInfoLog(programID, logLen, &lenWithoutNull, errorMessage.data()));
1765 }
1766
1767 return (linkStatus == GL_TRUE);
1768 }
1769
getProgramBinary(QSSGRenderBackendShaderProgramObject po,quint32 & format,QByteArray & binary)1770 void QSSGRenderBackendGLBase::getProgramBinary(QSSGRenderBackendShaderProgramObject po, quint32 &format, QByteArray &binary)
1771 {
1772 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1773 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1774 GLint binLen, linkStatus;
1775
1776 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus));
1777 Q_ASSERT(linkStatus == GL_TRUE);
1778
1779 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &binLen));
1780
1781 binary.resize(binLen);
1782 GLenum fmt;
1783 GL_CALL_EXTRA_FUNCTION(glGetProgramBinary(programID, binLen, nullptr, &fmt,
1784 binary.data()));
1785 format = fmt;
1786 }
1787
setActiveProgram(QSSGRenderBackendShaderProgramObject po)1788 void QSSGRenderBackendGLBase::setActiveProgram(QSSGRenderBackendShaderProgramObject po)
1789 {
1790 GLuint programID = 0;
1791
1792 if (po) {
1793 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1794 programID = static_cast<GLuint>(pProgram->m_programID);
1795 }
1796
1797 GL_CALL_FUNCTION(glUseProgram(programID));
1798 }
1799
createProgramPipeline()1800 QSSGRenderBackend::QSSGRenderBackendProgramPipeline QSSGRenderBackendGLBase::createProgramPipeline()
1801 {
1802 // needs GL 4 context
1803 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1804 return QSSGRenderBackend::QSSGRenderBackendProgramPipeline(nullptr);
1805 }
1806
releaseProgramPipeline(QSSGRenderBackendProgramPipeline)1807 void QSSGRenderBackendGLBase::releaseProgramPipeline(QSSGRenderBackendProgramPipeline)
1808 {
1809 // needs GL 4 context
1810 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1811 }
1812
setActiveProgramPipeline(QSSGRenderBackendProgramPipeline)1813 void QSSGRenderBackendGLBase::setActiveProgramPipeline(QSSGRenderBackendProgramPipeline)
1814 {
1815 // needs GL 4 context
1816 // TODO: should be fixed?
1817 // Q_ASSERT(false);
1818 }
1819
setProgramStages(QSSGRenderBackendProgramPipeline,QSSGRenderShaderTypeFlags,QSSGRenderBackendShaderProgramObject)1820 void QSSGRenderBackendGLBase::setProgramStages(QSSGRenderBackendProgramPipeline, QSSGRenderShaderTypeFlags, QSSGRenderBackendShaderProgramObject)
1821 {
1822 // needs GL 4 context
1823 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1824 }
1825
dispatchCompute(QSSGRenderBackendShaderProgramObject,quint32,quint32,quint32)1826 void QSSGRenderBackendGLBase::dispatchCompute(QSSGRenderBackendShaderProgramObject, quint32, quint32, quint32)
1827 {
1828 // needs GL 4 context
1829 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1830 }
1831
getConstantCount(QSSGRenderBackendShaderProgramObject po)1832 qint32 QSSGRenderBackendGLBase::getConstantCount(QSSGRenderBackendShaderProgramObject po)
1833 {
1834 Q_ASSERT(po);
1835 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1836 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1837
1838 GLint numUniforms;
1839 GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_UNIFORMS, &numUniforms));
1840
1841 return numUniforms;
1842 }
1843
getConstantBufferCount(QSSGRenderBackendShaderProgramObject po)1844 qint32 QSSGRenderBackendGLBase::getConstantBufferCount(QSSGRenderBackendShaderProgramObject po)
1845 {
1846 // needs GL3 and above
1847 Q_UNUSED(po)
1848
1849 return 0;
1850 }
1851
getConstantInfoByID(QSSGRenderBackendShaderProgramObject po,quint32 id,quint32 bufSize,qint32 * numElem,QSSGRenderShaderDataType * type,qint32 * binding,char * nameBuf)1852 qint32 QSSGRenderBackendGLBase::getConstantInfoByID(QSSGRenderBackendShaderProgramObject po,
1853 quint32 id,
1854 quint32 bufSize,
1855 qint32 *numElem,
1856 QSSGRenderShaderDataType *type,
1857 qint32 *binding,
1858 char *nameBuf)
1859 {
1860 Q_ASSERT(po);
1861 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
1862 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
1863
1864 GLenum glType;
1865 GL_CALL_FUNCTION(glGetActiveUniform(programID, id, GLsizei(bufSize), nullptr, numElem, &glType, nameBuf));
1866 *type = GLConversion::fromShaderGLToPropertyDataTypes(glType);
1867
1868 qint32 uniformLoc = GL_CALL_FUNCTION(glGetUniformLocation(programID, nameBuf));
1869
1870 // get unit binding point
1871 *binding = -1;
1872 if (uniformLoc != -1 && (glType == GL_IMAGE_2D || glType == GL_UNSIGNED_INT_IMAGE_2D || glType == GL_UNSIGNED_INT_ATOMIC_COUNTER)) {
1873 GL_CALL_FUNCTION(glGetUniformiv(programID, uniformLoc, binding));
1874 }
1875
1876 return uniformLoc;
1877 }
1878
getConstantBufferInfoByID(QSSGRenderBackendShaderProgramObject po,quint32 id,quint32 nameBufSize,qint32 * paramCount,qint32 * bufferSize,qint32 * length,char * nameBuf)1879 qint32 QSSGRenderBackendGLBase::getConstantBufferInfoByID(QSSGRenderBackendShaderProgramObject po,
1880 quint32 id,
1881 quint32 nameBufSize,
1882 qint32 *paramCount,
1883 qint32 *bufferSize,
1884 qint32 *length,
1885 char *nameBuf)
1886 {
1887 // needs GL3 and above
1888 Q_UNUSED(po)
1889 Q_UNUSED(id)
1890 Q_UNUSED(nameBufSize)
1891 Q_UNUSED(paramCount)
1892 Q_UNUSED(bufferSize)
1893 Q_UNUSED(length)
1894 Q_UNUSED(nameBuf)
1895
1896 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1897
1898 return -1;
1899 }
1900
getConstantBufferParamIndices(QSSGRenderBackendShaderProgramObject po,quint32 id,qint32 * indices)1901 void QSSGRenderBackendGLBase::getConstantBufferParamIndices(QSSGRenderBackendShaderProgramObject po, quint32 id, qint32 *indices)
1902 {
1903 // needs GL3 and above
1904 Q_UNUSED(po)
1905 Q_UNUSED(id)
1906 Q_UNUSED(indices)
1907
1908 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1909 }
1910
getConstantBufferParamInfoByIndices(QSSGRenderBackendShaderProgramObject po,quint32 count,quint32 * indices,QSSGRenderShaderDataType * type,qint32 * size,qint32 * offset)1911 void QSSGRenderBackendGLBase::getConstantBufferParamInfoByIndices(QSSGRenderBackendShaderProgramObject po,
1912 quint32 count,
1913 quint32 *indices,
1914 QSSGRenderShaderDataType *type,
1915 qint32 *size,
1916 qint32 *offset)
1917 {
1918 // needs GL3 and above
1919 Q_UNUSED(po)
1920 Q_UNUSED(count)
1921 Q_UNUSED(indices)
1922 Q_UNUSED(type)
1923 Q_UNUSED(size)
1924 Q_UNUSED(offset)
1925
1926 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1927 }
1928
programSetConstantBlock(QSSGRenderBackendShaderProgramObject po,quint32 blockIndex,quint32 binding)1929 void QSSGRenderBackendGLBase::programSetConstantBlock(QSSGRenderBackendShaderProgramObject po, quint32 blockIndex, quint32 binding)
1930 {
1931 // needs GL3 and above
1932 Q_UNUSED(po)
1933 Q_UNUSED(blockIndex)
1934 Q_UNUSED(binding)
1935
1936 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1937 }
1938
programSetConstantBuffer(quint32 index,QSSGRenderBackendBufferObject bo)1939 void QSSGRenderBackendGLBase::programSetConstantBuffer(quint32 index, QSSGRenderBackendBufferObject bo)
1940 {
1941 // needs GL3 and above
1942 Q_UNUSED(index)
1943 Q_UNUSED(bo)
1944
1945 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1946 }
1947
getStorageBufferCount(QSSGRenderBackendShaderProgramObject po)1948 qint32 QSSGRenderBackendGLBase::getStorageBufferCount(QSSGRenderBackendShaderProgramObject po)
1949 {
1950 // needs GL4 and above
1951 Q_UNUSED(po)
1952
1953 return 0;
1954 }
1955
getStorageBufferInfoByID(QSSGRenderBackendShaderProgramObject po,quint32 id,quint32 nameBufSize,qint32 * paramCount,qint32 * bufferSize,qint32 * length,char * nameBuf)1956 qint32 QSSGRenderBackendGLBase::getStorageBufferInfoByID(QSSGRenderBackendShaderProgramObject po,
1957 quint32 id,
1958 quint32 nameBufSize,
1959 qint32 *paramCount,
1960 qint32 *bufferSize,
1961 qint32 *length,
1962 char *nameBuf)
1963 {
1964 // needs GL4 and above
1965 Q_UNUSED(po)
1966 Q_UNUSED(id)
1967 Q_UNUSED(nameBufSize)
1968 Q_UNUSED(paramCount)
1969 Q_UNUSED(bufferSize)
1970 Q_UNUSED(length)
1971 Q_UNUSED(nameBuf)
1972
1973 qCCritical(RENDER_INVALID_OPERATION) << QObject::tr("Unsupported method: ") << __FUNCTION__;
1974
1975 return -1;
1976 }
1977
programSetStorageBuffer(quint32 index,QSSGRenderBackendBufferObject bo)1978 void QSSGRenderBackendGLBase::programSetStorageBuffer(quint32 index, QSSGRenderBackendBufferObject bo)
1979 {
1980 // needs GL4 and above
1981 Q_UNUSED(index)
1982 Q_UNUSED(bo)
1983 }
1984
setConstantValue(QSSGRenderBackendShaderProgramObject,quint32 id,QSSGRenderShaderDataType type,qint32 count,const void * value,bool transpose)1985 void QSSGRenderBackendGLBase::setConstantValue(QSSGRenderBackendShaderProgramObject,
1986 quint32 id,
1987 QSSGRenderShaderDataType type,
1988 qint32 count,
1989 const void *value,
1990 bool transpose)
1991 {
1992 GLenum glType = GLConversion::fromPropertyDataTypesToShaderGL(type);
1993
1994 switch (glType) {
1995 case GL_FLOAT:
1996 GL_CALL_FUNCTION(glUniform1fv(GLint(id), count, reinterpret_cast<const GLfloat *>(value)));
1997 break;
1998 case GL_FLOAT_VEC2:
1999 GL_CALL_FUNCTION(glUniform2fv(GLint(id), count, reinterpret_cast<const GLfloat *>(value)));
2000 break;
2001 case GL_FLOAT_VEC3:
2002 GL_CALL_FUNCTION(glUniform3fv(GLint(id), count, reinterpret_cast<const GLfloat *>(value)));
2003 break;
2004 case GL_FLOAT_VEC4:
2005 GL_CALL_FUNCTION(glUniform4fv(GLint(id), count, reinterpret_cast<const GLfloat *>(value)));
2006 break;
2007 case GL_INT:
2008 GL_CALL_FUNCTION(glUniform1iv(GLint(id), count, reinterpret_cast<const GLint *>(value)));
2009 break;
2010 case GL_BOOL: {
2011 const GLint boolValue = value ? *reinterpret_cast<const bool *>(value) : false;
2012 GL_CALL_FUNCTION(glUniform1iv(GLint(id), count, &boolValue));
2013 } break;
2014 case GL_INT_VEC2:
2015 case GL_BOOL_VEC2:
2016 GL_CALL_FUNCTION(glUniform2iv(GLint(id), count, reinterpret_cast<const GLint *>(value)));
2017 break;
2018 case GL_INT_VEC3:
2019 case GL_BOOL_VEC3:
2020 GL_CALL_FUNCTION(glUniform3iv(GLint(id), count, reinterpret_cast<const GLint *>(value)));
2021 break;
2022 case GL_INT_VEC4:
2023 case GL_BOOL_VEC4:
2024 GL_CALL_FUNCTION(glUniform4iv(GLint(id), count, reinterpret_cast<const GLint *>(value)));
2025 break;
2026 case GL_FLOAT_MAT3:
2027 GL_CALL_FUNCTION(glUniformMatrix3fv(GLint(id), count, transpose, reinterpret_cast<const GLfloat *>(value)));
2028 break;
2029 case GL_FLOAT_MAT4:
2030 GL_CALL_FUNCTION(glUniformMatrix4fv(GLint(id), count, transpose, reinterpret_cast<const GLfloat *>(value)));
2031 break;
2032 case GL_IMAGE_2D:
2033 case GL_SAMPLER_2D:
2034 case GL_SAMPLER_2D_SHADOW:
2035 case GL_SAMPLER_CUBE: {
2036 if (count > 1) {
2037 const GLint *sampler = reinterpret_cast<const GLint *>(value);
2038 GL_CALL_FUNCTION(glUniform1iv(GLint(id), count, sampler));
2039 } else {
2040 const GLint sampler = *reinterpret_cast<const GLint *>(value);
2041 GL_CALL_FUNCTION(glUniform1i(GLint(id), sampler));
2042 }
2043 } break;
2044 default:
2045 qCCritical(RENDER_INTERNAL_ERROR, "Unknown shader type format %d", int(type));
2046 Q_ASSERT(false);
2047 break;
2048 }
2049 }
2050
draw(QSSGRenderDrawMode drawMode,quint32 start,quint32 count)2051 void QSSGRenderBackendGLBase::draw(QSSGRenderDrawMode drawMode, quint32 start, quint32 count)
2052 {
2053 GL_CALL_FUNCTION(glDrawArrays(m_conversion.fromDrawModeToGL(drawMode, m_backendSupport.caps.bits.bTessellationSupported), GLint(start), GLsizei(count)));
2054 }
2055
drawIndexed(QSSGRenderDrawMode drawMode,quint32 count,QSSGRenderComponentType type,const void * indices)2056 void QSSGRenderBackendGLBase::drawIndexed(QSSGRenderDrawMode drawMode,
2057 quint32 count,
2058 QSSGRenderComponentType type,
2059 const void *indices)
2060 {
2061 GL_CALL_FUNCTION(glDrawElements(m_conversion.fromDrawModeToGL(drawMode, m_backendSupport.caps.bits.bTessellationSupported),
2062 GLint(count),
2063 m_conversion.fromIndexBufferComponentsTypesToGL(type),
2064 indices));
2065 }
2066
readPixel(QSSGRenderBackendRenderTargetObject,qint32 x,qint32 y,qint32 width,qint32 height,QSSGRenderReadPixelFormat inFormat,QSSGByteRef pixels)2067 void QSSGRenderBackendGLBase::readPixel(QSSGRenderBackendRenderTargetObject /* rto */,
2068 qint32 x,
2069 qint32 y,
2070 qint32 width,
2071 qint32 height,
2072 QSSGRenderReadPixelFormat inFormat,
2073 QSSGByteRef pixels)
2074 {
2075 GLuint glFormat;
2076 GLuint glType;
2077 if (GLConversion::fromReadPixelsToGlFormatAndType(inFormat, &glFormat, &glType)) {
2078 GL_CALL_FUNCTION(glReadPixels(x, y, width, height, glFormat, glType, pixels));
2079 }
2080 }
2081
2082 ///< private calls
getShadingLanguageVersionString()2083 const char *QSSGRenderBackendGLBase::getShadingLanguageVersionString()
2084 {
2085 const GLubyte *retval = GL_CALL_FUNCTION(glGetString(GL_SHADING_LANGUAGE_VERSION));
2086 if (retval == nullptr)
2087 return "";
2088
2089 return reinterpret_cast<const char *>(retval);
2090 }
2091
getVersionString()2092 const char *QSSGRenderBackendGLBase::getVersionString()
2093 {
2094 const GLubyte *retval = GL_CALL_FUNCTION(glGetString(GL_VERSION));
2095 if (retval == nullptr)
2096 return "";
2097
2098 return reinterpret_cast<const char *>(retval);
2099 }
2100
getVendorString()2101 const char *QSSGRenderBackendGLBase::getVendorString()
2102 {
2103 const GLubyte *retval = GL_CALL_FUNCTION(glGetString(GL_VENDOR));
2104 if (retval == nullptr)
2105 return "";
2106
2107 return reinterpret_cast<const char *>(retval);
2108 }
2109
getRendererString()2110 const char *QSSGRenderBackendGLBase::getRendererString()
2111 {
2112 const GLubyte *retval = GL_CALL_FUNCTION(glGetString(GL_RENDERER));
2113 if (retval == nullptr)
2114 return "";
2115
2116 return reinterpret_cast<const char *>(retval);
2117 }
2118
getExtensionString()2119 const char *QSSGRenderBackendGLBase::getExtensionString()
2120 {
2121 const GLubyte *retval = GL_CALL_FUNCTION(glGetString(GL_EXTENSIONS));
2122 if (retval == nullptr)
2123 return "";
2124
2125 return reinterpret_cast<const char *>(retval);
2126 }
2127
2128 /**
2129 * @brief This function inspects the various strings to setup
2130 * HW capabilities of the device.
2131 * We can do a lot of smart things here based on GL version
2132 * renderer string and vendor.
2133 *
2134 * @return No return
2135 */
setAndInspectHardwareCaps()2136 void QSSGRenderBackendGLBase::setAndInspectHardwareCaps()
2137 {
2138 QByteArray apiVersion(getVersionString());
2139 qCInfo(RENDER_TRACE_INFO, "GL version: %s", apiVersion.constData());
2140
2141 // we assume all GLES versions running on mobile with shared memory
2142 // this means framebuffer blits are slow and should be optimized or avoided
2143 if (!apiVersion.contains("OpenGL ES")) {
2144 // no ES device
2145 m_backendSupport.caps.bits.bFastBlitsSupported = true;
2146 }
2147 }
2148
2149 QT_END_NAMESPACE
2150