1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qopenglshaderprogram.h" |
5 | #include "qopenglextrafunctions.h" |
6 | #include "private/qopenglcontext_p.h" |
7 | #include <QtOpenGL/QOpenGLVersionFunctionsFactory> |
8 | #include <QtCore/private/qobject_p.h> |
9 | #include <QtCore/qdebug.h> |
10 | #include <QtCore/qfile.h> |
11 | #include <QtCore/qlist.h> |
12 | #include <QtCore/qloggingcategory.h> |
13 | #include <QtCore/qvarlengtharray.h> |
14 | #include <QtGui/private/qopenglprogrambinarycache_p.h> |
15 | #include <QtGui/qtransform.h> |
16 | #include <QtGui/QColor> |
17 | #include <QtGui/QSurfaceFormat> |
18 | |
19 | #if !QT_CONFIG(opengles2) |
20 | #include <QtOpenGL/qopenglfunctions_4_0_core.h> |
21 | #endif |
22 | |
23 | #include <algorithm> |
24 | #include <memory> |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | using namespace Qt::StringLiterals; |
29 | |
30 | /*! |
31 | \class QOpenGLShaderProgram |
32 | \brief The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used. |
33 | \since 5.0 |
34 | \ingroup painting-3D |
35 | \inmodule QtOpenGL |
36 | |
37 | \section1 Introduction |
38 | |
39 | This class supports shader programs written in the OpenGL Shading |
40 | Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES). |
41 | |
42 | QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of |
43 | compiling and linking vertex and fragment shaders. |
44 | |
45 | The following example creates a vertex shader program using the |
46 | supplied source \c{code}. Once compiled and linked, the shader |
47 | program is activated in the current QOpenGLContext by calling |
48 | QOpenGLShaderProgram::bind(): |
49 | |
50 | \snippet code/src_gui_qopenglshaderprogram.cpp 0 |
51 | |
52 | \section1 Writing Portable Shaders |
53 | |
54 | Shader programs can be difficult to reuse across OpenGL implementations |
55 | because of varying levels of support for standard vertex attributes and |
56 | uniform variables. In particular, GLSL/ES lacks all of the |
57 | standard variables that are present on desktop OpenGL systems: |
58 | \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL |
59 | lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}. |
60 | |
61 | The QOpenGLShaderProgram class makes the process of writing portable shaders |
62 | easier by prefixing all shader programs with the following lines on |
63 | desktop OpenGL: |
64 | |
65 | \code |
66 | #define highp |
67 | #define mediump |
68 | #define lowp |
69 | \endcode |
70 | |
71 | This makes it possible to run most GLSL/ES shader programs |
72 | on desktop systems. The programmer should restrict themselves |
73 | to just features that are present in GLSL/ES, and avoid |
74 | standard variable names that only work on the desktop. |
75 | |
76 | \section1 Simple Shader Example |
77 | |
78 | \snippet code/src_gui_qopenglshaderprogram.cpp 1 |
79 | |
80 | With the above shader program active, we can draw a green triangle |
81 | as follows: |
82 | |
83 | \snippet code/src_gui_qopenglshaderprogram.cpp 2 |
84 | |
85 | \section1 Binary Shaders and Programs |
86 | |
87 | Binary shaders may be specified using \c{glShaderBinary()} on |
88 | the return value from QOpenGLShader::shaderId(). The QOpenGLShader instance |
89 | containing the binary can then be added to the shader program with |
90 | addShader() and linked in the usual fashion with link(). |
91 | |
92 | Binary programs may be specified using \c{glProgramBinaryOES()} |
93 | on the return value from programId(). Then the application should |
94 | call link(), which will notice that the program has already been |
95 | specified and linked, allowing other operations to be performed |
96 | on the shader program. The shader program's id can be explicitly |
97 | created using the create() function. |
98 | |
99 | \section2 Caching Program Binaries |
100 | |
101 | As of Qt 5.9, support for caching program binaries on disk is built in. To |
102 | enable this, switch to using addCacheableShaderFromSourceCode() and |
103 | addCacheableShaderFromSourceFile(). With an OpenGL ES 3.x context or support |
104 | for \c{GL_ARB_get_program_binary}, this will transparently cache program |
105 | binaries under QStandardPaths::GenericCacheLocation or |
106 | QStandardPaths::CacheLocation. When support is not available, calling the |
107 | cacheable function variants is equivalent to the normal ones. |
108 | |
109 | \note Some drivers do not have any binary formats available, even though |
110 | they advertise the extension or offer OpenGL ES 3.0. In this case program |
111 | binary support will be disabled. |
112 | |
113 | \sa QOpenGLShader |
114 | */ |
115 | |
116 | /*! |
117 | \class QOpenGLShader |
118 | \brief The QOpenGLShader class allows OpenGL shaders to be compiled. |
119 | \since 5.0 |
120 | \ingroup painting-3D |
121 | \inmodule QtOpenGL |
122 | |
123 | This class supports shaders written in the OpenGL Shading Language (GLSL) |
124 | and in the OpenGL/ES Shading Language (GLSL/ES). |
125 | |
126 | QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of |
127 | compiling and linking vertex and fragment shaders. |
128 | |
129 | \sa QOpenGLShaderProgram |
130 | */ |
131 | |
132 | /*! |
133 | \enum QOpenGLShader::ShaderTypeBit |
134 | This enum specifies the type of QOpenGLShader that is being created. |
135 | |
136 | \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL). |
137 | \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL). |
138 | \value Geometry Geometry shaders written in the OpenGL Shading Language (GLSL) |
139 | (requires OpenGL >= 3.2 or OpenGL ES >= 3.2). |
140 | \value TessellationControl Tessellation control shaders written in the OpenGL |
141 | shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2). |
142 | \value TessellationEvaluation Tessellation evaluation shaders written in the OpenGL |
143 | shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2). |
144 | \value Compute Compute shaders written in the OpenGL shading language (GLSL) |
145 | (requires OpenGL >= 4.3 or OpenGL ES >= 3.1). |
146 | */ |
147 | |
148 | // For GLES 3.1/3.2 |
149 | #ifndef GL_GEOMETRY_SHADER |
150 | #define GL_GEOMETRY_SHADER 0x8DD9 |
151 | #endif |
152 | #ifndef GL_TESS_CONTROL_SHADER |
153 | #define GL_TESS_CONTROL_SHADER 0x8E88 |
154 | #endif |
155 | #ifndef GL_TESS_EVALUATION_SHADER |
156 | #define GL_TESS_EVALUATION_SHADER 0x8E87 |
157 | #endif |
158 | #ifndef GL_COMPUTE_SHADER |
159 | #define GL_COMPUTE_SHADER 0x91B9 |
160 | #endif |
161 | #ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES |
162 | #define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 |
163 | #endif |
164 | #ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS |
165 | #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 |
166 | #endif |
167 | #ifndef GL_PATCH_VERTICES |
168 | #define GL_PATCH_VERTICES 0x8E72 |
169 | #endif |
170 | #ifndef GL_PATCH_DEFAULT_OUTER_LEVEL |
171 | #define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 |
172 | #endif |
173 | #ifndef GL_PATCH_DEFAULT_INNER_LEVEL |
174 | #define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 |
175 | #endif |
176 | |
177 | #if !QT_CONFIG(opengles2) |
178 | static inline bool isFormatGLES(const QSurfaceFormat &f) |
179 | { |
180 | return (f.renderableType() == QSurfaceFormat::OpenGLES); |
181 | } |
182 | #endif |
183 | |
184 | static inline bool supportsGeometry(const QSurfaceFormat &f) |
185 | { |
186 | return f.version() >= qMakePair(value1: 3, value2: 2); |
187 | } |
188 | |
189 | static inline bool supportsCompute(const QSurfaceFormat &f) |
190 | { |
191 | #if !QT_CONFIG(opengles2) |
192 | if (!isFormatGLES(f)) |
193 | return f.version() >= qMakePair(value1: 4, value2: 3); |
194 | else |
195 | return f.version() >= qMakePair(value1: 3, value2: 1); |
196 | #else |
197 | return f.version() >= qMakePair(3, 1); |
198 | #endif |
199 | } |
200 | |
201 | static inline bool supportsTessellation(const QSurfaceFormat &f) |
202 | { |
203 | #if !QT_CONFIG(opengles2) |
204 | if (!isFormatGLES(f)) |
205 | return f.version() >= qMakePair(value1: 4, value2: 0); |
206 | else |
207 | return f.version() >= qMakePair(value1: 3, value2: 2); |
208 | #else |
209 | return f.version() >= qMakePair(3, 2); |
210 | #endif |
211 | } |
212 | |
213 | class QOpenGLShaderPrivate : public QObjectPrivate |
214 | { |
215 | Q_DECLARE_PUBLIC(QOpenGLShader) |
216 | public: |
217 | QOpenGLShaderPrivate(QOpenGLContext *ctx, QOpenGLShader::ShaderType type) |
218 | : shaderGuard(nullptr) |
219 | , shaderType(type) |
220 | , compiled(false) |
221 | , glfuncs(new QOpenGLExtraFunctions(ctx)) |
222 | , supportsGeometryShaders(false) |
223 | , supportsTessellationShaders(false) |
224 | , supportsComputeShaders(false) |
225 | { |
226 | if (shaderType & QOpenGLShader::Geometry) |
227 | supportsGeometryShaders = supportsGeometry(f: ctx->format()); |
228 | else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) |
229 | supportsTessellationShaders = supportsTessellation(f: ctx->format()); |
230 | else if (shaderType & QOpenGLShader::Compute) |
231 | supportsComputeShaders = supportsCompute(f: ctx->format()); |
232 | } |
233 | ~QOpenGLShaderPrivate(); |
234 | |
235 | QOpenGLSharedResourceGuard *shaderGuard; |
236 | QOpenGLShader::ShaderType shaderType; |
237 | bool compiled; |
238 | QString log; |
239 | |
240 | QOpenGLExtraFunctions *glfuncs; |
241 | |
242 | // Support for geometry shaders |
243 | bool supportsGeometryShaders; |
244 | // Support for tessellation shaders |
245 | bool supportsTessellationShaders; |
246 | // Support for compute shaders |
247 | bool supportsComputeShaders; |
248 | |
249 | |
250 | bool create(); |
251 | bool compile(QOpenGLShader *q); |
252 | void deleteShader(); |
253 | }; |
254 | |
255 | namespace { |
256 | void freeShaderFunc(QOpenGLFunctions *funcs, GLuint id) |
257 | { |
258 | funcs->glDeleteShader(shader: id); |
259 | } |
260 | } |
261 | |
262 | QOpenGLShaderPrivate::~QOpenGLShaderPrivate() |
263 | { |
264 | delete glfuncs; |
265 | if (shaderGuard) |
266 | shaderGuard->free(); |
267 | } |
268 | |
269 | bool QOpenGLShaderPrivate::create() |
270 | { |
271 | QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); |
272 | if (!context) |
273 | return false; |
274 | GLuint shader = 0; |
275 | if (shaderType == QOpenGLShader::Vertex) { |
276 | shader = glfuncs->glCreateShader(GL_VERTEX_SHADER); |
277 | } else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) { |
278 | shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER); |
279 | } else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) { |
280 | shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER); |
281 | } else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) { |
282 | shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER); |
283 | } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) { |
284 | shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER); |
285 | } else if (shaderType == QOpenGLShader::Fragment) { |
286 | shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER); |
287 | } |
288 | if (!shader) { |
289 | qWarning(msg: "QOpenGLShader: could not create shader" ); |
290 | return false; |
291 | } |
292 | shaderGuard = new QOpenGLSharedResourceGuard(context, shader, freeShaderFunc); |
293 | return true; |
294 | } |
295 | |
296 | bool QOpenGLShaderPrivate::compile(QOpenGLShader *q) |
297 | { |
298 | GLuint shader = shaderGuard ? shaderGuard->id() : 0; |
299 | if (!shader) |
300 | return false; |
301 | |
302 | // Try to compile shader |
303 | glfuncs->glCompileShader(shader); |
304 | GLint value = 0; |
305 | |
306 | // Get compilation status |
307 | glfuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, params: &value); |
308 | compiled = (value != 0); |
309 | |
310 | if (!compiled) { |
311 | // Compilation failed, try to provide some information about the failure |
312 | QString name = q->objectName(); |
313 | |
314 | const char *types[] = { |
315 | "Fragment" , |
316 | "Vertex" , |
317 | "Geometry" , |
318 | "Tessellation Control" , |
319 | "Tessellation Evaluation" , |
320 | "Compute" , |
321 | "" |
322 | }; |
323 | |
324 | const char *type = types[6]; |
325 | switch (shaderType) { |
326 | case QOpenGLShader::Fragment: |
327 | type = types[0]; break; |
328 | case QOpenGLShader::Vertex: |
329 | type = types[1]; break; |
330 | case QOpenGLShader::Geometry: |
331 | type = types[2]; break; |
332 | case QOpenGLShader::TessellationControl: |
333 | type = types[3]; break; |
334 | case QOpenGLShader::TessellationEvaluation: |
335 | type = types[4]; break; |
336 | case QOpenGLShader::Compute: |
337 | type = types[5]; break; |
338 | } |
339 | |
340 | // Get info and source code lengths |
341 | GLint infoLogLength = 0; |
342 | GLint sourceCodeLength = 0; |
343 | char *logBuffer = nullptr; |
344 | char *sourceCodeBuffer = nullptr; |
345 | |
346 | // Get the compilation info log |
347 | glfuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, params: &infoLogLength); |
348 | |
349 | if (infoLogLength > 1) { |
350 | GLint temp; |
351 | logBuffer = new char [infoLogLength]; |
352 | glfuncs->glGetShaderInfoLog(shader, bufsize: infoLogLength, length: &temp, infolog: logBuffer); |
353 | } |
354 | |
355 | // Get the source code |
356 | glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, params: &sourceCodeLength); |
357 | |
358 | if (sourceCodeLength > 1) { |
359 | GLint temp; |
360 | sourceCodeBuffer = new char [sourceCodeLength]; |
361 | glfuncs->glGetShaderSource(shader, bufsize: sourceCodeLength, length: &temp, source: sourceCodeBuffer); |
362 | } |
363 | |
364 | if (logBuffer) |
365 | log = QString::fromLatin1(ba: logBuffer); |
366 | else |
367 | log = u"failed"_s ; |
368 | |
369 | if (name.isEmpty()) |
370 | qWarning(msg: "QOpenGLShader::compile(%s): %s" , type, qPrintable(log)); |
371 | else |
372 | qWarning(msg: "QOpenGLShader::compile(%s)[%s]: %s" , type, qPrintable(name), qPrintable(log)); |
373 | |
374 | // Dump the source code if we got it |
375 | if (sourceCodeBuffer) { |
376 | qWarning(msg: "*** Problematic %s shader source code ***\n" |
377 | "%ls\n" |
378 | "***" , |
379 | type, qUtf16Printable(QString::fromLatin1(sourceCodeBuffer))); |
380 | } |
381 | |
382 | // Cleanup |
383 | delete [] logBuffer; |
384 | delete [] sourceCodeBuffer; |
385 | } |
386 | |
387 | return compiled; |
388 | } |
389 | |
390 | void QOpenGLShaderPrivate::deleteShader() |
391 | { |
392 | if (shaderGuard) { |
393 | shaderGuard->free(); |
394 | shaderGuard = nullptr; |
395 | } |
396 | } |
397 | |
398 | /*! |
399 | Constructs a new QOpenGLShader object of the specified \a type |
400 | and attaches it to \a parent. If shader programs are not supported, |
401 | QOpenGLShaderProgram::hasOpenGLShaderPrograms() will return false. |
402 | |
403 | This constructor is normally followed by a call to compileSourceCode() |
404 | or compileSourceFile(). |
405 | |
406 | The shader will be associated with the current QOpenGLContext. |
407 | |
408 | \sa compileSourceCode(), compileSourceFile() |
409 | */ |
410 | QOpenGLShader::QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent) |
411 | : QObject(*new QOpenGLShaderPrivate(QOpenGLContext::currentContext(), type), parent) |
412 | { |
413 | Q_D(QOpenGLShader); |
414 | d->create(); |
415 | } |
416 | |
417 | /*! |
418 | Deletes this shader. If the shader has been attached to a |
419 | QOpenGLShaderProgram object, then the actual shader will stay around |
420 | until the QOpenGLShaderProgram is destroyed. |
421 | */ |
422 | QOpenGLShader::~QOpenGLShader() |
423 | { |
424 | } |
425 | |
426 | /*! |
427 | Returns the type of this shader. |
428 | */ |
429 | QOpenGLShader::ShaderType QOpenGLShader::shaderType() const |
430 | { |
431 | Q_D(const QOpenGLShader); |
432 | return d->shaderType; |
433 | } |
434 | |
435 | static const char qualifierDefines[] = |
436 | "#define lowp\n" |
437 | "#define mediump\n" |
438 | "#define highp\n" ; |
439 | |
440 | #if QT_CONFIG(opengles2) && !defined(QT_OPENGL_FORCE_SHADER_DEFINES) |
441 | // The "highp" qualifier doesn't exist in fragment shaders |
442 | // on all ES platforms. When it doesn't exist, use "mediump". |
443 | #define QOpenGL_REDEFINE_HIGHP 1 |
444 | static const char redefineHighp[] = |
445 | "#ifndef GL_FRAGMENT_PRECISION_HIGH\n" |
446 | "#define highp mediump\n" |
447 | "#endif\n" ; |
448 | #endif |
449 | |
450 | // Boiler-plate header to have the layout attributes available we need later |
451 | static const char [] = |
452 | "#ifdef GL_KHR_blend_equation_advanced\n" |
453 | "#extension GL_ARB_fragment_coord_conventions : enable\n" |
454 | "#extension GL_KHR_blend_equation_advanced : enable\n" |
455 | "#endif\n" ; |
456 | |
457 | struct QVersionDirectivePosition |
458 | { |
459 | constexpr QVersionDirectivePosition(int position = 0, int line = -1) |
460 | : position(position) |
461 | , line(line) |
462 | { |
463 | } |
464 | |
465 | constexpr bool hasPosition() const |
466 | { |
467 | return position > 0; |
468 | } |
469 | |
470 | const int position; |
471 | const int line; |
472 | }; |
473 | |
474 | static QVersionDirectivePosition findVersionDirectivePosition(const char *source) |
475 | { |
476 | Q_ASSERT(source); |
477 | |
478 | // According to the GLSL spec the #version directive must not be |
479 | // preceded by anything but whitespace and comments. |
480 | // In order to not get confused by #version directives within a |
481 | // multiline comment, we need to do some minimal comment parsing |
482 | // while searching for the directive. |
483 | enum { |
484 | Normal, |
485 | StartOfLine, |
486 | PreprocessorDirective, |
487 | , |
488 | , |
489 | , |
490 | |
491 | } state = StartOfLine; |
492 | |
493 | const char *c = source; |
494 | while (*c) { |
495 | switch (state) { |
496 | case PreprocessorDirective: |
497 | if (*c == ' ' || *c == '\t') |
498 | break; |
499 | if (!strncmp(s1: c, s2: "version" , n: strlen(s: "version" ))) { |
500 | // Found version directive |
501 | c += strlen(s: "version" ); |
502 | while (*c && *c != '\n') |
503 | ++c; |
504 | int splitPosition = c - source + 1; |
505 | int linePosition = int(std::count(first: source, last: c, value: '\n')) + 1; |
506 | return QVersionDirectivePosition(splitPosition, linePosition); |
507 | } else if (*c == '/') |
508 | state = CommentStarting; |
509 | else if (*c == '\n') |
510 | state = StartOfLine; |
511 | else |
512 | state = Normal; |
513 | break; |
514 | case StartOfLine: |
515 | if (*c == ' ' || *c == '\t') |
516 | break; |
517 | else if (*c == '#') { |
518 | state = PreprocessorDirective; |
519 | break; |
520 | } |
521 | state = Normal; |
522 | Q_FALLTHROUGH(); |
523 | case Normal: |
524 | if (*c == '/') |
525 | state = CommentStarting; |
526 | else if (*c == '\n') |
527 | state = StartOfLine; |
528 | break; |
529 | case CommentStarting: |
530 | if (*c == '*') |
531 | state = MultiLineComment; |
532 | else if (*c == '/') |
533 | state = SingleLineComment; |
534 | else |
535 | state = Normal; |
536 | break; |
537 | case MultiLineComment: |
538 | if (*c == '*') |
539 | state = CommentEnding; |
540 | break; |
541 | case SingleLineComment: |
542 | if (*c == '\n') |
543 | state = Normal; |
544 | break; |
545 | case CommentEnding: |
546 | if (*c == '/') |
547 | state = Normal; |
548 | else if (*c != u'*') |
549 | state = MultiLineComment; |
550 | break; |
551 | } |
552 | ++c; |
553 | } |
554 | |
555 | return QVersionDirectivePosition(0, 1); |
556 | } |
557 | |
558 | /*! |
559 | Sets the \a source code for this shader and compiles it. |
560 | Returns \c true if the source was successfully compiled, false otherwise. |
561 | |
562 | \sa compileSourceFile() |
563 | */ |
564 | bool QOpenGLShader::compileSourceCode(const char *source) |
565 | { |
566 | Q_D(QOpenGLShader); |
567 | // This method breaks the shader code into two parts: |
568 | // 1. Up to and including an optional #version directive. |
569 | // 2. The rest. |
570 | // If a #version directive exists, qualifierDefines and redefineHighp |
571 | // are inserted after. Otherwise they are inserted right at the start. |
572 | // In both cases a #line directive is appended in order to compensate |
573 | // for line number changes in case of compiler errors. |
574 | |
575 | if (d->shaderGuard && d->shaderGuard->id() && source) { |
576 | const QVersionDirectivePosition versionDirectivePosition = findVersionDirectivePosition(source); |
577 | |
578 | QVarLengthArray<const char *, 5> sourceChunks; |
579 | QVarLengthArray<GLint, 5> sourceChunkLengths; |
580 | QOpenGLContext *ctx = QOpenGLContext::currentContext(); |
581 | |
582 | if (versionDirectivePosition.hasPosition()) { |
583 | // Append source up to and including the #version directive |
584 | sourceChunks.append(t: source); |
585 | sourceChunkLengths.append(t: GLint(versionDirectivePosition.position)); |
586 | } else { |
587 | // QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always |
588 | if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) { |
589 | const char *vendor = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VENDOR)); |
590 | if (vendor && !strcmp(s1: vendor, s2: "Intel" )) { |
591 | static const char version110[] = "#version 110\n" ; |
592 | sourceChunks.append(t: version110); |
593 | sourceChunkLengths.append(t: GLint(sizeof(version110)) - 1); |
594 | } |
595 | } |
596 | } |
597 | if (d->shaderType == Fragment) { |
598 | sourceChunks.append(t: blendEquationAdvancedHeader); |
599 | sourceChunkLengths.append(t: GLint(sizeof(blendEquationAdvancedHeader) - 1)); |
600 | } |
601 | |
602 | // The precision qualifiers are useful on OpenGL/ES systems, |
603 | // but usually not present on desktop systems. |
604 | const QSurfaceFormat currentSurfaceFormat = ctx->format(); |
605 | QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context: QOpenGLContext::currentContext()); |
606 | if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL |
607 | || ctx_d->workaround_missingPrecisionQualifiers |
608 | #ifdef QT_OPENGL_FORCE_SHADER_DEFINES |
609 | || true |
610 | #endif |
611 | ) { |
612 | sourceChunks.append(t: qualifierDefines); |
613 | sourceChunkLengths.append(t: GLint(sizeof(qualifierDefines) - 1)); |
614 | } |
615 | |
616 | #ifdef QOpenGL_REDEFINE_HIGHP |
617 | if (d->shaderType == Fragment && !ctx_d->workaround_missingPrecisionQualifiers |
618 | && QOpenGLContext::currentContext()->isOpenGLES()) { |
619 | sourceChunks.append(redefineHighp); |
620 | sourceChunkLengths.append(GLint(sizeof(redefineHighp) - 1)); |
621 | } |
622 | #endif |
623 | |
624 | QByteArray lineDirective; |
625 | // #line is rejected by some drivers: |
626 | // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel" |
627 | const char *version = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VERSION)); |
628 | if (!version || !strstr(haystack: version, needle: "2.1 Mesa 8" )) { |
629 | // Append #line directive in order to compensate for text insertion |
630 | lineDirective = QStringLiteral("#line %1\n" ).arg(a: versionDirectivePosition.line).toUtf8(); |
631 | sourceChunks.append(t: lineDirective.constData()); |
632 | sourceChunkLengths.append(t: GLint(lineDirective.size())); |
633 | } |
634 | |
635 | // Append rest of shader code |
636 | sourceChunks.append(t: source + versionDirectivePosition.position); |
637 | sourceChunkLengths.append(t: GLint(qstrlen(str: source + versionDirectivePosition.position))); |
638 | |
639 | d->glfuncs->glShaderSource(shader: d->shaderGuard->id(), count: sourceChunks.size(), string: sourceChunks.data(), length: sourceChunkLengths.data()); |
640 | return d->compile(q: this); |
641 | } else { |
642 | return false; |
643 | } |
644 | } |
645 | |
646 | /*! |
647 | \overload |
648 | |
649 | Sets the \a source code for this shader and compiles it. |
650 | Returns \c true if the source was successfully compiled, false otherwise. |
651 | |
652 | \sa compileSourceFile() |
653 | */ |
654 | bool QOpenGLShader::compileSourceCode(const QByteArray& source) |
655 | { |
656 | return compileSourceCode(source: source.constData()); |
657 | } |
658 | |
659 | /*! |
660 | \overload |
661 | |
662 | Sets the \a source code for this shader and compiles it. |
663 | Returns \c true if the source was successfully compiled, false otherwise. |
664 | |
665 | \sa compileSourceFile() |
666 | */ |
667 | bool QOpenGLShader::compileSourceCode(const QString& source) |
668 | { |
669 | return compileSourceCode(source: source.toLatin1().constData()); |
670 | } |
671 | |
672 | /*! |
673 | Sets the source code for this shader to the contents of \a fileName |
674 | and compiles it. Returns \c true if the file could be opened and the |
675 | source compiled, false otherwise. |
676 | |
677 | \sa compileSourceCode() |
678 | */ |
679 | bool QOpenGLShader::compileSourceFile(const QString& fileName) |
680 | { |
681 | QFile file(fileName); |
682 | if (!file.open(flags: QFile::ReadOnly)) { |
683 | qWarning() << "QOpenGLShader: Unable to open file" << fileName; |
684 | return false; |
685 | } |
686 | |
687 | QByteArray contents = file.readAll(); |
688 | return compileSourceCode(source: contents.constData()); |
689 | } |
690 | |
691 | /*! |
692 | Returns the source code for this shader. |
693 | |
694 | \sa compileSourceCode() |
695 | */ |
696 | QByteArray QOpenGLShader::sourceCode() const |
697 | { |
698 | Q_D(const QOpenGLShader); |
699 | GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0; |
700 | if (!shader) |
701 | return QByteArray(); |
702 | GLint size = 0; |
703 | d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, params: &size); |
704 | if (size <= 0) |
705 | return QByteArray(); |
706 | GLint len = 0; |
707 | char *source = new char [size]; |
708 | d->glfuncs->glGetShaderSource(shader, bufsize: size, length: &len, source); |
709 | QByteArray src(source); |
710 | delete [] source; |
711 | return src; |
712 | } |
713 | |
714 | /*! |
715 | Returns \c true if this shader has been compiled; false otherwise. |
716 | |
717 | \sa compileSourceCode(), compileSourceFile() |
718 | */ |
719 | bool QOpenGLShader::isCompiled() const |
720 | { |
721 | Q_D(const QOpenGLShader); |
722 | return d->compiled; |
723 | } |
724 | |
725 | /*! |
726 | Returns the errors and warnings that occurred during the last compile. |
727 | |
728 | \sa compileSourceCode(), compileSourceFile() |
729 | */ |
730 | QString QOpenGLShader::log() const |
731 | { |
732 | Q_D(const QOpenGLShader); |
733 | return d->log; |
734 | } |
735 | |
736 | /*! |
737 | Returns the OpenGL identifier associated with this shader. |
738 | |
739 | \sa QOpenGLShaderProgram::programId() |
740 | */ |
741 | GLuint QOpenGLShader::shaderId() const |
742 | { |
743 | Q_D(const QOpenGLShader); |
744 | return d->shaderGuard ? d->shaderGuard->id() : 0; |
745 | } |
746 | |
747 | class QOpenGLShaderProgramPrivate : public QObjectPrivate |
748 | { |
749 | Q_DECLARE_PUBLIC(QOpenGLShaderProgram) |
750 | public: |
751 | QOpenGLShaderProgramPrivate() |
752 | : programGuard(nullptr) |
753 | , linked(false) |
754 | , inited(false) |
755 | , removingShaders(false) |
756 | , glfuncs(new QOpenGLExtraFunctions) |
757 | #if !QT_CONFIG(opengles2) |
758 | , tessellationFuncs(nullptr) |
759 | #endif |
760 | , linkBinaryRecursion(false) |
761 | { |
762 | } |
763 | ~QOpenGLShaderProgramPrivate(); |
764 | |
765 | QOpenGLSharedResourceGuard *programGuard; |
766 | bool linked; |
767 | bool inited; |
768 | bool removingShaders; |
769 | |
770 | QString log; |
771 | QList<QOpenGLShader *> shaders; |
772 | QList<QOpenGLShader *> anonShaders; |
773 | |
774 | QOpenGLExtraFunctions *glfuncs; |
775 | #if !QT_CONFIG(opengles2) |
776 | // for tessellation features not in GLES 3.2 |
777 | QOpenGLFunctions_4_0_Core *tessellationFuncs; |
778 | #endif |
779 | |
780 | bool hasShader(QOpenGLShader::ShaderType type) const; |
781 | |
782 | QOpenGLProgramBinaryCache::ProgramDesc binaryProgram; |
783 | bool isCacheDisabled() const; |
784 | bool compileCacheable(); |
785 | bool linkBinary(); |
786 | |
787 | bool linkBinaryRecursion; |
788 | }; |
789 | |
790 | namespace { |
791 | void freeProgramFunc(QOpenGLFunctions *funcs, GLuint id) |
792 | { |
793 | funcs->glDeleteProgram(program: id); |
794 | } |
795 | } |
796 | |
797 | |
798 | QOpenGLShaderProgramPrivate::~QOpenGLShaderProgramPrivate() |
799 | { |
800 | delete glfuncs; |
801 | if (programGuard) |
802 | programGuard->free(); |
803 | } |
804 | |
805 | bool QOpenGLShaderProgramPrivate::hasShader(QOpenGLShader::ShaderType type) const |
806 | { |
807 | for (QOpenGLShader *shader : shaders) { |
808 | if (shader->shaderType() == type) |
809 | return true; |
810 | } |
811 | return false; |
812 | } |
813 | |
814 | /*! |
815 | Constructs a new shader program and attaches it to \a parent. |
816 | The program will be invalid until addShader() is called. |
817 | |
818 | The shader program will be associated with the current QOpenGLContext. |
819 | |
820 | \sa addShader() |
821 | */ |
822 | QOpenGLShaderProgram::QOpenGLShaderProgram(QObject *parent) |
823 | : QObject(*new QOpenGLShaderProgramPrivate, parent) |
824 | { |
825 | } |
826 | |
827 | /*! |
828 | Deletes this shader program. |
829 | */ |
830 | QOpenGLShaderProgram::~QOpenGLShaderProgram() |
831 | { |
832 | } |
833 | |
834 | /*! |
835 | Requests the shader program's id to be created immediately. Returns \c true |
836 | if successful; \c false otherwise. |
837 | |
838 | This function is primarily useful when combining QOpenGLShaderProgram |
839 | with other OpenGL functions that operate directly on the shader |
840 | program id, like \c {GL_OES_get_program_binary}. |
841 | |
842 | When the shader program is used normally, the shader program's id will |
843 | be created on demand. |
844 | |
845 | \sa programId() |
846 | |
847 | \since 5.3 |
848 | */ |
849 | bool QOpenGLShaderProgram::create() |
850 | { |
851 | return init(); |
852 | } |
853 | |
854 | bool QOpenGLShaderProgram::init() |
855 | { |
856 | Q_D(QOpenGLShaderProgram); |
857 | if ((d->programGuard && d->programGuard->id()) || d->inited) |
858 | return true; |
859 | d->inited = true; |
860 | QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); |
861 | if (!context) |
862 | return false; |
863 | d->glfuncs->initializeOpenGLFunctions(); |
864 | |
865 | #if !QT_CONFIG(opengles2) |
866 | if (!context->isOpenGLES() && context->format().version() >= qMakePair(value1: 4, value2: 0)) { |
867 | d->tessellationFuncs = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_0_Core>(context); |
868 | d->tessellationFuncs->initializeOpenGLFunctions(); |
869 | } |
870 | #endif |
871 | |
872 | GLuint program = d->glfuncs->glCreateProgram(); |
873 | if (!program) { |
874 | qWarning(msg: "QOpenGLShaderProgram: could not create shader program" ); |
875 | return false; |
876 | } |
877 | if (d->programGuard) |
878 | delete d->programGuard; |
879 | d->programGuard = new QOpenGLSharedResourceGuard(context, program, freeProgramFunc); |
880 | return true; |
881 | } |
882 | |
883 | /*! |
884 | Adds a compiled \a shader to this shader program. Returns \c true |
885 | if the shader could be added, or false otherwise. |
886 | |
887 | Ownership of the \a shader object remains with the caller. |
888 | It will not be deleted when this QOpenGLShaderProgram instance |
889 | is deleted. This allows the caller to add the same shader |
890 | to multiple shader programs. |
891 | |
892 | \sa addShaderFromSourceCode(), addShaderFromSourceFile() |
893 | \sa removeShader(), link(), removeAllShaders() |
894 | */ |
895 | bool QOpenGLShaderProgram::addShader(QOpenGLShader *shader) |
896 | { |
897 | Q_D(QOpenGLShaderProgram); |
898 | if (!init()) |
899 | return false; |
900 | if (d->shaders.contains(t: shader)) |
901 | return true; // Already added to this shader program. |
902 | if (d->programGuard && d->programGuard->id() && shader) { |
903 | if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id()) |
904 | return false; |
905 | if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) { |
906 | qWarning(msg: "QOpenGLShaderProgram::addShader: Program and shader are not associated with same context." ); |
907 | return false; |
908 | } |
909 | d->glfuncs->glAttachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id()); |
910 | d->linked = false; // Program needs to be relinked. |
911 | d->shaders.append(t: shader); |
912 | connect(sender: shader, SIGNAL(destroyed()), receiver: this, SLOT(shaderDestroyed())); |
913 | return true; |
914 | } else { |
915 | return false; |
916 | } |
917 | } |
918 | |
919 | /*! |
920 | Compiles \a source as a shader of the specified \a type and |
921 | adds it to this shader program. Returns \c true if compilation |
922 | was successful, false otherwise. The compilation errors |
923 | and warnings will be made available via log(). |
924 | |
925 | This function is intended to be a short-cut for quickly |
926 | adding vertex and fragment shaders to a shader program without |
927 | creating an instance of QOpenGLShader first. |
928 | |
929 | \sa addShader(), addShaderFromSourceFile() |
930 | \sa removeShader(), link(), log(), removeAllShaders() |
931 | */ |
932 | bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source) |
933 | { |
934 | Q_D(QOpenGLShaderProgram); |
935 | if (!init()) |
936 | return false; |
937 | QOpenGLShader *shader = new QOpenGLShader(type, this); |
938 | if (!shader->compileSourceCode(source)) { |
939 | d->log = shader->log(); |
940 | delete shader; |
941 | return false; |
942 | } |
943 | d->anonShaders.append(t: shader); |
944 | return addShader(shader); |
945 | } |
946 | |
947 | /*! |
948 | \overload |
949 | |
950 | Compiles \a source as a shader of the specified \a type and |
951 | adds it to this shader program. Returns \c true if compilation |
952 | was successful, false otherwise. The compilation errors |
953 | and warnings will be made available via log(). |
954 | |
955 | This function is intended to be a short-cut for quickly |
956 | adding vertex and fragment shaders to a shader program without |
957 | creating an instance of QOpenGLShader first. |
958 | |
959 | \sa addShader(), addShaderFromSourceFile() |
960 | \sa removeShader(), link(), log(), removeAllShaders() |
961 | */ |
962 | bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray& source) |
963 | { |
964 | return addShaderFromSourceCode(type, source: source.constData()); |
965 | } |
966 | |
967 | /*! |
968 | \overload |
969 | |
970 | Compiles \a source as a shader of the specified \a type and |
971 | adds it to this shader program. Returns \c true if compilation |
972 | was successful, false otherwise. The compilation errors |
973 | and warnings will be made available via log(). |
974 | |
975 | This function is intended to be a short-cut for quickly |
976 | adding vertex and fragment shaders to a shader program without |
977 | creating an instance of QOpenGLShader first. |
978 | |
979 | \sa addShader(), addShaderFromSourceFile() |
980 | \sa removeShader(), link(), log(), removeAllShaders() |
981 | */ |
982 | bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString& source) |
983 | { |
984 | return addShaderFromSourceCode(type, source: source.toLatin1().constData()); |
985 | } |
986 | |
987 | /*! |
988 | Compiles the contents of \a fileName as a shader of the specified |
989 | \a type and adds it to this shader program. Returns \c true if |
990 | compilation was successful, false otherwise. The compilation errors |
991 | and warnings will be made available via log(). |
992 | |
993 | This function is intended to be a short-cut for quickly |
994 | adding vertex and fragment shaders to a shader program without |
995 | creating an instance of QOpenGLShader first. |
996 | |
997 | \sa addShader(), addShaderFromSourceCode() |
998 | */ |
999 | bool QOpenGLShaderProgram::addShaderFromSourceFile |
1000 | (QOpenGLShader::ShaderType type, const QString& fileName) |
1001 | { |
1002 | Q_D(QOpenGLShaderProgram); |
1003 | if (!init()) |
1004 | return false; |
1005 | QOpenGLShader *shader = new QOpenGLShader(type, this); |
1006 | if (!shader->compileSourceFile(fileName)) { |
1007 | d->log = shader->log(); |
1008 | delete shader; |
1009 | return false; |
1010 | } |
1011 | d->anonShaders.append(t: shader); |
1012 | return addShader(shader); |
1013 | } |
1014 | |
1015 | /*! |
1016 | Registers the shader of the specified \a type and \a source to this |
1017 | program. Unlike addShaderFromSourceCode(), this function does not perform |
1018 | compilation. Compilation is deferred to link(), and may not happen at all, |
1019 | because link() may potentially use a program binary from Qt's shader disk |
1020 | cache. This will typically lead to a significant increase in performance. |
1021 | |
1022 | \return true if the shader has been registered or, in the non-cached case, |
1023 | compiled successfully; false if there was an error. The compilation error |
1024 | messages can be retrieved via log(). |
1025 | |
1026 | When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for |
1027 | example, or the OpenGL context has no support for context binaries, calling |
1028 | this function is equivalent to addShaderFromSourceCode(). |
1029 | |
1030 | \since 5.9 |
1031 | \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() |
1032 | */ |
1033 | bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source) |
1034 | { |
1035 | Q_D(QOpenGLShaderProgram); |
1036 | if (!init()) |
1037 | return false; |
1038 | if (d->isCacheDisabled()) |
1039 | return addShaderFromSourceCode(type, source); |
1040 | |
1041 | return addCacheableShaderFromSourceCode(type, source: QByteArray(source)); |
1042 | } |
1043 | |
1044 | static inline QShader::Stage qt_shaderTypeToStage(QOpenGLShader::ShaderType type) |
1045 | { |
1046 | switch (type) { |
1047 | case QOpenGLShader::Vertex: |
1048 | return QShader::VertexStage; |
1049 | case QOpenGLShader::Fragment: |
1050 | return QShader::FragmentStage; |
1051 | case QOpenGLShader::Geometry: |
1052 | return QShader::GeometryStage; |
1053 | case QOpenGLShader::TessellationControl: |
1054 | return QShader::TessellationControlStage; |
1055 | case QOpenGLShader::TessellationEvaluation: |
1056 | return QShader::TessellationEvaluationStage; |
1057 | case QOpenGLShader::Compute: |
1058 | return QShader::ComputeStage; |
1059 | } |
1060 | return QShader::VertexStage; |
1061 | } |
1062 | |
1063 | static inline QOpenGLShader::ShaderType qt_shaderStageToType(QShader::Stage stage) |
1064 | { |
1065 | switch (stage) { |
1066 | case QShader::VertexStage: |
1067 | return QOpenGLShader::Vertex; |
1068 | case QShader::TessellationControlStage: |
1069 | return QOpenGLShader::TessellationControl; |
1070 | case QShader::TessellationEvaluationStage: |
1071 | return QOpenGLShader::TessellationEvaluation; |
1072 | case QShader::GeometryStage: |
1073 | return QOpenGLShader::Geometry; |
1074 | case QShader::FragmentStage: |
1075 | return QOpenGLShader::Fragment; |
1076 | case QShader::ComputeStage: |
1077 | return QOpenGLShader::Compute; |
1078 | } |
1079 | return QOpenGLShader::Vertex; |
1080 | } |
1081 | |
1082 | /*! |
1083 | \overload |
1084 | |
1085 | Registers the shader of the specified \a type and \a source to this |
1086 | program. Unlike addShaderFromSourceCode(), this function does not perform |
1087 | compilation. Compilation is deferred to link(), and may not happen at all, |
1088 | because link() may potentially use a program binary from Qt's shader disk |
1089 | cache. This will typically lead to a significant increase in performance. |
1090 | |
1091 | \return true if the shader has been registered or, in the non-cached case, |
1092 | compiled successfully; false if there was an error. The compilation error |
1093 | messages can be retrieved via log(). |
1094 | |
1095 | When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for |
1096 | example, or the OpenGL context has no support for context binaries, calling |
1097 | this function is equivalent to addShaderFromSourceCode(). |
1098 | |
1099 | \since 5.9 |
1100 | \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() |
1101 | */ |
1102 | bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source) |
1103 | { |
1104 | Q_D(QOpenGLShaderProgram); |
1105 | if (!init()) |
1106 | return false; |
1107 | if (d->isCacheDisabled()) |
1108 | return addShaderFromSourceCode(type, source); |
1109 | |
1110 | d->binaryProgram.shaders.append(t: QOpenGLProgramBinaryCache::ShaderDesc(qt_shaderTypeToStage(type), source)); |
1111 | return true; |
1112 | } |
1113 | |
1114 | /*! |
1115 | \overload |
1116 | |
1117 | Registers the shader of the specified \a type and \a source to this |
1118 | program. Unlike addShaderFromSourceCode(), this function does not perform |
1119 | compilation. Compilation is deferred to link(), and may not happen at all, |
1120 | because link() may potentially use a program binary from Qt's shader disk |
1121 | cache. This will typically lead to a significant increase in performance. |
1122 | |
1123 | When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for |
1124 | example, or the OpenGL context has no support for context binaries, calling |
1125 | this function is equivalent to addShaderFromSourceCode(). |
1126 | |
1127 | \since 5.9 |
1128 | \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() |
1129 | */ |
1130 | bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source) |
1131 | { |
1132 | Q_D(QOpenGLShaderProgram); |
1133 | if (!init()) |
1134 | return false; |
1135 | if (d->isCacheDisabled()) |
1136 | return addShaderFromSourceCode(type, source); |
1137 | |
1138 | return addCacheableShaderFromSourceCode(type, source: source.toUtf8().constData()); |
1139 | } |
1140 | |
1141 | /*! |
1142 | Registers the shader of the specified \a type and \a fileName to this |
1143 | program. Unlike addShaderFromSourceFile(), this function does not perform |
1144 | compilation. Compilation is deferred to link(), and may not happen at all, |
1145 | because link() may potentially use a program binary from Qt's shader disk |
1146 | cache. This will typically lead to a significant increase in performance. |
1147 | |
1148 | \return true if the file has been read successfully, false if the file could |
1149 | not be opened or the normal, non-cached compilation of the shader has |
1150 | failed. The compilation error messages can be retrieved via log(). |
1151 | |
1152 | When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for |
1153 | example, or the OpenGL context has no support for context binaries, calling |
1154 | this function is equivalent to addShaderFromSourceFile(). |
1155 | |
1156 | \since 5.9 |
1157 | \sa addShaderFromSourceFile(), addCacheableShaderFromSourceCode() |
1158 | */ |
1159 | bool QOpenGLShaderProgram::addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName) |
1160 | { |
1161 | Q_D(QOpenGLShaderProgram); |
1162 | if (!init()) |
1163 | return false; |
1164 | if (d->isCacheDisabled()) |
1165 | return addShaderFromSourceFile(type, fileName); |
1166 | |
1167 | QOpenGLProgramBinaryCache::ShaderDesc shader(qt_shaderTypeToStage(type)); |
1168 | // NB! It could be tempting to defer reading the file contents and just |
1169 | // hash the filename as the cache key, perhaps combined with last-modified |
1170 | // timestamp checks. However, this would raise a number of issues (no |
1171 | // timestamps for files in the resource system; preference for global, not |
1172 | // per-application cache items (where filenames may clash); resource-based |
1173 | // shaders from libraries like Qt Quick; etc.), so just avoid it. |
1174 | QFile f(fileName); |
1175 | if (f.open(flags: QIODevice::ReadOnly | QIODevice::Text)) { |
1176 | shader.source = f.readAll(); |
1177 | f.close(); |
1178 | } else { |
1179 | qWarning(msg: "QOpenGLShaderProgram: Unable to open file %s" , qPrintable(fileName)); |
1180 | return false; |
1181 | } |
1182 | d->binaryProgram.shaders.append(t: shader); |
1183 | return true; |
1184 | } |
1185 | |
1186 | /*! |
1187 | Removes \a shader from this shader program. The object is not deleted. |
1188 | |
1189 | The shader program must be valid in the current QOpenGLContext. |
1190 | |
1191 | \sa addShader(), link(), removeAllShaders() |
1192 | */ |
1193 | void QOpenGLShaderProgram::removeShader(QOpenGLShader *shader) |
1194 | { |
1195 | Q_D(QOpenGLShaderProgram); |
1196 | if (d->programGuard && d->programGuard->id() |
1197 | && shader && shader->d_func()->shaderGuard) |
1198 | { |
1199 | d->glfuncs->glDetachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id()); |
1200 | } |
1201 | d->linked = false; // Program needs to be relinked. |
1202 | if (shader) { |
1203 | d->shaders.removeAll(t: shader); |
1204 | d->anonShaders.removeAll(t: shader); |
1205 | disconnect(sender: shader, SIGNAL(destroyed()), receiver: this, SLOT(shaderDestroyed())); |
1206 | } |
1207 | } |
1208 | |
1209 | /*! |
1210 | Returns a list of all shaders that have been added to this shader |
1211 | program using addShader(). |
1212 | |
1213 | \sa addShader(), removeShader() |
1214 | */ |
1215 | QList<QOpenGLShader *> QOpenGLShaderProgram::shaders() const |
1216 | { |
1217 | Q_D(const QOpenGLShaderProgram); |
1218 | return d->shaders; |
1219 | } |
1220 | |
1221 | /*! |
1222 | Removes all of the shaders that were added to this program previously. |
1223 | The QOpenGLShader objects for the shaders will not be deleted if they |
1224 | were constructed externally. QOpenGLShader objects that are constructed |
1225 | internally by QOpenGLShaderProgram will be deleted. |
1226 | |
1227 | \sa addShader(), removeShader() |
1228 | */ |
1229 | void QOpenGLShaderProgram::removeAllShaders() |
1230 | { |
1231 | Q_D(QOpenGLShaderProgram); |
1232 | d->removingShaders = true; |
1233 | for (QOpenGLShader *shader : std::as_const(t&: d->shaders)) { |
1234 | if (d->programGuard && d->programGuard->id() |
1235 | && shader && shader->d_func()->shaderGuard) |
1236 | { |
1237 | d->glfuncs->glDetachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id()); |
1238 | } |
1239 | } |
1240 | // Delete shader objects that were created anonymously. |
1241 | qDeleteAll(c: d->anonShaders); |
1242 | d->shaders.clear(); |
1243 | d->anonShaders.clear(); |
1244 | d->binaryProgram = QOpenGLProgramBinaryCache::ProgramDesc(); |
1245 | d->linked = false; // Program needs to be relinked. |
1246 | d->removingShaders = false; |
1247 | } |
1248 | |
1249 | /*! |
1250 | Links together the shaders that were added to this program with |
1251 | addShader(). Returns \c true if the link was successful or |
1252 | false otherwise. If the link failed, the error messages can |
1253 | be retrieved with log(). |
1254 | |
1255 | Subclasses can override this function to initialize attributes |
1256 | and uniform variables for use in specific shader programs. |
1257 | |
1258 | If the shader program was already linked, calling this |
1259 | function again will force it to be re-linked. |
1260 | |
1261 | When shaders were added to this program via |
1262 | addCacheableShaderFromSourceCode() or addCacheableShaderFromSourceFile(), |
1263 | program binaries are supported, and a cached binary is available on disk, |
1264 | actual compilation and linking are skipped. Instead, link() will initialize |
1265 | the program with the binary blob via glProgramBinary(). If there is no |
1266 | cached version of the program or it was generated with a different driver |
1267 | version, the shaders will be compiled from source and the program will get |
1268 | linked normally. This allows seamless upgrading of the graphics drivers, |
1269 | without having to worry about potentially incompatible binary formats. |
1270 | |
1271 | \sa addShader(), log() |
1272 | */ |
1273 | bool QOpenGLShaderProgram::link() |
1274 | { |
1275 | Q_D(QOpenGLShaderProgram); |
1276 | GLuint program = d->programGuard ? d->programGuard->id() : 0; |
1277 | if (!program) |
1278 | return false; |
1279 | |
1280 | if (!d->linkBinaryRecursion && d->shaders.isEmpty() && !d->binaryProgram.shaders.isEmpty()) |
1281 | return d->linkBinary(); |
1282 | |
1283 | GLint value; |
1284 | if (d->shaders.isEmpty()) { |
1285 | // If there are no explicit shaders, then it is possible that the |
1286 | // application added a program binary with glProgramBinaryOES(), or |
1287 | // otherwise populated the shaders itself. This is also the case when |
1288 | // we are recursively called back from linkBinary() after a successful |
1289 | // glProgramBinary(). Check to see if the program is already linked and |
1290 | // bail out if so. |
1291 | value = 0; |
1292 | d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, params: &value); |
1293 | d->linked = (value != 0); |
1294 | if (d->linked) |
1295 | return true; |
1296 | } |
1297 | |
1298 | d->glfuncs->glLinkProgram(program); |
1299 | value = 0; |
1300 | d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, params: &value); |
1301 | d->linked = (value != 0); |
1302 | value = 0; |
1303 | d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, params: &value); |
1304 | d->log = QString(); |
1305 | if (value > 1) { |
1306 | char *logbuf = new char [value]; |
1307 | GLint len; |
1308 | d->glfuncs->glGetProgramInfoLog(program, bufsize: value, length: &len, infolog: logbuf); |
1309 | d->log = QString::fromLatin1(ba: logbuf); |
1310 | if (!d->linked && !d->linkBinaryRecursion) { |
1311 | QString name = objectName(); |
1312 | if (name.isEmpty()) |
1313 | qWarning(msg: "QOpenGLShader::link: %ls" , qUtf16Printable(d->log)); |
1314 | else |
1315 | qWarning(msg: "QOpenGLShader::link[%ls]: %ls" , qUtf16Printable(name), qUtf16Printable(d->log)); |
1316 | } |
1317 | delete [] logbuf; |
1318 | } |
1319 | return d->linked; |
1320 | } |
1321 | |
1322 | /*! |
1323 | Returns \c true if this shader program has been linked; false otherwise. |
1324 | |
1325 | \sa link() |
1326 | */ |
1327 | bool QOpenGLShaderProgram::isLinked() const |
1328 | { |
1329 | Q_D(const QOpenGLShaderProgram); |
1330 | return d->linked; |
1331 | } |
1332 | |
1333 | /*! |
1334 | Returns the errors and warnings that occurred during the last link() |
1335 | or addShader() with explicitly specified source code. |
1336 | |
1337 | \sa link() |
1338 | */ |
1339 | QString QOpenGLShaderProgram::log() const |
1340 | { |
1341 | Q_D(const QOpenGLShaderProgram); |
1342 | return d->log; |
1343 | } |
1344 | |
1345 | /*! |
1346 | Binds this shader program to the active QOpenGLContext and makes |
1347 | it the current shader program. Any previously bound shader program |
1348 | is released. This is equivalent to calling \c{glUseProgram()} on |
1349 | programId(). Returns \c true if the program was successfully bound; |
1350 | false otherwise. If the shader program has not yet been linked, |
1351 | or it needs to be re-linked, this function will call link(). |
1352 | |
1353 | \sa link(), release() |
1354 | */ |
1355 | bool QOpenGLShaderProgram::bind() |
1356 | { |
1357 | Q_D(QOpenGLShaderProgram); |
1358 | GLuint program = d->programGuard ? d->programGuard->id() : 0; |
1359 | if (!program) |
1360 | return false; |
1361 | if (!d->linked && !link()) |
1362 | return false; |
1363 | #ifndef QT_NO_DEBUG |
1364 | if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) { |
1365 | qWarning(msg: "QOpenGLShaderProgram::bind: program is not valid in the current context." ); |
1366 | return false; |
1367 | } |
1368 | #endif |
1369 | d->glfuncs->glUseProgram(program); |
1370 | return true; |
1371 | } |
1372 | |
1373 | /*! |
1374 | Releases the active shader program from the current QOpenGLContext. |
1375 | This is equivalent to calling \c{glUseProgram(0)}. |
1376 | |
1377 | \sa bind() |
1378 | */ |
1379 | void QOpenGLShaderProgram::release() |
1380 | { |
1381 | Q_D(QOpenGLShaderProgram); |
1382 | #ifndef QT_NO_DEBUG |
1383 | if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) |
1384 | qWarning(msg: "QOpenGLShaderProgram::release: program is not valid in the current context." ); |
1385 | #endif |
1386 | d->glfuncs->glUseProgram(program: 0); |
1387 | } |
1388 | |
1389 | /*! |
1390 | Returns the OpenGL identifier associated with this shader program. |
1391 | |
1392 | \sa QOpenGLShader::shaderId() |
1393 | */ |
1394 | GLuint QOpenGLShaderProgram::programId() const |
1395 | { |
1396 | Q_D(const QOpenGLShaderProgram); |
1397 | GLuint id = d->programGuard ? d->programGuard->id() : 0; |
1398 | if (id) |
1399 | return id; |
1400 | |
1401 | // Create the identifier if we don't have one yet. This is for |
1402 | // applications that want to create the attached shader configuration |
1403 | // themselves, particularly those using program binaries. |
1404 | if (!const_cast<QOpenGLShaderProgram *>(this)->init()) |
1405 | return 0; |
1406 | return d->programGuard ? d->programGuard->id() : 0; |
1407 | } |
1408 | |
1409 | /*! |
1410 | Binds the attribute \a name to the specified \a location. This |
1411 | function can be called before or after the program has been linked. |
1412 | Any attributes that have not been explicitly bound when the program |
1413 | is linked will be assigned locations automatically. |
1414 | |
1415 | When this function is called after the program has been linked, |
1416 | the program will need to be relinked for the change to take effect. |
1417 | |
1418 | \sa attributeLocation() |
1419 | */ |
1420 | void QOpenGLShaderProgram::bindAttributeLocation(const char *name, int location) |
1421 | { |
1422 | Q_D(QOpenGLShaderProgram); |
1423 | if (!init() || !d->programGuard || !d->programGuard->id()) |
1424 | return; |
1425 | d->glfuncs->glBindAttribLocation(program: d->programGuard->id(), index: location, name); |
1426 | d->linked = false; // Program needs to be relinked. |
1427 | } |
1428 | |
1429 | /*! |
1430 | \overload |
1431 | |
1432 | Binds the attribute \a name to the specified \a location. This |
1433 | function can be called before or after the program has been linked. |
1434 | Any attributes that have not been explicitly bound when the program |
1435 | is linked will be assigned locations automatically. |
1436 | |
1437 | When this function is called after the program has been linked, |
1438 | the program will need to be relinked for the change to take effect. |
1439 | |
1440 | \sa attributeLocation() |
1441 | */ |
1442 | void QOpenGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location) |
1443 | { |
1444 | bindAttributeLocation(name: name.constData(), location); |
1445 | } |
1446 | |
1447 | /*! |
1448 | \overload |
1449 | |
1450 | Binds the attribute \a name to the specified \a location. This |
1451 | function can be called before or after the program has been linked. |
1452 | Any attributes that have not been explicitly bound when the program |
1453 | is linked will be assigned locations automatically. |
1454 | |
1455 | When this function is called after the program has been linked, |
1456 | the program will need to be relinked for the change to take effect. |
1457 | |
1458 | \sa attributeLocation() |
1459 | */ |
1460 | void QOpenGLShaderProgram::bindAttributeLocation(const QString& name, int location) |
1461 | { |
1462 | bindAttributeLocation(name: name.toLatin1().constData(), location); |
1463 | } |
1464 | |
1465 | /*! |
1466 | Returns the location of the attribute \a name within this shader |
1467 | program's parameter list. Returns -1 if \a name is not a valid |
1468 | attribute for this shader program. |
1469 | |
1470 | \sa uniformLocation(), bindAttributeLocation() |
1471 | */ |
1472 | int QOpenGLShaderProgram::attributeLocation(const char *name) const |
1473 | { |
1474 | Q_D(const QOpenGLShaderProgram); |
1475 | if (d->linked && d->programGuard && d->programGuard->id()) { |
1476 | return d->glfuncs->glGetAttribLocation(program: d->programGuard->id(), name); |
1477 | } else { |
1478 | qWarning(msg: "QOpenGLShaderProgram::attributeLocation(%s): shader program is not linked" , name); |
1479 | return -1; |
1480 | } |
1481 | } |
1482 | |
1483 | /*! |
1484 | \overload |
1485 | |
1486 | Returns the location of the attribute \a name within this shader |
1487 | program's parameter list. Returns -1 if \a name is not a valid |
1488 | attribute for this shader program. |
1489 | |
1490 | \sa uniformLocation(), bindAttributeLocation() |
1491 | */ |
1492 | int QOpenGLShaderProgram::attributeLocation(const QByteArray& name) const |
1493 | { |
1494 | return attributeLocation(name: name.constData()); |
1495 | } |
1496 | |
1497 | /*! |
1498 | \overload |
1499 | |
1500 | Returns the location of the attribute \a name within this shader |
1501 | program's parameter list. Returns -1 if \a name is not a valid |
1502 | attribute for this shader program. |
1503 | |
1504 | \sa uniformLocation(), bindAttributeLocation() |
1505 | */ |
1506 | int QOpenGLShaderProgram::attributeLocation(const QString& name) const |
1507 | { |
1508 | return attributeLocation(name: name.toLatin1().constData()); |
1509 | } |
1510 | |
1511 | /*! |
1512 | Sets the attribute at \a location in the current context to \a value. |
1513 | |
1514 | \sa setUniformValue() |
1515 | */ |
1516 | void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat value) |
1517 | { |
1518 | Q_D(QOpenGLShaderProgram); |
1519 | if (location != -1) |
1520 | d->glfuncs->glVertexAttrib1fv(indx: location, values: &value); |
1521 | } |
1522 | |
1523 | /*! |
1524 | \overload |
1525 | |
1526 | Sets the attribute called \a name in the current context to \a value. |
1527 | |
1528 | \sa setUniformValue() |
1529 | */ |
1530 | void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat value) |
1531 | { |
1532 | setAttributeValue(location: attributeLocation(name), value); |
1533 | } |
1534 | |
1535 | /*! |
1536 | Sets the attribute at \a location in the current context to |
1537 | the 2D vector (\a x, \a y). |
1538 | |
1539 | \sa setUniformValue() |
1540 | */ |
1541 | void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y) |
1542 | { |
1543 | Q_D(QOpenGLShaderProgram); |
1544 | if (location != -1) { |
1545 | GLfloat values[2] = {x, y}; |
1546 | d->glfuncs->glVertexAttrib2fv(indx: location, values); |
1547 | } |
1548 | } |
1549 | |
1550 | /*! |
1551 | \overload |
1552 | |
1553 | Sets the attribute called \a name in the current context to |
1554 | the 2D vector (\a x, \a y). |
1555 | |
1556 | \sa setUniformValue() |
1557 | */ |
1558 | void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y) |
1559 | { |
1560 | setAttributeValue(location: attributeLocation(name), x, y); |
1561 | } |
1562 | |
1563 | /*! |
1564 | Sets the attribute at \a location in the current context to |
1565 | the 3D vector (\a x, \a y, \a z). |
1566 | |
1567 | \sa setUniformValue() |
1568 | */ |
1569 | void QOpenGLShaderProgram::setAttributeValue |
1570 | (int location, GLfloat x, GLfloat y, GLfloat z) |
1571 | { |
1572 | Q_D(QOpenGLShaderProgram); |
1573 | Q_UNUSED(d); |
1574 | if (location != -1) { |
1575 | GLfloat values[3] = {x, y, z}; |
1576 | d->glfuncs->glVertexAttrib3fv(indx: location, values); |
1577 | } |
1578 | } |
1579 | |
1580 | /*! |
1581 | \overload |
1582 | |
1583 | Sets the attribute called \a name in the current context to |
1584 | the 3D vector (\a x, \a y, \a z). |
1585 | |
1586 | \sa setUniformValue() |
1587 | */ |
1588 | void QOpenGLShaderProgram::setAttributeValue |
1589 | (const char *name, GLfloat x, GLfloat y, GLfloat z) |
1590 | { |
1591 | setAttributeValue(location: attributeLocation(name), x, y, z); |
1592 | } |
1593 | |
1594 | /*! |
1595 | Sets the attribute at \a location in the current context to |
1596 | the 4D vector (\a x, \a y, \a z, \a w). |
1597 | |
1598 | \sa setUniformValue() |
1599 | */ |
1600 | void QOpenGLShaderProgram::setAttributeValue |
1601 | (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
1602 | { |
1603 | Q_D(QOpenGLShaderProgram); |
1604 | if (location != -1) { |
1605 | GLfloat values[4] = {x, y, z, w}; |
1606 | d->glfuncs->glVertexAttrib4fv(indx: location, values); |
1607 | } |
1608 | } |
1609 | |
1610 | /*! |
1611 | \overload |
1612 | |
1613 | Sets the attribute called \a name in the current context to |
1614 | the 4D vector (\a x, \a y, \a z, \a w). |
1615 | |
1616 | \sa setUniformValue() |
1617 | */ |
1618 | void QOpenGLShaderProgram::setAttributeValue |
1619 | (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
1620 | { |
1621 | setAttributeValue(location: attributeLocation(name), x, y, z, w); |
1622 | } |
1623 | |
1624 | /*! |
1625 | Sets the attribute at \a location in the current context to \a value. |
1626 | |
1627 | \sa setUniformValue() |
1628 | */ |
1629 | void QOpenGLShaderProgram::setAttributeValue(int location, const QVector2D& value) |
1630 | { |
1631 | Q_D(QOpenGLShaderProgram); |
1632 | if (location != -1) |
1633 | d->glfuncs->glVertexAttrib2fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value)); |
1634 | } |
1635 | |
1636 | /*! |
1637 | \overload |
1638 | |
1639 | Sets the attribute called \a name in the current context to \a value. |
1640 | |
1641 | \sa setUniformValue() |
1642 | */ |
1643 | void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value) |
1644 | { |
1645 | setAttributeValue(location: attributeLocation(name), value); |
1646 | } |
1647 | |
1648 | /*! |
1649 | Sets the attribute at \a location in the current context to \a value. |
1650 | |
1651 | \sa setUniformValue() |
1652 | */ |
1653 | void QOpenGLShaderProgram::setAttributeValue(int location, const QVector3D& value) |
1654 | { |
1655 | Q_D(QOpenGLShaderProgram); |
1656 | Q_UNUSED(d); |
1657 | if (location != -1) |
1658 | d->glfuncs->glVertexAttrib3fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value)); |
1659 | } |
1660 | |
1661 | /*! |
1662 | \overload |
1663 | |
1664 | Sets the attribute called \a name in the current context to \a value. |
1665 | |
1666 | \sa setUniformValue() |
1667 | */ |
1668 | void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value) |
1669 | { |
1670 | setAttributeValue(location: attributeLocation(name), value); |
1671 | } |
1672 | |
1673 | /*! |
1674 | Sets the attribute at \a location in the current context to \a value. |
1675 | |
1676 | \sa setUniformValue() |
1677 | */ |
1678 | void QOpenGLShaderProgram::setAttributeValue(int location, const QVector4D& value) |
1679 | { |
1680 | Q_D(QOpenGLShaderProgram); |
1681 | Q_UNUSED(d); |
1682 | if (location != -1) |
1683 | d->glfuncs->glVertexAttrib4fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value)); |
1684 | } |
1685 | |
1686 | /*! |
1687 | \overload |
1688 | |
1689 | Sets the attribute called \a name in the current context to \a value. |
1690 | |
1691 | \sa setUniformValue() |
1692 | */ |
1693 | void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value) |
1694 | { |
1695 | setAttributeValue(location: attributeLocation(name), value); |
1696 | } |
1697 | |
1698 | /*! |
1699 | Sets the attribute at \a location in the current context to \a value. |
1700 | |
1701 | \sa setUniformValue() |
1702 | */ |
1703 | void QOpenGLShaderProgram::setAttributeValue(int location, const QColor& value) |
1704 | { |
1705 | Q_D(QOpenGLShaderProgram); |
1706 | Q_UNUSED(d); |
1707 | if (location != -1) { |
1708 | GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()), |
1709 | GLfloat(value.blueF()), GLfloat(value.alphaF())}; |
1710 | d->glfuncs->glVertexAttrib4fv(indx: location, values); |
1711 | } |
1712 | } |
1713 | |
1714 | /*! |
1715 | \overload |
1716 | |
1717 | Sets the attribute called \a name in the current context to \a value. |
1718 | |
1719 | \sa setUniformValue() |
1720 | */ |
1721 | void QOpenGLShaderProgram::setAttributeValue(const char *name, const QColor& value) |
1722 | { |
1723 | setAttributeValue(location: attributeLocation(name), value); |
1724 | } |
1725 | |
1726 | /*! |
1727 | Sets the attribute at \a location in the current context to the |
1728 | contents of \a values, which contains \a columns elements, each |
1729 | consisting of \a rows elements. The \a rows value should be |
1730 | 1, 2, 3, or 4. This function is typically used to set matrix |
1731 | values and column vectors. |
1732 | |
1733 | \sa setUniformValue() |
1734 | */ |
1735 | void QOpenGLShaderProgram::setAttributeValue |
1736 | (int location, const GLfloat *values, int columns, int rows) |
1737 | { |
1738 | Q_D(QOpenGLShaderProgram); |
1739 | Q_UNUSED(d); |
1740 | if (rows < 1 || rows > 4) { |
1741 | qWarning(msg: "QOpenGLShaderProgram::setAttributeValue: rows %d not supported" , rows); |
1742 | return; |
1743 | } |
1744 | if (location != -1) { |
1745 | while (columns-- > 0) { |
1746 | if (rows == 1) |
1747 | d->glfuncs->glVertexAttrib1fv(indx: location, values); |
1748 | else if (rows == 2) |
1749 | d->glfuncs->glVertexAttrib2fv(indx: location, values); |
1750 | else if (rows == 3) |
1751 | d->glfuncs->glVertexAttrib3fv(indx: location, values); |
1752 | else |
1753 | d->glfuncs->glVertexAttrib4fv(indx: location, values); |
1754 | values += rows; |
1755 | ++location; |
1756 | } |
1757 | } |
1758 | } |
1759 | |
1760 | /*! |
1761 | \overload |
1762 | |
1763 | Sets the attribute called \a name in the current context to the |
1764 | contents of \a values, which contains \a columns elements, each |
1765 | consisting of \a rows elements. The \a rows value should be |
1766 | 1, 2, 3, or 4. This function is typically used to set matrix |
1767 | values and column vectors. |
1768 | |
1769 | \sa setUniformValue() |
1770 | */ |
1771 | void QOpenGLShaderProgram::setAttributeValue |
1772 | (const char *name, const GLfloat *values, int columns, int rows) |
1773 | { |
1774 | setAttributeValue(location: attributeLocation(name), values, columns, rows); |
1775 | } |
1776 | |
1777 | /*! |
1778 | Sets an array of vertex \a values on the attribute at \a location |
1779 | in this shader program. The \a tupleSize indicates the number of |
1780 | components per vertex (1, 2, 3, or 4), and the \a stride indicates |
1781 | the number of bytes between vertices. A default \a stride value |
1782 | of zero indicates that the vertices are densely packed in \a values. |
1783 | |
1784 | The array will become active when enableAttributeArray() is called |
1785 | on the \a location. Otherwise the value specified with |
1786 | setAttributeValue() for \a location will be used. |
1787 | |
1788 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1789 | \sa disableAttributeArray() |
1790 | */ |
1791 | void QOpenGLShaderProgram::setAttributeArray |
1792 | (int location, const GLfloat *values, int tupleSize, int stride) |
1793 | { |
1794 | Q_D(QOpenGLShaderProgram); |
1795 | Q_UNUSED(d); |
1796 | if (location != -1) { |
1797 | d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, GL_FLOAT, GL_FALSE, |
1798 | stride, ptr: values); |
1799 | } |
1800 | } |
1801 | |
1802 | /*! |
1803 | Sets an array of 2D vertex \a values on the attribute at \a location |
1804 | in this shader program. The \a stride indicates the number of bytes |
1805 | between vertices. A default \a stride value of zero indicates that |
1806 | the vertices are densely packed in \a values. |
1807 | |
1808 | The array will become active when enableAttributeArray() is called |
1809 | on the \a location. Otherwise the value specified with |
1810 | setAttributeValue() for \a location will be used. |
1811 | |
1812 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1813 | \sa disableAttributeArray() |
1814 | */ |
1815 | void QOpenGLShaderProgram::setAttributeArray |
1816 | (int location, const QVector2D *values, int stride) |
1817 | { |
1818 | Q_D(QOpenGLShaderProgram); |
1819 | Q_UNUSED(d); |
1820 | if (location != -1) { |
1821 | d->glfuncs->glVertexAttribPointer(indx: location, size: 2, GL_FLOAT, GL_FALSE, |
1822 | stride, ptr: values); |
1823 | } |
1824 | } |
1825 | |
1826 | /*! |
1827 | Sets an array of 3D vertex \a values on the attribute at \a location |
1828 | in this shader program. The \a stride indicates the number of bytes |
1829 | between vertices. A default \a stride value of zero indicates that |
1830 | the vertices are densely packed in \a values. |
1831 | |
1832 | The array will become active when enableAttributeArray() is called |
1833 | on the \a location. Otherwise the value specified with |
1834 | setAttributeValue() for \a location will be used. |
1835 | |
1836 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1837 | \sa disableAttributeArray() |
1838 | */ |
1839 | void QOpenGLShaderProgram::setAttributeArray |
1840 | (int location, const QVector3D *values, int stride) |
1841 | { |
1842 | Q_D(QOpenGLShaderProgram); |
1843 | Q_UNUSED(d); |
1844 | if (location != -1) { |
1845 | d->glfuncs->glVertexAttribPointer(indx: location, size: 3, GL_FLOAT, GL_FALSE, |
1846 | stride, ptr: values); |
1847 | } |
1848 | } |
1849 | |
1850 | /*! |
1851 | Sets an array of 4D vertex \a values on the attribute at \a location |
1852 | in this shader program. The \a stride indicates the number of bytes |
1853 | between vertices. A default \a stride value of zero indicates that |
1854 | the vertices are densely packed in \a values. |
1855 | |
1856 | The array will become active when enableAttributeArray() is called |
1857 | on the \a location. Otherwise the value specified with |
1858 | setAttributeValue() for \a location will be used. |
1859 | |
1860 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1861 | \sa disableAttributeArray() |
1862 | */ |
1863 | void QOpenGLShaderProgram::setAttributeArray |
1864 | (int location, const QVector4D *values, int stride) |
1865 | { |
1866 | Q_D(QOpenGLShaderProgram); |
1867 | Q_UNUSED(d); |
1868 | if (location != -1) { |
1869 | d->glfuncs->glVertexAttribPointer(indx: location, size: 4, GL_FLOAT, GL_FALSE, |
1870 | stride, ptr: values); |
1871 | } |
1872 | } |
1873 | |
1874 | /*! |
1875 | Sets an array of vertex \a values on the attribute at \a location |
1876 | in this shader program. The \a stride indicates the number of bytes |
1877 | between vertices. A default \a stride value of zero indicates that |
1878 | the vertices are densely packed in \a values. |
1879 | |
1880 | The \a type indicates the type of elements in the \a values array, |
1881 | usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize |
1882 | indicates the number of components per vertex: 1, 2, 3, or 4. |
1883 | |
1884 | The array will become active when enableAttributeArray() is called |
1885 | on the \a location. Otherwise the value specified with |
1886 | setAttributeValue() for \a location will be used. |
1887 | |
1888 | The setAttributeBuffer() function can be used to set the attribute |
1889 | array to an offset within a vertex buffer. |
1890 | |
1891 | \note Normalization will be enabled. If this is not desired, call |
1892 | glVertexAttribPointer directly through QOpenGLFunctions. |
1893 | |
1894 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1895 | \sa disableAttributeArray(), setAttributeBuffer() |
1896 | */ |
1897 | void QOpenGLShaderProgram::setAttributeArray |
1898 | (int location, GLenum type, const void *values, int tupleSize, int stride) |
1899 | { |
1900 | Q_D(QOpenGLShaderProgram); |
1901 | Q_UNUSED(d); |
1902 | if (location != -1) { |
1903 | d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, type, GL_TRUE, |
1904 | stride, ptr: values); |
1905 | } |
1906 | } |
1907 | |
1908 | /*! |
1909 | \overload |
1910 | |
1911 | Sets an array of vertex \a values on the attribute called \a name |
1912 | in this shader program. The \a tupleSize indicates the number of |
1913 | components per vertex (1, 2, 3, or 4), and the \a stride indicates |
1914 | the number of bytes between vertices. A default \a stride value |
1915 | of zero indicates that the vertices are densely packed in \a values. |
1916 | |
1917 | The array will become active when enableAttributeArray() is called |
1918 | on \a name. Otherwise the value specified with setAttributeValue() |
1919 | for \a name will be used. |
1920 | |
1921 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1922 | \sa disableAttributeArray() |
1923 | */ |
1924 | void QOpenGLShaderProgram::setAttributeArray |
1925 | (const char *name, const GLfloat *values, int tupleSize, int stride) |
1926 | { |
1927 | setAttributeArray(location: attributeLocation(name), values, tupleSize, stride); |
1928 | } |
1929 | |
1930 | /*! |
1931 | \overload |
1932 | |
1933 | Sets an array of 2D vertex \a values on the attribute called \a name |
1934 | in this shader program. The \a stride indicates the number of bytes |
1935 | between vertices. A default \a stride value of zero indicates that |
1936 | the vertices are densely packed in \a values. |
1937 | |
1938 | The array will become active when enableAttributeArray() is called |
1939 | on \a name. Otherwise the value specified with setAttributeValue() |
1940 | for \a name will be used. |
1941 | |
1942 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1943 | \sa disableAttributeArray() |
1944 | */ |
1945 | void QOpenGLShaderProgram::setAttributeArray |
1946 | (const char *name, const QVector2D *values, int stride) |
1947 | { |
1948 | setAttributeArray(location: attributeLocation(name), values, stride); |
1949 | } |
1950 | |
1951 | /*! |
1952 | \overload |
1953 | |
1954 | Sets an array of 3D vertex \a values on the attribute called \a name |
1955 | in this shader program. The \a stride indicates the number of bytes |
1956 | between vertices. A default \a stride value of zero indicates that |
1957 | the vertices are densely packed in \a values. |
1958 | |
1959 | The array will become active when enableAttributeArray() is called |
1960 | on \a name. Otherwise the value specified with setAttributeValue() |
1961 | for \a name will be used. |
1962 | |
1963 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1964 | \sa disableAttributeArray() |
1965 | */ |
1966 | void QOpenGLShaderProgram::setAttributeArray |
1967 | (const char *name, const QVector3D *values, int stride) |
1968 | { |
1969 | setAttributeArray(location: attributeLocation(name), values, stride); |
1970 | } |
1971 | |
1972 | /*! |
1973 | \overload |
1974 | |
1975 | Sets an array of 4D vertex \a values on the attribute called \a name |
1976 | in this shader program. The \a stride indicates the number of bytes |
1977 | between vertices. A default \a stride value of zero indicates that |
1978 | the vertices are densely packed in \a values. |
1979 | |
1980 | The array will become active when enableAttributeArray() is called |
1981 | on \a name. Otherwise the value specified with setAttributeValue() |
1982 | for \a name will be used. |
1983 | |
1984 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
1985 | \sa disableAttributeArray() |
1986 | */ |
1987 | void QOpenGLShaderProgram::setAttributeArray |
1988 | (const char *name, const QVector4D *values, int stride) |
1989 | { |
1990 | setAttributeArray(location: attributeLocation(name), values, stride); |
1991 | } |
1992 | |
1993 | /*! |
1994 | \overload |
1995 | |
1996 | Sets an array of vertex \a values on the attribute called \a name |
1997 | in this shader program. The \a stride indicates the number of bytes |
1998 | between vertices. A default \a stride value of zero indicates that |
1999 | the vertices are densely packed in \a values. |
2000 | |
2001 | The \a type indicates the type of elements in the \a values array, |
2002 | usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize |
2003 | indicates the number of components per vertex: 1, 2, 3, or 4. |
2004 | |
2005 | The array will become active when enableAttributeArray() is called |
2006 | on the \a name. Otherwise the value specified with |
2007 | setAttributeValue() for \a name will be used. |
2008 | |
2009 | The setAttributeBuffer() function can be used to set the attribute |
2010 | array to an offset within a vertex buffer. |
2011 | |
2012 | \sa setAttributeValue(), setUniformValue(), enableAttributeArray() |
2013 | \sa disableAttributeArray(), setAttributeBuffer() |
2014 | */ |
2015 | void QOpenGLShaderProgram::setAttributeArray |
2016 | (const char *name, GLenum type, const void *values, int tupleSize, int stride) |
2017 | { |
2018 | setAttributeArray(location: attributeLocation(name), type, values, tupleSize, stride); |
2019 | } |
2020 | |
2021 | /*! |
2022 | Sets an array of vertex values on the attribute at \a location in |
2023 | this shader program, starting at a specific \a offset in the |
2024 | currently bound vertex buffer. The \a stride indicates the number |
2025 | of bytes between vertices. A default \a stride value of zero |
2026 | indicates that the vertices are densely packed in the value array. |
2027 | |
2028 | The \a type indicates the type of elements in the vertex value |
2029 | array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a |
2030 | tupleSize indicates the number of components per vertex: 1, 2, 3, |
2031 | or 4. |
2032 | |
2033 | The array will become active when enableAttributeArray() is called |
2034 | on the \a location. Otherwise the value specified with |
2035 | setAttributeValue() for \a location will be used. |
2036 | |
2037 | \note Normalization will be enabled. If this is not desired, call |
2038 | glVertexAttribPointer directly through QOpenGLFunctions. |
2039 | |
2040 | \sa setAttributeArray() |
2041 | */ |
2042 | void QOpenGLShaderProgram::setAttributeBuffer |
2043 | (int location, GLenum type, int offset, int tupleSize, int stride) |
2044 | { |
2045 | Q_D(QOpenGLShaderProgram); |
2046 | Q_UNUSED(d); |
2047 | if (location != -1) { |
2048 | d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, type, GL_TRUE, stride, |
2049 | ptr: reinterpret_cast<const void *>(qintptr(offset))); |
2050 | } |
2051 | } |
2052 | |
2053 | /*! |
2054 | \overload |
2055 | |
2056 | Sets an array of vertex values on the attribute called \a name |
2057 | in this shader program, starting at a specific \a offset in the |
2058 | currently bound vertex buffer. The \a stride indicates the number |
2059 | of bytes between vertices. A default \a stride value of zero |
2060 | indicates that the vertices are densely packed in the value array. |
2061 | |
2062 | The \a type indicates the type of elements in the vertex value |
2063 | array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a |
2064 | tupleSize indicates the number of components per vertex: 1, 2, 3, |
2065 | or 4. |
2066 | |
2067 | The array will become active when enableAttributeArray() is called |
2068 | on the \a name. Otherwise the value specified with |
2069 | setAttributeValue() for \a name will be used. |
2070 | |
2071 | \sa setAttributeArray() |
2072 | */ |
2073 | void QOpenGLShaderProgram::setAttributeBuffer |
2074 | (const char *name, GLenum type, int offset, int tupleSize, int stride) |
2075 | { |
2076 | setAttributeBuffer(location: attributeLocation(name), type, offset, tupleSize, stride); |
2077 | } |
2078 | |
2079 | /*! |
2080 | Enables the vertex array at \a location in this shader program |
2081 | so that the value set by setAttributeArray() on \a location |
2082 | will be used by the shader program. |
2083 | |
2084 | \sa disableAttributeArray(), setAttributeArray(), setAttributeValue() |
2085 | \sa setUniformValue() |
2086 | */ |
2087 | void QOpenGLShaderProgram::enableAttributeArray(int location) |
2088 | { |
2089 | Q_D(QOpenGLShaderProgram); |
2090 | Q_UNUSED(d); |
2091 | if (location != -1) |
2092 | d->glfuncs->glEnableVertexAttribArray(index: location); |
2093 | } |
2094 | |
2095 | /*! |
2096 | \overload |
2097 | |
2098 | Enables the vertex array called \a name in this shader program |
2099 | so that the value set by setAttributeArray() on \a name |
2100 | will be used by the shader program. |
2101 | |
2102 | \sa disableAttributeArray(), setAttributeArray(), setAttributeValue() |
2103 | \sa setUniformValue() |
2104 | */ |
2105 | void QOpenGLShaderProgram::enableAttributeArray(const char *name) |
2106 | { |
2107 | enableAttributeArray(location: attributeLocation(name)); |
2108 | } |
2109 | |
2110 | /*! |
2111 | Disables the vertex array at \a location in this shader program |
2112 | that was enabled by a previous call to enableAttributeArray(). |
2113 | |
2114 | \sa enableAttributeArray(), setAttributeArray(), setAttributeValue() |
2115 | \sa setUniformValue() |
2116 | */ |
2117 | void QOpenGLShaderProgram::disableAttributeArray(int location) |
2118 | { |
2119 | Q_D(QOpenGLShaderProgram); |
2120 | Q_UNUSED(d); |
2121 | if (location != -1) |
2122 | d->glfuncs->glDisableVertexAttribArray(index: location); |
2123 | } |
2124 | |
2125 | /*! |
2126 | \overload |
2127 | |
2128 | Disables the vertex array called \a name in this shader program |
2129 | that was enabled by a previous call to enableAttributeArray(). |
2130 | |
2131 | \sa enableAttributeArray(), setAttributeArray(), setAttributeValue() |
2132 | \sa setUniformValue() |
2133 | */ |
2134 | void QOpenGLShaderProgram::disableAttributeArray(const char *name) |
2135 | { |
2136 | disableAttributeArray(location: attributeLocation(name)); |
2137 | } |
2138 | |
2139 | /*! |
2140 | Returns the location of the uniform variable \a name within this shader |
2141 | program's parameter list. Returns -1 if \a name is not a valid |
2142 | uniform variable for this shader program. |
2143 | |
2144 | \sa attributeLocation() |
2145 | */ |
2146 | int QOpenGLShaderProgram::uniformLocation(const char *name) const |
2147 | { |
2148 | Q_D(const QOpenGLShaderProgram); |
2149 | Q_UNUSED(d); |
2150 | if (d->linked && d->programGuard && d->programGuard->id()) { |
2151 | return d->glfuncs->glGetUniformLocation(program: d->programGuard->id(), name); |
2152 | } else { |
2153 | qWarning(msg: "QOpenGLShaderProgram::uniformLocation(%s): shader program is not linked" , name); |
2154 | return -1; |
2155 | } |
2156 | } |
2157 | |
2158 | /*! |
2159 | \overload |
2160 | |
2161 | Returns the location of the uniform variable \a name within this shader |
2162 | program's parameter list. Returns -1 if \a name is not a valid |
2163 | uniform variable for this shader program. |
2164 | |
2165 | \sa attributeLocation() |
2166 | */ |
2167 | int QOpenGLShaderProgram::uniformLocation(const QByteArray& name) const |
2168 | { |
2169 | return uniformLocation(name: name.constData()); |
2170 | } |
2171 | |
2172 | /*! |
2173 | \overload |
2174 | |
2175 | Returns the location of the uniform variable \a name within this shader |
2176 | program's parameter list. Returns -1 if \a name is not a valid |
2177 | uniform variable for this shader program. |
2178 | |
2179 | \sa attributeLocation() |
2180 | */ |
2181 | int QOpenGLShaderProgram::uniformLocation(const QString& name) const |
2182 | { |
2183 | return uniformLocation(name: name.toLatin1().constData()); |
2184 | } |
2185 | |
2186 | /*! |
2187 | Sets the uniform variable at \a location in the current context to \a value. |
2188 | |
2189 | \sa setAttributeValue() |
2190 | */ |
2191 | void QOpenGLShaderProgram::setUniformValue(int location, GLfloat value) |
2192 | { |
2193 | Q_D(QOpenGLShaderProgram); |
2194 | Q_UNUSED(d); |
2195 | if (location != -1) |
2196 | d->glfuncs->glUniform1fv(location, count: 1, v: &value); |
2197 | } |
2198 | |
2199 | /*! |
2200 | \overload |
2201 | |
2202 | Sets the uniform variable called \a name in the current context |
2203 | to \a value. |
2204 | |
2205 | \sa setAttributeValue() |
2206 | */ |
2207 | void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat value) |
2208 | { |
2209 | setUniformValue(location: uniformLocation(name), value); |
2210 | } |
2211 | |
2212 | /*! |
2213 | Sets the uniform variable at \a location in the current context to \a value. |
2214 | |
2215 | \sa setAttributeValue() |
2216 | */ |
2217 | void QOpenGLShaderProgram::setUniformValue(int location, GLint value) |
2218 | { |
2219 | Q_D(QOpenGLShaderProgram); |
2220 | Q_UNUSED(d); |
2221 | if (location != -1) |
2222 | d->glfuncs->glUniform1i(location, x: value); |
2223 | } |
2224 | |
2225 | /*! |
2226 | \overload |
2227 | |
2228 | Sets the uniform variable called \a name in the current context |
2229 | to \a value. |
2230 | |
2231 | \sa setAttributeValue() |
2232 | */ |
2233 | void QOpenGLShaderProgram::setUniformValue(const char *name, GLint value) |
2234 | { |
2235 | setUniformValue(location: uniformLocation(name), value); |
2236 | } |
2237 | |
2238 | /*! |
2239 | Sets the uniform variable at \a location in the current context to \a value. |
2240 | This function should be used when setting sampler values. |
2241 | |
2242 | \note This function is not aware of unsigned int support in modern OpenGL |
2243 | versions and therefore treats \a value as a GLint and calls glUniform1i. |
2244 | |
2245 | \sa setAttributeValue() |
2246 | */ |
2247 | void QOpenGLShaderProgram::setUniformValue(int location, GLuint value) |
2248 | { |
2249 | Q_D(QOpenGLShaderProgram); |
2250 | Q_UNUSED(d); |
2251 | if (location != -1) |
2252 | d->glfuncs->glUniform1i(location, x: value); |
2253 | } |
2254 | |
2255 | /*! |
2256 | \overload |
2257 | |
2258 | Sets the uniform variable called \a name in the current context |
2259 | to \a value. This function should be used when setting sampler values. |
2260 | |
2261 | \note This function is not aware of unsigned int support in modern OpenGL |
2262 | versions and therefore treats \a value as a GLint and calls glUniform1i. |
2263 | |
2264 | \sa setAttributeValue() |
2265 | */ |
2266 | void QOpenGLShaderProgram::setUniformValue(const char *name, GLuint value) |
2267 | { |
2268 | setUniformValue(location: uniformLocation(name), value); |
2269 | } |
2270 | |
2271 | /*! |
2272 | Sets the uniform variable at \a location in the current context to |
2273 | the 2D vector (\a x, \a y). |
2274 | |
2275 | \sa setAttributeValue() |
2276 | */ |
2277 | void QOpenGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y) |
2278 | { |
2279 | Q_D(QOpenGLShaderProgram); |
2280 | Q_UNUSED(d); |
2281 | if (location != -1) { |
2282 | GLfloat values[2] = {x, y}; |
2283 | d->glfuncs->glUniform2fv(location, count: 1, v: values); |
2284 | } |
2285 | } |
2286 | |
2287 | /*! |
2288 | \overload |
2289 | |
2290 | Sets the uniform variable called \a name in the current context to |
2291 | the 2D vector (\a x, \a y). |
2292 | |
2293 | \sa setAttributeValue() |
2294 | */ |
2295 | void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y) |
2296 | { |
2297 | setUniformValue(location: uniformLocation(name), x, y); |
2298 | } |
2299 | |
2300 | /*! |
2301 | Sets the uniform variable at \a location in the current context to |
2302 | the 3D vector (\a x, \a y, \a z). |
2303 | |
2304 | \sa setAttributeValue() |
2305 | */ |
2306 | void QOpenGLShaderProgram::setUniformValue |
2307 | (int location, GLfloat x, GLfloat y, GLfloat z) |
2308 | { |
2309 | Q_D(QOpenGLShaderProgram); |
2310 | Q_UNUSED(d); |
2311 | if (location != -1) { |
2312 | GLfloat values[3] = {x, y, z}; |
2313 | d->glfuncs->glUniform3fv(location, count: 1, v: values); |
2314 | } |
2315 | } |
2316 | |
2317 | /*! |
2318 | \overload |
2319 | |
2320 | Sets the uniform variable called \a name in the current context to |
2321 | the 3D vector (\a x, \a y, \a z). |
2322 | |
2323 | \sa setAttributeValue() |
2324 | */ |
2325 | void QOpenGLShaderProgram::setUniformValue |
2326 | (const char *name, GLfloat x, GLfloat y, GLfloat z) |
2327 | { |
2328 | setUniformValue(location: uniformLocation(name), x, y, z); |
2329 | } |
2330 | |
2331 | /*! |
2332 | Sets the uniform variable at \a location in the current context to |
2333 | the 4D vector (\a x, \a y, \a z, \a w). |
2334 | |
2335 | \sa setAttributeValue() |
2336 | */ |
2337 | void QOpenGLShaderProgram::setUniformValue |
2338 | (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
2339 | { |
2340 | Q_D(QOpenGLShaderProgram); |
2341 | Q_UNUSED(d); |
2342 | if (location != -1) { |
2343 | GLfloat values[4] = {x, y, z, w}; |
2344 | d->glfuncs->glUniform4fv(location, count: 1, v: values); |
2345 | } |
2346 | } |
2347 | |
2348 | /*! |
2349 | \overload |
2350 | |
2351 | Sets the uniform variable called \a name in the current context to |
2352 | the 4D vector (\a x, \a y, \a z, \a w). |
2353 | |
2354 | \sa setAttributeValue() |
2355 | */ |
2356 | void QOpenGLShaderProgram::setUniformValue |
2357 | (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
2358 | { |
2359 | setUniformValue(location: uniformLocation(name), x, y, z, w); |
2360 | } |
2361 | |
2362 | /*! |
2363 | Sets the uniform variable at \a location in the current context to \a value. |
2364 | |
2365 | \sa setAttributeValue() |
2366 | */ |
2367 | void QOpenGLShaderProgram::setUniformValue(int location, const QVector2D& value) |
2368 | { |
2369 | Q_D(QOpenGLShaderProgram); |
2370 | Q_UNUSED(d); |
2371 | if (location != -1) |
2372 | d->glfuncs->glUniform2fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value)); |
2373 | } |
2374 | |
2375 | /*! |
2376 | \overload |
2377 | |
2378 | Sets the uniform variable called \a name in the current context |
2379 | to \a value. |
2380 | |
2381 | \sa setAttributeValue() |
2382 | */ |
2383 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector2D& value) |
2384 | { |
2385 | setUniformValue(location: uniformLocation(name), value); |
2386 | } |
2387 | |
2388 | /*! |
2389 | Sets the uniform variable at \a location in the current context to \a value. |
2390 | |
2391 | \sa setAttributeValue() |
2392 | */ |
2393 | void QOpenGLShaderProgram::setUniformValue(int location, const QVector3D& value) |
2394 | { |
2395 | Q_D(QOpenGLShaderProgram); |
2396 | Q_UNUSED(d); |
2397 | if (location != -1) |
2398 | d->glfuncs->glUniform3fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value)); |
2399 | } |
2400 | |
2401 | /*! |
2402 | \overload |
2403 | |
2404 | Sets the uniform variable called \a name in the current context |
2405 | to \a value. |
2406 | |
2407 | \sa setAttributeValue() |
2408 | */ |
2409 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector3D& value) |
2410 | { |
2411 | setUniformValue(location: uniformLocation(name), value); |
2412 | } |
2413 | |
2414 | /*! |
2415 | Sets the uniform variable at \a location in the current context to \a value. |
2416 | |
2417 | \sa setAttributeValue() |
2418 | */ |
2419 | void QOpenGLShaderProgram::setUniformValue(int location, const QVector4D& value) |
2420 | { |
2421 | Q_D(QOpenGLShaderProgram); |
2422 | Q_UNUSED(d); |
2423 | if (location != -1) |
2424 | d->glfuncs->glUniform4fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value)); |
2425 | } |
2426 | |
2427 | /*! |
2428 | \overload |
2429 | |
2430 | Sets the uniform variable called \a name in the current context |
2431 | to \a value. |
2432 | |
2433 | \sa setAttributeValue() |
2434 | */ |
2435 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector4D& value) |
2436 | { |
2437 | setUniformValue(location: uniformLocation(name), value); |
2438 | } |
2439 | |
2440 | /*! |
2441 | Sets the uniform variable at \a location in the current context to |
2442 | the red, green, blue, and alpha components of \a color. |
2443 | |
2444 | \sa setAttributeValue() |
2445 | */ |
2446 | void QOpenGLShaderProgram::setUniformValue(int location, const QColor& color) |
2447 | { |
2448 | Q_D(QOpenGLShaderProgram); |
2449 | Q_UNUSED(d); |
2450 | if (location != -1) { |
2451 | GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()), |
2452 | GLfloat(color.blueF()), GLfloat(color.alphaF())}; |
2453 | d->glfuncs->glUniform4fv(location, count: 1, v: values); |
2454 | } |
2455 | } |
2456 | |
2457 | /*! |
2458 | \overload |
2459 | |
2460 | Sets the uniform variable called \a name in the current context to |
2461 | the red, green, blue, and alpha components of \a color. |
2462 | |
2463 | \sa setAttributeValue() |
2464 | */ |
2465 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QColor& color) |
2466 | { |
2467 | setUniformValue(location: uniformLocation(name), color); |
2468 | } |
2469 | |
2470 | /*! |
2471 | Sets the uniform variable at \a location in the current context to |
2472 | the x and y coordinates of \a point. |
2473 | |
2474 | \sa setAttributeValue() |
2475 | */ |
2476 | void QOpenGLShaderProgram::setUniformValue(int location, const QPoint& point) |
2477 | { |
2478 | Q_D(QOpenGLShaderProgram); |
2479 | Q_UNUSED(d); |
2480 | if (location != -1) { |
2481 | GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())}; |
2482 | d->glfuncs->glUniform2fv(location, count: 1, v: values); |
2483 | } |
2484 | } |
2485 | |
2486 | /*! |
2487 | \overload |
2488 | |
2489 | Sets the uniform variable associated with \a name in the current |
2490 | context to the x and y coordinates of \a point. |
2491 | |
2492 | \sa setAttributeValue() |
2493 | */ |
2494 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QPoint& point) |
2495 | { |
2496 | setUniformValue(location: uniformLocation(name), point); |
2497 | } |
2498 | |
2499 | /*! |
2500 | Sets the uniform variable at \a location in the current context to |
2501 | the x and y coordinates of \a point. |
2502 | |
2503 | \sa setAttributeValue() |
2504 | */ |
2505 | void QOpenGLShaderProgram::setUniformValue(int location, const QPointF& point) |
2506 | { |
2507 | Q_D(QOpenGLShaderProgram); |
2508 | Q_UNUSED(d); |
2509 | if (location != -1) { |
2510 | GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())}; |
2511 | d->glfuncs->glUniform2fv(location, count: 1, v: values); |
2512 | } |
2513 | } |
2514 | |
2515 | /*! |
2516 | \overload |
2517 | |
2518 | Sets the uniform variable associated with \a name in the current |
2519 | context to the x and y coordinates of \a point. |
2520 | |
2521 | \sa setAttributeValue() |
2522 | */ |
2523 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QPointF& point) |
2524 | { |
2525 | setUniformValue(location: uniformLocation(name), point); |
2526 | } |
2527 | |
2528 | /*! |
2529 | Sets the uniform variable at \a location in the current context to |
2530 | the width and height of the given \a size. |
2531 | |
2532 | \sa setAttributeValue() |
2533 | */ |
2534 | void QOpenGLShaderProgram::setUniformValue(int location, const QSize& size) |
2535 | { |
2536 | Q_D(QOpenGLShaderProgram); |
2537 | Q_UNUSED(d); |
2538 | if (location != -1) { |
2539 | GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())}; |
2540 | d->glfuncs->glUniform2fv(location, count: 1, v: values); |
2541 | } |
2542 | } |
2543 | |
2544 | /*! |
2545 | \overload |
2546 | |
2547 | Sets the uniform variable associated with \a name in the current |
2548 | context to the width and height of the given \a size. |
2549 | |
2550 | \sa setAttributeValue() |
2551 | */ |
2552 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QSize& size) |
2553 | { |
2554 | setUniformValue(location: uniformLocation(name), size); |
2555 | } |
2556 | |
2557 | /*! |
2558 | Sets the uniform variable at \a location in the current context to |
2559 | the width and height of the given \a size. |
2560 | |
2561 | \sa setAttributeValue() |
2562 | */ |
2563 | void QOpenGLShaderProgram::setUniformValue(int location, const QSizeF& size) |
2564 | { |
2565 | Q_D(QOpenGLShaderProgram); |
2566 | Q_UNUSED(d); |
2567 | if (location != -1) { |
2568 | GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())}; |
2569 | d->glfuncs->glUniform2fv(location, count: 1, v: values); |
2570 | } |
2571 | } |
2572 | |
2573 | /*! |
2574 | \overload |
2575 | |
2576 | Sets the uniform variable associated with \a name in the current |
2577 | context to the width and height of the given \a size. |
2578 | |
2579 | \sa setAttributeValue() |
2580 | */ |
2581 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QSizeF& size) |
2582 | { |
2583 | setUniformValue(location: uniformLocation(name), size); |
2584 | } |
2585 | |
2586 | /*! |
2587 | Sets the uniform variable at \a location in the current context |
2588 | to a 2x2 matrix \a value. |
2589 | |
2590 | \sa setAttributeValue() |
2591 | */ |
2592 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value) |
2593 | { |
2594 | Q_D(QOpenGLShaderProgram); |
2595 | Q_UNUSED(d); |
2596 | d->glfuncs->glUniformMatrix2fv(location, count: 1, GL_FALSE, value: value.constData()); |
2597 | } |
2598 | |
2599 | /*! |
2600 | \overload |
2601 | |
2602 | Sets the uniform variable called \a name in the current context |
2603 | to a 2x2 matrix \a value. |
2604 | |
2605 | \sa setAttributeValue() |
2606 | */ |
2607 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value) |
2608 | { |
2609 | setUniformValue(location: uniformLocation(name), value); |
2610 | } |
2611 | |
2612 | /*! |
2613 | Sets the uniform variable at \a location in the current context |
2614 | to a 2x3 matrix \a value. |
2615 | |
2616 | \note This function is not aware of non square matrix support, |
2617 | that is, GLSL types like mat2x3, that is present in modern OpenGL |
2618 | versions. Instead, it treats the uniform as an array of vec3. |
2619 | |
2620 | \sa setAttributeValue() |
2621 | */ |
2622 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value) |
2623 | { |
2624 | Q_D(QOpenGLShaderProgram); |
2625 | Q_UNUSED(d); |
2626 | d->glfuncs->glUniform3fv(location, count: 2, v: value.constData()); |
2627 | } |
2628 | |
2629 | /*! |
2630 | \overload |
2631 | |
2632 | Sets the uniform variable called \a name in the current context |
2633 | to a 2x3 matrix \a value. |
2634 | |
2635 | \note This function is not aware of non square matrix support, |
2636 | that is, GLSL types like mat2x3, that is present in modern OpenGL |
2637 | versions. Instead, it treats the uniform as an array of vec3. |
2638 | |
2639 | \sa setAttributeValue() |
2640 | */ |
2641 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value) |
2642 | { |
2643 | setUniformValue(location: uniformLocation(name), value); |
2644 | } |
2645 | |
2646 | /*! |
2647 | Sets the uniform variable at \a location in the current context |
2648 | to a 2x4 matrix \a value. |
2649 | |
2650 | \note This function is not aware of non square matrix support, |
2651 | that is, GLSL types like mat2x4, that is present in modern OpenGL |
2652 | versions. Instead, it treats the uniform as an array of vec4. |
2653 | |
2654 | \sa setAttributeValue() |
2655 | */ |
2656 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value) |
2657 | { |
2658 | Q_D(QOpenGLShaderProgram); |
2659 | Q_UNUSED(d); |
2660 | d->glfuncs->glUniform4fv(location, count: 2, v: value.constData()); |
2661 | } |
2662 | |
2663 | /*! |
2664 | \overload |
2665 | |
2666 | Sets the uniform variable called \a name in the current context |
2667 | to a 2x4 matrix \a value. |
2668 | |
2669 | \note This function is not aware of non square matrix support, |
2670 | that is, GLSL types like mat2x4, that is present in modern OpenGL |
2671 | versions. Instead, it treats the uniform as an array of vec4. |
2672 | |
2673 | \sa setAttributeValue() |
2674 | */ |
2675 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value) |
2676 | { |
2677 | setUniformValue(location: uniformLocation(name), value); |
2678 | } |
2679 | |
2680 | /*! |
2681 | Sets the uniform variable at \a location in the current context |
2682 | to a 3x2 matrix \a value. |
2683 | |
2684 | \note This function is not aware of non square matrix support, |
2685 | that is, GLSL types like mat3x2, that is present in modern OpenGL |
2686 | versions. Instead, it treats the uniform as an array of vec2. |
2687 | |
2688 | \sa setAttributeValue() |
2689 | */ |
2690 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value) |
2691 | { |
2692 | Q_D(QOpenGLShaderProgram); |
2693 | Q_UNUSED(d); |
2694 | d->glfuncs->glUniform2fv(location, count: 3, v: value.constData()); |
2695 | } |
2696 | |
2697 | /*! |
2698 | \overload |
2699 | |
2700 | Sets the uniform variable called \a name in the current context |
2701 | to a 3x2 matrix \a value. |
2702 | |
2703 | \note This function is not aware of non square matrix support, |
2704 | that is, GLSL types like mat3x2, that is present in modern OpenGL |
2705 | versions. Instead, it treats the uniform as an array of vec2. |
2706 | |
2707 | \sa setAttributeValue() |
2708 | */ |
2709 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value) |
2710 | { |
2711 | setUniformValue(location: uniformLocation(name), value); |
2712 | } |
2713 | |
2714 | /*! |
2715 | Sets the uniform variable at \a location in the current context |
2716 | to a 3x3 matrix \a value. |
2717 | |
2718 | \sa setAttributeValue() |
2719 | */ |
2720 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value) |
2721 | { |
2722 | Q_D(QOpenGLShaderProgram); |
2723 | Q_UNUSED(d); |
2724 | d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: value.constData()); |
2725 | } |
2726 | |
2727 | /*! |
2728 | \overload |
2729 | |
2730 | Sets the uniform variable called \a name in the current context |
2731 | to a 3x3 matrix \a value. |
2732 | |
2733 | \sa setAttributeValue() |
2734 | */ |
2735 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value) |
2736 | { |
2737 | setUniformValue(location: uniformLocation(name), value); |
2738 | } |
2739 | |
2740 | /*! |
2741 | Sets the uniform variable at \a location in the current context |
2742 | to a 3x4 matrix \a value. |
2743 | |
2744 | \note This function is not aware of non square matrix support, |
2745 | that is, GLSL types like mat3x4, that is present in modern OpenGL |
2746 | versions. Instead, it treats the uniform as an array of vec4. |
2747 | |
2748 | \sa setAttributeValue() |
2749 | */ |
2750 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value) |
2751 | { |
2752 | Q_D(QOpenGLShaderProgram); |
2753 | Q_UNUSED(d); |
2754 | d->glfuncs->glUniform4fv(location, count: 3, v: value.constData()); |
2755 | } |
2756 | |
2757 | /*! |
2758 | \overload |
2759 | |
2760 | Sets the uniform variable called \a name in the current context |
2761 | to a 3x4 matrix \a value. |
2762 | |
2763 | \note This function is not aware of non square matrix support, |
2764 | that is, GLSL types like mat3x4, that is present in modern OpenGL |
2765 | versions. Instead, it treats the uniform as an array of vec4. |
2766 | |
2767 | \sa setAttributeValue() |
2768 | */ |
2769 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value) |
2770 | { |
2771 | setUniformValue(location: uniformLocation(name), value); |
2772 | } |
2773 | |
2774 | /*! |
2775 | Sets the uniform variable at \a location in the current context |
2776 | to a 4x2 matrix \a value. |
2777 | |
2778 | \note This function is not aware of non square matrix support, |
2779 | that is, GLSL types like mat4x2, that is present in modern OpenGL |
2780 | versions. Instead, it treats the uniform as an array of vec2. |
2781 | |
2782 | \sa setAttributeValue() |
2783 | */ |
2784 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value) |
2785 | { |
2786 | Q_D(QOpenGLShaderProgram); |
2787 | Q_UNUSED(d); |
2788 | d->glfuncs->glUniform2fv(location, count: 4, v: value.constData()); |
2789 | } |
2790 | |
2791 | /*! |
2792 | \overload |
2793 | |
2794 | Sets the uniform variable called \a name in the current context |
2795 | to a 4x2 matrix \a value. |
2796 | |
2797 | \note This function is not aware of non square matrix support, |
2798 | that is, GLSL types like mat4x2, that is present in modern OpenGL |
2799 | versions. Instead, it treats the uniform as an array of vec2. |
2800 | |
2801 | \sa setAttributeValue() |
2802 | */ |
2803 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value) |
2804 | { |
2805 | setUniformValue(location: uniformLocation(name), value); |
2806 | } |
2807 | |
2808 | /*! |
2809 | Sets the uniform variable at \a location in the current context |
2810 | to a 4x3 matrix \a value. |
2811 | |
2812 | \note This function is not aware of non square matrix support, |
2813 | that is, GLSL types like mat4x3, that is present in modern OpenGL |
2814 | versions. Instead, it treats the uniform as an array of vec3. |
2815 | |
2816 | \sa setAttributeValue() |
2817 | */ |
2818 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value) |
2819 | { |
2820 | Q_D(QOpenGLShaderProgram); |
2821 | Q_UNUSED(d); |
2822 | d->glfuncs->glUniform3fv(location, count: 4, v: value.constData()); |
2823 | } |
2824 | |
2825 | /*! |
2826 | \overload |
2827 | |
2828 | Sets the uniform variable called \a name in the current context |
2829 | to a 4x3 matrix \a value. |
2830 | |
2831 | \note This function is not aware of non square matrix support, |
2832 | that is, GLSL types like mat4x3, that is present in modern OpenGL |
2833 | versions. Instead, it treats the uniform as an array of vec3. |
2834 | |
2835 | \sa setAttributeValue() |
2836 | */ |
2837 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value) |
2838 | { |
2839 | setUniformValue(location: uniformLocation(name), value); |
2840 | } |
2841 | |
2842 | /*! |
2843 | Sets the uniform variable at \a location in the current context |
2844 | to a 4x4 matrix \a value. |
2845 | |
2846 | \sa setAttributeValue() |
2847 | */ |
2848 | void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value) |
2849 | { |
2850 | Q_D(QOpenGLShaderProgram); |
2851 | Q_UNUSED(d); |
2852 | d->glfuncs->glUniformMatrix4fv(location, count: 1, GL_FALSE, value: value.constData()); |
2853 | } |
2854 | |
2855 | /*! |
2856 | \overload |
2857 | |
2858 | Sets the uniform variable called \a name in the current context |
2859 | to a 4x4 matrix \a value. |
2860 | |
2861 | \sa setAttributeValue() |
2862 | */ |
2863 | void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value) |
2864 | { |
2865 | setUniformValue(location: uniformLocation(name), value); |
2866 | } |
2867 | |
2868 | /*! |
2869 | \overload |
2870 | |
2871 | Sets the uniform variable at \a location in the current context |
2872 | to a 2x2 matrix \a value. The matrix elements must be specified |
2873 | in column-major order. |
2874 | |
2875 | \sa setAttributeValue() |
2876 | */ |
2877 | void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2]) |
2878 | { |
2879 | Q_D(QOpenGLShaderProgram); |
2880 | Q_UNUSED(d); |
2881 | if (location != -1) |
2882 | d->glfuncs->glUniformMatrix2fv(location, count: 1, GL_FALSE, value: value[0]); |
2883 | } |
2884 | |
2885 | /*! |
2886 | \overload |
2887 | |
2888 | Sets the uniform variable at \a location in the current context |
2889 | to a 3x3 matrix \a value. The matrix elements must be specified |
2890 | in column-major order. |
2891 | |
2892 | \sa setAttributeValue() |
2893 | */ |
2894 | void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3]) |
2895 | { |
2896 | Q_D(QOpenGLShaderProgram); |
2897 | Q_UNUSED(d); |
2898 | if (location != -1) |
2899 | d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: value[0]); |
2900 | } |
2901 | |
2902 | /*! |
2903 | \overload |
2904 | |
2905 | Sets the uniform variable at \a location in the current context |
2906 | to a 4x4 matrix \a value. The matrix elements must be specified |
2907 | in column-major order. |
2908 | |
2909 | \sa setAttributeValue() |
2910 | */ |
2911 | void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4]) |
2912 | { |
2913 | Q_D(QOpenGLShaderProgram); |
2914 | Q_UNUSED(d); |
2915 | if (location != -1) |
2916 | d->glfuncs->glUniformMatrix4fv(location, count: 1, GL_FALSE, value: value[0]); |
2917 | } |
2918 | |
2919 | |
2920 | /*! |
2921 | \overload |
2922 | |
2923 | Sets the uniform variable called \a name in the current context |
2924 | to a 2x2 matrix \a value. The matrix elements must be specified |
2925 | in column-major order. |
2926 | |
2927 | \sa setAttributeValue() |
2928 | */ |
2929 | void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2]) |
2930 | { |
2931 | setUniformValue(location: uniformLocation(name), value); |
2932 | } |
2933 | |
2934 | /*! |
2935 | \overload |
2936 | |
2937 | Sets the uniform variable called \a name in the current context |
2938 | to a 3x3 matrix \a value. The matrix elements must be specified |
2939 | in column-major order. |
2940 | |
2941 | \sa setAttributeValue() |
2942 | */ |
2943 | void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3]) |
2944 | { |
2945 | setUniformValue(location: uniformLocation(name), value); |
2946 | } |
2947 | |
2948 | /*! |
2949 | \overload |
2950 | |
2951 | Sets the uniform variable called \a name in the current context |
2952 | to a 4x4 matrix \a value. The matrix elements must be specified |
2953 | in column-major order. |
2954 | |
2955 | \sa setAttributeValue() |
2956 | */ |
2957 | void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4]) |
2958 | { |
2959 | setUniformValue(location: uniformLocation(name), value); |
2960 | } |
2961 | |
2962 | /*! |
2963 | Sets the uniform variable at \a location in the current context to a |
2964 | 3x3 transformation matrix \a value that is specified as a QTransform value. |
2965 | |
2966 | To set a QTransform value as a 4x4 matrix in a shader, use |
2967 | \c{setUniformValue(location, QMatrix4x4(value))}. |
2968 | */ |
2969 | void QOpenGLShaderProgram::setUniformValue(int location, const QTransform& value) |
2970 | { |
2971 | Q_D(QOpenGLShaderProgram); |
2972 | Q_UNUSED(d); |
2973 | if (location != -1) { |
2974 | GLfloat mat[3][3] = { |
2975 | {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())}, |
2976 | {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())}, |
2977 | {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())} |
2978 | }; |
2979 | d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: mat[0]); |
2980 | } |
2981 | } |
2982 | |
2983 | /*! |
2984 | \overload |
2985 | |
2986 | Sets the uniform variable called \a name in the current context to a |
2987 | 3x3 transformation matrix \a value that is specified as a QTransform value. |
2988 | |
2989 | To set a QTransform value as a 4x4 matrix in a shader, use |
2990 | \c{setUniformValue(name, QMatrix4x4(value))}. |
2991 | */ |
2992 | void QOpenGLShaderProgram::setUniformValue |
2993 | (const char *name, const QTransform& value) |
2994 | { |
2995 | setUniformValue(location: uniformLocation(name), value); |
2996 | } |
2997 | |
2998 | /*! |
2999 | Sets the uniform variable array at \a location in the current |
3000 | context to the \a count elements of \a values. |
3001 | |
3002 | \sa setAttributeValue() |
3003 | */ |
3004 | void QOpenGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count) |
3005 | { |
3006 | Q_D(QOpenGLShaderProgram); |
3007 | Q_UNUSED(d); |
3008 | if (location != -1) |
3009 | d->glfuncs->glUniform1iv(location, count, v: values); |
3010 | } |
3011 | |
3012 | /*! |
3013 | \overload |
3014 | |
3015 | Sets the uniform variable array called \a name in the current |
3016 | context to the \a count elements of \a values. |
3017 | |
3018 | \sa setAttributeValue() |
3019 | */ |
3020 | void QOpenGLShaderProgram::setUniformValueArray |
3021 | (const char *name, const GLint *values, int count) |
3022 | { |
3023 | setUniformValueArray(location: uniformLocation(name), values, count); |
3024 | } |
3025 | |
3026 | /*! |
3027 | Sets the uniform variable array at \a location in the current |
3028 | context to the \a count elements of \a values. This overload |
3029 | should be used when setting an array of sampler values. |
3030 | |
3031 | \note This function is not aware of unsigned int support in modern OpenGL |
3032 | versions and therefore treats \a values as a GLint and calls glUniform1iv. |
3033 | |
3034 | \sa setAttributeValue() |
3035 | */ |
3036 | void QOpenGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count) |
3037 | { |
3038 | Q_D(QOpenGLShaderProgram); |
3039 | Q_UNUSED(d); |
3040 | if (location != -1) |
3041 | d->glfuncs->glUniform1iv(location, count, v: reinterpret_cast<const GLint *>(values)); |
3042 | } |
3043 | |
3044 | /*! |
3045 | \overload |
3046 | |
3047 | Sets the uniform variable array called \a name in the current |
3048 | context to the \a count elements of \a values. This overload |
3049 | should be used when setting an array of sampler values. |
3050 | |
3051 | \sa setAttributeValue() |
3052 | */ |
3053 | void QOpenGLShaderProgram::setUniformValueArray |
3054 | (const char *name, const GLuint *values, int count) |
3055 | { |
3056 | setUniformValueArray(location: uniformLocation(name), values, count); |
3057 | } |
3058 | |
3059 | /*! |
3060 | Sets the uniform variable array at \a location in the current |
3061 | context to the \a count elements of \a values. Each element |
3062 | has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4. |
3063 | |
3064 | \sa setAttributeValue() |
3065 | */ |
3066 | void QOpenGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize) |
3067 | { |
3068 | Q_D(QOpenGLShaderProgram); |
3069 | Q_UNUSED(d); |
3070 | if (location != -1) { |
3071 | if (tupleSize == 1) |
3072 | d->glfuncs->glUniform1fv(location, count, v: values); |
3073 | else if (tupleSize == 2) |
3074 | d->glfuncs->glUniform2fv(location, count, v: values); |
3075 | else if (tupleSize == 3) |
3076 | d->glfuncs->glUniform3fv(location, count, v: values); |
3077 | else if (tupleSize == 4) |
3078 | d->glfuncs->glUniform4fv(location, count, v: values); |
3079 | else |
3080 | qWarning(msg: "QOpenGLShaderProgram::setUniformValue: size %d not supported" , tupleSize); |
3081 | } |
3082 | } |
3083 | |
3084 | /*! |
3085 | \overload |
3086 | |
3087 | Sets the uniform variable array called \a name in the current |
3088 | context to the \a count elements of \a values. Each element |
3089 | has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4. |
3090 | |
3091 | \sa setAttributeValue() |
3092 | */ |
3093 | void QOpenGLShaderProgram::setUniformValueArray |
3094 | (const char *name, const GLfloat *values, int count, int tupleSize) |
3095 | { |
3096 | setUniformValueArray(location: uniformLocation(name), values, count, tupleSize); |
3097 | } |
3098 | |
3099 | /*! |
3100 | Sets the uniform variable array at \a location in the current |
3101 | context to the \a count 2D vector elements of \a values. |
3102 | |
3103 | \sa setAttributeValue() |
3104 | */ |
3105 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count) |
3106 | { |
3107 | Q_D(QOpenGLShaderProgram); |
3108 | Q_UNUSED(d); |
3109 | if (location != -1) |
3110 | d->glfuncs->glUniform2fv(location, count, v: reinterpret_cast<const GLfloat *>(values)); |
3111 | } |
3112 | |
3113 | /*! |
3114 | \overload |
3115 | |
3116 | Sets the uniform variable array called \a name in the current |
3117 | context to the \a count 2D vector elements of \a values. |
3118 | |
3119 | \sa setAttributeValue() |
3120 | */ |
3121 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count) |
3122 | { |
3123 | setUniformValueArray(location: uniformLocation(name), values, count); |
3124 | } |
3125 | |
3126 | /*! |
3127 | Sets the uniform variable array at \a location in the current |
3128 | context to the \a count 3D vector elements of \a values. |
3129 | |
3130 | \sa setAttributeValue() |
3131 | */ |
3132 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count) |
3133 | { |
3134 | Q_D(QOpenGLShaderProgram); |
3135 | Q_UNUSED(d); |
3136 | if (location != -1) |
3137 | d->glfuncs->glUniform3fv(location, count, v: reinterpret_cast<const GLfloat *>(values)); |
3138 | } |
3139 | |
3140 | /*! |
3141 | \overload |
3142 | |
3143 | Sets the uniform variable array called \a name in the current |
3144 | context to the \a count 3D vector elements of \a values. |
3145 | |
3146 | \sa setAttributeValue() |
3147 | */ |
3148 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count) |
3149 | { |
3150 | setUniformValueArray(location: uniformLocation(name), values, count); |
3151 | } |
3152 | |
3153 | /*! |
3154 | Sets the uniform variable array at \a location in the current |
3155 | context to the \a count 4D vector elements of \a values. |
3156 | |
3157 | \sa setAttributeValue() |
3158 | */ |
3159 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count) |
3160 | { |
3161 | Q_D(QOpenGLShaderProgram); |
3162 | Q_UNUSED(d); |
3163 | if (location != -1) |
3164 | d->glfuncs->glUniform4fv(location, count, v: reinterpret_cast<const GLfloat *>(values)); |
3165 | } |
3166 | |
3167 | /*! |
3168 | \overload |
3169 | |
3170 | Sets the uniform variable array called \a name in the current |
3171 | context to the \a count 4D vector elements of \a values. |
3172 | |
3173 | \sa setAttributeValue() |
3174 | */ |
3175 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count) |
3176 | { |
3177 | setUniformValueArray(location: uniformLocation(name), values, count); |
3178 | } |
3179 | |
3180 | // We have to repack matrix arrays from qreal to GLfloat. |
3181 | #define setUniformMatrixArray(func,location,values,count,type,cols,rows) \ |
3182 | if (location == -1 || count <= 0) \ |
3183 | return; \ |
3184 | if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \ |
3185 | func(location, count, GL_FALSE, \ |
3186 | reinterpret_cast<const GLfloat *>(values[0].constData())); \ |
3187 | } else { \ |
3188 | QVarLengthArray<GLfloat> temp(cols * rows * count); \ |
3189 | for (int index = 0; index < count; ++index) { \ |
3190 | for (int index2 = 0; index2 < (cols * rows); ++index2) { \ |
3191 | temp.data()[cols * rows * index + index2] = \ |
3192 | values[index].constData()[index2]; \ |
3193 | } \ |
3194 | } \ |
3195 | func(location, count, GL_FALSE, temp.constData()); \ |
3196 | } |
3197 | #define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \ |
3198 | if (location == -1 || count <= 0) \ |
3199 | return; \ |
3200 | if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \ |
3201 | const GLfloat *data = reinterpret_cast<const GLfloat *> \ |
3202 | (values[0].constData()); \ |
3203 | colfunc(location, count * cols, data); \ |
3204 | } else { \ |
3205 | QVarLengthArray<GLfloat> temp(cols * rows * count); \ |
3206 | for (int index = 0; index < count; ++index) { \ |
3207 | for (int index2 = 0; index2 < (cols * rows); ++index2) { \ |
3208 | temp.data()[cols * rows * index + index2] = \ |
3209 | values[index].constData()[index2]; \ |
3210 | } \ |
3211 | } \ |
3212 | colfunc(location, count * cols, temp.constData()); \ |
3213 | } |
3214 | |
3215 | /*! |
3216 | Sets the uniform variable array at \a location in the current |
3217 | context to the \a count 2x2 matrix elements of \a values. |
3218 | |
3219 | \sa setAttributeValue() |
3220 | */ |
3221 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count) |
3222 | { |
3223 | Q_D(QOpenGLShaderProgram); |
3224 | Q_UNUSED(d); |
3225 | setUniformMatrixArray |
3226 | (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2); |
3227 | } |
3228 | |
3229 | /*! |
3230 | \overload |
3231 | |
3232 | Sets the uniform variable array called \a name in the current |
3233 | context to the \a count 2x2 matrix elements of \a values. |
3234 | |
3235 | \sa setAttributeValue() |
3236 | */ |
3237 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count) |
3238 | { |
3239 | setUniformValueArray(location: uniformLocation(name), values, count); |
3240 | } |
3241 | |
3242 | /*! |
3243 | Sets the uniform variable array at \a location in the current |
3244 | context to the \a count 2x3 matrix elements of \a values. |
3245 | |
3246 | \sa setAttributeValue() |
3247 | */ |
3248 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count) |
3249 | { |
3250 | Q_D(QOpenGLShaderProgram); |
3251 | Q_UNUSED(d); |
3252 | setUniformGenericMatrixArray |
3253 | (d->glfuncs->glUniform3fv, location, values, count, |
3254 | QMatrix2x3, 2, 3); |
3255 | } |
3256 | |
3257 | /*! |
3258 | \overload |
3259 | |
3260 | Sets the uniform variable array called \a name in the current |
3261 | context to the \a count 2x3 matrix elements of \a values. |
3262 | |
3263 | \sa setAttributeValue() |
3264 | */ |
3265 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count) |
3266 | { |
3267 | setUniformValueArray(location: uniformLocation(name), values, count); |
3268 | } |
3269 | |
3270 | /*! |
3271 | Sets the uniform variable array at \a location in the current |
3272 | context to the \a count 2x4 matrix elements of \a values. |
3273 | |
3274 | \sa setAttributeValue() |
3275 | */ |
3276 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count) |
3277 | { |
3278 | Q_D(QOpenGLShaderProgram); |
3279 | Q_UNUSED(d); |
3280 | setUniformGenericMatrixArray |
3281 | (d->glfuncs->glUniform4fv, location, values, count, |
3282 | QMatrix2x4, 2, 4); |
3283 | } |
3284 | |
3285 | /*! |
3286 | \overload |
3287 | |
3288 | Sets the uniform variable array called \a name in the current |
3289 | context to the \a count 2x4 matrix elements of \a values. |
3290 | |
3291 | \sa setAttributeValue() |
3292 | */ |
3293 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count) |
3294 | { |
3295 | setUniformValueArray(location: uniformLocation(name), values, count); |
3296 | } |
3297 | |
3298 | /*! |
3299 | Sets the uniform variable array at \a location in the current |
3300 | context to the \a count 3x2 matrix elements of \a values. |
3301 | |
3302 | \sa setAttributeValue() |
3303 | */ |
3304 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count) |
3305 | { |
3306 | Q_D(QOpenGLShaderProgram); |
3307 | Q_UNUSED(d); |
3308 | setUniformGenericMatrixArray |
3309 | (d->glfuncs->glUniform2fv, location, values, count, |
3310 | QMatrix3x2, 3, 2); |
3311 | } |
3312 | |
3313 | /*! |
3314 | \overload |
3315 | |
3316 | Sets the uniform variable array called \a name in the current |
3317 | context to the \a count 3x2 matrix elements of \a values. |
3318 | |
3319 | \sa setAttributeValue() |
3320 | */ |
3321 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count) |
3322 | { |
3323 | setUniformValueArray(location: uniformLocation(name), values, count); |
3324 | } |
3325 | |
3326 | /*! |
3327 | Sets the uniform variable array at \a location in the current |
3328 | context to the \a count 3x3 matrix elements of \a values. |
3329 | |
3330 | \sa setAttributeValue() |
3331 | */ |
3332 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count) |
3333 | { |
3334 | Q_D(QOpenGLShaderProgram); |
3335 | Q_UNUSED(d); |
3336 | setUniformMatrixArray |
3337 | (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3); |
3338 | } |
3339 | |
3340 | /*! |
3341 | \overload |
3342 | |
3343 | Sets the uniform variable array called \a name in the current |
3344 | context to the \a count 3x3 matrix elements of \a values. |
3345 | |
3346 | \sa setAttributeValue() |
3347 | */ |
3348 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count) |
3349 | { |
3350 | setUniformValueArray(location: uniformLocation(name), values, count); |
3351 | } |
3352 | |
3353 | /*! |
3354 | Sets the uniform variable array at \a location in the current |
3355 | context to the \a count 3x4 matrix elements of \a values. |
3356 | |
3357 | \sa setAttributeValue() |
3358 | */ |
3359 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count) |
3360 | { |
3361 | Q_D(QOpenGLShaderProgram); |
3362 | Q_UNUSED(d); |
3363 | setUniformGenericMatrixArray |
3364 | (d->glfuncs->glUniform4fv, location, values, count, |
3365 | QMatrix3x4, 3, 4); |
3366 | } |
3367 | |
3368 | /*! |
3369 | \overload |
3370 | |
3371 | Sets the uniform variable array called \a name in the current |
3372 | context to the \a count 3x4 matrix elements of \a values. |
3373 | |
3374 | \sa setAttributeValue() |
3375 | */ |
3376 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count) |
3377 | { |
3378 | setUniformValueArray(location: uniformLocation(name), values, count); |
3379 | } |
3380 | |
3381 | /*! |
3382 | Sets the uniform variable array at \a location in the current |
3383 | context to the \a count 4x2 matrix elements of \a values. |
3384 | |
3385 | \sa setAttributeValue() |
3386 | */ |
3387 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count) |
3388 | { |
3389 | Q_D(QOpenGLShaderProgram); |
3390 | Q_UNUSED(d); |
3391 | setUniformGenericMatrixArray |
3392 | (d->glfuncs->glUniform2fv, location, values, count, |
3393 | QMatrix4x2, 4, 2); |
3394 | } |
3395 | |
3396 | /*! |
3397 | \overload |
3398 | |
3399 | Sets the uniform variable array called \a name in the current |
3400 | context to the \a count 4x2 matrix elements of \a values. |
3401 | |
3402 | \sa setAttributeValue() |
3403 | */ |
3404 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count) |
3405 | { |
3406 | setUniformValueArray(location: uniformLocation(name), values, count); |
3407 | } |
3408 | |
3409 | /*! |
3410 | Sets the uniform variable array at \a location in the current |
3411 | context to the \a count 4x3 matrix elements of \a values. |
3412 | |
3413 | \sa setAttributeValue() |
3414 | */ |
3415 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count) |
3416 | { |
3417 | Q_D(QOpenGLShaderProgram); |
3418 | Q_UNUSED(d); |
3419 | setUniformGenericMatrixArray |
3420 | (d->glfuncs->glUniform3fv, location, values, count, |
3421 | QMatrix4x3, 4, 3); |
3422 | } |
3423 | |
3424 | /*! |
3425 | \overload |
3426 | |
3427 | Sets the uniform variable array called \a name in the current |
3428 | context to the \a count 4x3 matrix elements of \a values. |
3429 | |
3430 | \sa setAttributeValue() |
3431 | */ |
3432 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count) |
3433 | { |
3434 | setUniformValueArray(location: uniformLocation(name), values, count); |
3435 | } |
3436 | |
3437 | /*! |
3438 | Sets the uniform variable array at \a location in the current |
3439 | context to the \a count 4x4 matrix elements of \a values. |
3440 | |
3441 | \sa setAttributeValue() |
3442 | */ |
3443 | void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count) |
3444 | { |
3445 | Q_D(QOpenGLShaderProgram); |
3446 | Q_UNUSED(d); |
3447 | setUniformMatrixArray |
3448 | (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4); |
3449 | } |
3450 | |
3451 | /*! |
3452 | \overload |
3453 | |
3454 | Sets the uniform variable array called \a name in the current |
3455 | context to the \a count 4x4 matrix elements of \a values. |
3456 | |
3457 | \sa setAttributeValue() |
3458 | */ |
3459 | void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count) |
3460 | { |
3461 | setUniformValueArray(location: uniformLocation(name), values, count); |
3462 | } |
3463 | |
3464 | /*! |
3465 | Returns the hardware limit for how many vertices a geometry shader |
3466 | can output. |
3467 | */ |
3468 | int QOpenGLShaderProgram::maxGeometryOutputVertices() const |
3469 | { |
3470 | GLint n = 0; |
3471 | Q_D(const QOpenGLShaderProgram); |
3472 | d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, params: &n); |
3473 | return n; |
3474 | } |
3475 | |
3476 | /*! |
3477 | Use this function to specify to OpenGL the number of vertices in |
3478 | a patch to \a count. A patch is a custom OpenGL primitive whose interpretation |
3479 | is entirely defined by the tessellation shader stages. Therefore, calling |
3480 | this function only makes sense when using a QOpenGLShaderProgram |
3481 | containing tessellation stage shaders. When using OpenGL tessellation, |
3482 | the only primitive that can be rendered with \c{glDraw*()} functions is |
3483 | \c{GL_PATCHES}. |
3484 | |
3485 | This is equivalent to calling glPatchParameteri(GL_PATCH_VERTICES, count). |
3486 | |
3487 | \note This modifies global OpenGL state and is not specific to this |
3488 | QOpenGLShaderProgram instance. You should call this in your render |
3489 | function when needed, as QOpenGLShaderProgram will not apply this for |
3490 | you. This is purely a convenience function. |
3491 | |
3492 | \sa patchVertexCount() |
3493 | */ |
3494 | void QOpenGLShaderProgram::setPatchVertexCount(int count) |
3495 | { |
3496 | Q_D(QOpenGLShaderProgram); |
3497 | d->glfuncs->glPatchParameteri(GL_PATCH_VERTICES, value: count); |
3498 | } |
3499 | |
3500 | /*! |
3501 | Returns the number of vertices per-patch to be used when rendering. |
3502 | |
3503 | \note This returns the global OpenGL state value. It is not specific to |
3504 | this QOpenGLShaderProgram instance. |
3505 | |
3506 | \sa setPatchVertexCount() |
3507 | */ |
3508 | int QOpenGLShaderProgram::patchVertexCount() const |
3509 | { |
3510 | int patchVertices = 0; |
3511 | Q_D(const QOpenGLShaderProgram); |
3512 | d->glfuncs->glGetIntegerv(GL_PATCH_VERTICES, params: &patchVertices); |
3513 | return patchVertices; |
3514 | } |
3515 | |
3516 | /*! |
3517 | Sets the default outer tessellation levels to be used by the tessellation |
3518 | primitive generator in the event that the tessellation control shader |
3519 | does not output them to \a levels. For more details on OpenGL and Tessellation |
3520 | shaders see \l{OpenGL Tessellation Shaders}. |
3521 | |
3522 | The \a levels argument should be a QList consisting of 4 floats. Not all |
3523 | of the values make sense for all tessellation modes. If you specify a vector with |
3524 | fewer than 4 elements, the remaining elements will be given a default value of 1. |
3525 | |
3526 | \note This modifies global OpenGL state and is not specific to this |
3527 | QOpenGLShaderProgram instance. You should call this in your render |
3528 | function when needed, as QOpenGLShaderProgram will not apply this for |
3529 | you. This is purely a convenience function. |
3530 | |
3531 | \note This function is only available with OpenGL >= 4.0 and is not supported |
3532 | with OpenGL ES 3.2. |
3533 | |
3534 | \sa defaultOuterTessellationLevels(), setDefaultInnerTessellationLevels() |
3535 | */ |
3536 | void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QList<float> &levels) |
3537 | { |
3538 | #if !QT_CONFIG(opengles2) |
3539 | Q_D(QOpenGLShaderProgram); |
3540 | if (d->tessellationFuncs) { |
3541 | QList<float> tessLevels = levels; |
3542 | |
3543 | // Ensure we have the required 4 outer tessellation levels |
3544 | // Use default of 1 for missing entries (same as spec) |
3545 | const int argCount = 4; |
3546 | if (tessLevels.size() < argCount) { |
3547 | tessLevels.reserve(asize: argCount); |
3548 | for (int i = tessLevels.size(); i < argCount; ++i) |
3549 | tessLevels.append(t: 1.0f); |
3550 | } |
3551 | d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, values: tessLevels.data()); |
3552 | } |
3553 | #else |
3554 | Q_UNUSED(levels); |
3555 | #endif |
3556 | } |
3557 | |
3558 | /*! |
3559 | Returns the default outer tessellation levels to be used by the tessellation |
3560 | primitive generator in the event that the tessellation control shader |
3561 | does not output them. For more details on OpenGL and Tessellation shaders see |
3562 | \l{OpenGL Tessellation Shaders}. |
3563 | |
3564 | Returns a QList of floats describing the outer tessellation levels. The vector |
3565 | will always have four elements but not all of them make sense for every mode |
3566 | of tessellation. |
3567 | |
3568 | \note This returns the global OpenGL state value. It is not specific to |
3569 | this QOpenGLShaderProgram instance. |
3570 | |
3571 | \note This function is only supported with OpenGL >= 4.0 and will not |
3572 | return valid results with OpenGL ES 3.2. |
3573 | |
3574 | \sa setDefaultOuterTessellationLevels(), defaultInnerTessellationLevels() |
3575 | */ |
3576 | QList<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const |
3577 | { |
3578 | #if !QT_CONFIG(opengles2) |
3579 | QList<float> tessLevels(4, 1.0f); |
3580 | Q_D(const QOpenGLShaderProgram); |
3581 | if (d->tessellationFuncs) |
3582 | d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, params: tessLevels.data()); |
3583 | return tessLevels; |
3584 | #else |
3585 | return QList<float>(); |
3586 | #endif |
3587 | } |
3588 | |
3589 | /*! |
3590 | Sets the default outer tessellation levels to be used by the tessellation |
3591 | primitive generator in the event that the tessellation control shader |
3592 | does not output them to \a levels. For more details on OpenGL and Tessellation shaders see |
3593 | \l{OpenGL Tessellation Shaders}. |
3594 | |
3595 | The \a levels argument should be a QList consisting of 2 floats. Not all |
3596 | of the values make sense for all tessellation modes. If you specify a vector with |
3597 | fewer than 2 elements, the remaining elements will be given a default value of 1. |
3598 | |
3599 | \note This modifies global OpenGL state and is not specific to this |
3600 | QOpenGLShaderProgram instance. You should call this in your render |
3601 | function when needed, as QOpenGLShaderProgram will not apply this for |
3602 | you. This is purely a convenience function. |
3603 | |
3604 | \note This function is only available with OpenGL >= 4.0 and is not supported |
3605 | with OpenGL ES 3.2. |
3606 | |
3607 | \sa defaultInnerTessellationLevels(), setDefaultOuterTessellationLevels() |
3608 | */ |
3609 | void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QList<float> &levels) |
3610 | { |
3611 | #if !QT_CONFIG(opengles2) |
3612 | Q_D(QOpenGLShaderProgram); |
3613 | if (d->tessellationFuncs) { |
3614 | QList<float> tessLevels = levels; |
3615 | |
3616 | // Ensure we have the required 2 inner tessellation levels |
3617 | // Use default of 1 for missing entries (same as spec) |
3618 | const int argCount = 2; |
3619 | if (tessLevels.size() < argCount) { |
3620 | tessLevels.reserve(asize: argCount); |
3621 | for (int i = tessLevels.size(); i < argCount; ++i) |
3622 | tessLevels.append(t: 1.0f); |
3623 | } |
3624 | d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, values: tessLevels.data()); |
3625 | } |
3626 | #else |
3627 | Q_UNUSED(levels); |
3628 | #endif |
3629 | } |
3630 | |
3631 | /*! |
3632 | Returns the default inner tessellation levels to be used by the tessellation |
3633 | primitive generator in the event that the tessellation control shader |
3634 | does not output them. For more details on OpenGL and Tessellation shaders see |
3635 | \l{OpenGL Tessellation Shaders}. |
3636 | |
3637 | Returns a QList of floats describing the inner tessellation levels. The vector |
3638 | will always have two elements but not all of them make sense for every mode |
3639 | of tessellation. |
3640 | |
3641 | \note This returns the global OpenGL state value. It is not specific to |
3642 | this QOpenGLShaderProgram instance. |
3643 | |
3644 | \note This function is only supported with OpenGL >= 4.0 and will not |
3645 | return valid results with OpenGL ES 3.2. |
3646 | |
3647 | \sa setDefaultInnerTessellationLevels(), defaultOuterTessellationLevels() |
3648 | */ |
3649 | QList<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const |
3650 | { |
3651 | #if !QT_CONFIG(opengles2) |
3652 | QList<float> tessLevels(2, 1.0f); |
3653 | Q_D(const QOpenGLShaderProgram); |
3654 | if (d->tessellationFuncs) |
3655 | d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, params: tessLevels.data()); |
3656 | return tessLevels; |
3657 | #else |
3658 | return QList<float>(); |
3659 | #endif |
3660 | } |
3661 | |
3662 | |
3663 | /*! |
3664 | Returns \c true if shader programs written in the OpenGL Shading |
3665 | Language (GLSL) are supported on this system; false otherwise. |
3666 | |
3667 | The \a context is used to resolve the GLSL extensions. |
3668 | If \a context is \nullptr, then QOpenGLContext::currentContext() |
3669 | is used. |
3670 | */ |
3671 | bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context) |
3672 | { |
3673 | if (!context) |
3674 | context = QOpenGLContext::currentContext(); |
3675 | if (!context) |
3676 | return false; |
3677 | return QOpenGLFunctions(context).hasOpenGLFeature(feature: QOpenGLFunctions::Shaders); |
3678 | } |
3679 | |
3680 | /*! |
3681 | \internal |
3682 | */ |
3683 | void QOpenGLShaderProgram::shaderDestroyed() |
3684 | { |
3685 | Q_D(QOpenGLShaderProgram); |
3686 | QOpenGLShader *shader = qobject_cast<QOpenGLShader *>(object: sender()); |
3687 | if (shader && !d->removingShaders) |
3688 | removeShader(shader); |
3689 | } |
3690 | |
3691 | /*! |
3692 | Returns \c true if shader programs of type \a type are supported on |
3693 | this system; false otherwise. |
3694 | |
3695 | The \a context is used to resolve the GLSL extensions. |
3696 | If \a context is \nullptr, then QOpenGLContext::currentContext() |
3697 | is used. |
3698 | */ |
3699 | bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context) |
3700 | { |
3701 | if (!context) |
3702 | context = QOpenGLContext::currentContext(); |
3703 | if (!context) |
3704 | return false; |
3705 | |
3706 | if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0) |
3707 | return false; |
3708 | |
3709 | if (type & QOpenGLShader::Geometry) |
3710 | return supportsGeometry(f: context->format()); |
3711 | else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) |
3712 | return supportsTessellation(f: context->format()); |
3713 | else if (type & QOpenGLShader::Compute) |
3714 | return supportsCompute(f: context->format()); |
3715 | |
3716 | // Unconditional support of vertex and fragment shaders implicitly assumes |
3717 | // a minimum OpenGL version of 2.0 |
3718 | return true; |
3719 | } |
3720 | |
3721 | bool QOpenGLShaderProgramPrivate::isCacheDisabled() const |
3722 | { |
3723 | static QOpenGLProgramBinarySupportCheckWrapper binSupportCheck; |
3724 | return !binSupportCheck.get(context: QOpenGLContext::currentContext())->isSupported(); |
3725 | } |
3726 | |
3727 | bool QOpenGLShaderProgramPrivate::compileCacheable() |
3728 | { |
3729 | Q_Q(QOpenGLShaderProgram); |
3730 | for (const QOpenGLProgramBinaryCache::ShaderDesc &shader : std::as_const(t&: binaryProgram.shaders)) { |
3731 | auto s = std::make_unique<QOpenGLShader>(args: qt_shaderStageToType(stage: shader.stage), args: q); |
3732 | if (!s->compileSourceCode(source: shader.source)) { |
3733 | log = s->log(); |
3734 | return false; |
3735 | } |
3736 | anonShaders.append(t: s.release()); |
3737 | if (!q->addShader(shader: anonShaders.last())) |
3738 | return false; |
3739 | } |
3740 | return true; |
3741 | } |
3742 | |
3743 | bool QOpenGLShaderProgramPrivate::linkBinary() |
3744 | { |
3745 | static QOpenGLProgramBinaryCache binCache; |
3746 | |
3747 | Q_Q(QOpenGLShaderProgram); |
3748 | |
3749 | const QByteArray cacheKey = binaryProgram.cacheKey(); |
3750 | if (lcOpenGLProgramDiskCache().isEnabled(type: QtDebugMsg)) |
3751 | qCDebug(lcOpenGLProgramDiskCache, "program with %d shaders, cache key %s" , |
3752 | int(binaryProgram.shaders.size()), cacheKey.constData()); |
3753 | |
3754 | bool needsCompile = true; |
3755 | if (binCache.load(cacheKey, programId: q->programId())) { |
3756 | qCDebug(lcOpenGLProgramDiskCache, "Program binary received from cache" ); |
3757 | needsCompile = false; |
3758 | } |
3759 | |
3760 | bool needsSave = false; |
3761 | if (needsCompile) { |
3762 | qCDebug(lcOpenGLProgramDiskCache, "Program binary not in cache, compiling" ); |
3763 | if (compileCacheable()) |
3764 | needsSave = true; |
3765 | else |
3766 | return false; |
3767 | } |
3768 | |
3769 | linkBinaryRecursion = true; |
3770 | bool ok = q->link(); |
3771 | linkBinaryRecursion = false; |
3772 | if (ok && needsSave) |
3773 | binCache.save(cacheKey, programId: q->programId()); |
3774 | |
3775 | return ok; |
3776 | } |
3777 | |
3778 | QT_END_NAMESPACE |
3779 | |
3780 | #include "moc_qopenglshaderprogram.cpp" |
3781 | |