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