Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qopenglshaderprogram.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "private/qopenglcontext_p.h"
7#include <QtOpenGL/QOpenGLVersionFunctionsFactory>
8#include <QtCore/private/qobject_p.h>
9#include <QtCore/qdebug.h>
10#include <QtCore/qfile.h>
11#include <QtCore/qlist.h>
12#include <QtCore/qloggingcategory.h>
13#include <QtCore/qvarlengtharray.h>
14#include <QtGui/private/qopenglprogrambinarycache_p.h>
15#include <QtGui/qtransform.h>
16#include <QtGui/QColor>
17#include <QtGui/QSurfaceFormat>
18
19#if !QT_CONFIG(opengles2)
20#include <QtOpenGL/qopenglfunctions_4_0_core.h>
21#endif
22
23#include <algorithm>
24#include <memory>
25
27
28using namespace Qt::StringLiterals;
29
148// For GLES 3.1/3.2
149#ifndef GL_GEOMETRY_SHADER
150#define GL_GEOMETRY_SHADER 0x8DD9
151#endif
152#ifndef GL_TESS_CONTROL_SHADER
153#define GL_TESS_CONTROL_SHADER 0x8E88
154#endif
155#ifndef GL_TESS_EVALUATION_SHADER
156#define GL_TESS_EVALUATION_SHADER 0x8E87
157#endif
158#ifndef GL_COMPUTE_SHADER
159#define GL_COMPUTE_SHADER 0x91B9
160#endif
161#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES
162#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
163#endif
164#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
165#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
166#endif
167#ifndef GL_PATCH_VERTICES
168#define GL_PATCH_VERTICES 0x8E72
169#endif
170#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL
171#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
172#endif
173#ifndef GL_PATCH_DEFAULT_INNER_LEVEL
174#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
175#endif
176
177#if !QT_CONFIG(opengles2)
178static inline bool isFormatGLES(const QSurfaceFormat &f)
179{
180 return (f.renderableType() == QSurfaceFormat::OpenGLES);
181}
182#endif
183
184static inline bool supportsGeometry(const QSurfaceFormat &f)
185{
186 return f.version() >= qMakePair(3, 2);
187}
188
189static inline bool supportsCompute(const QSurfaceFormat &f)
190{
191#if !QT_CONFIG(opengles2)
192 if (!isFormatGLES(f))
193 return f.version() >= qMakePair(4, 3);
194 else
195 return f.version() >= qMakePair(3, 1);
196#else
197 return f.version() >= qMakePair(3, 1);
198#endif
199}
200
201static inline bool supportsTessellation(const QSurfaceFormat &f)
202{
203#if !QT_CONFIG(opengles2)
204 if (!isFormatGLES(f))
205 return f.version() >= qMakePair(4, 0);
206 else
207 return f.version() >= qMakePair(3, 2);
208#else
209 return f.version() >= qMakePair(3, 2);
210#endif
211}
212
214{
215 Q_DECLARE_PUBLIC(QOpenGLShader)
216public:
234
236 QOpenGLShader::ShaderType shaderType;
239
241
242 // Support for geometry shaders
244 // Support for tessellation shaders
246 // Support for compute shaders
248
249
250 bool create();
251 bool compile(QOpenGLShader *q);
252 void deleteShader();
253};
254
255namespace {
256 void freeShaderFunc(QOpenGLFunctions *funcs, GLuint id)
257 {
258 funcs->glDeleteShader(id);
259 }
260}
261
268
295
297{
299 if (!shader)
300 return false;
301
302 // Try to compile shader
304 GLint value = 0;
305
306 // Get compilation status
308 compiled = (value != 0);
309
310 if (!compiled) {
311 // Compilation failed, try to provide some information about the failure
312 QString name = q->objectName();
313
314 const char *types[] = {
315 "Fragment",
316 "Vertex",
317 "Geometry",
318 "Tessellation Control",
319 "Tessellation Evaluation",
320 "Compute",
321 ""
322 };
323
324 const char *type = types[6];
325 switch (shaderType) {
327 type = types[0]; break;
329 type = types[1]; break;
331 type = types[2]; break;
333 type = types[3]; break;
335 type = types[4]; break;
337 type = types[5]; break;
338 }
339
340 // Get info and source code lengths
341 GLint infoLogLength = 0;
342 GLint sourceCodeLength = 0;
343 char *logBuffer = nullptr;
344 char *sourceCodeBuffer = nullptr;
345
346 // Get the compilation info log
348
349 if (infoLogLength > 1) {
350 GLint temp;
351 logBuffer = new char [infoLogLength];
352 glfuncs->glGetShaderInfoLog(shader, infoLogLength, &temp, logBuffer);
353 }
354
355 // Get the source code
357
358 if (sourceCodeLength > 1) {
359 GLint temp;
360 sourceCodeBuffer = new char [sourceCodeLength];
361 glfuncs->glGetShaderSource(shader, sourceCodeLength, &temp, sourceCodeBuffer);
362 }
363
364 if (logBuffer)
365 log = QString::fromLatin1(logBuffer);
366 else
367 log = u"failed"_s;
368
369 if (name.isEmpty())
370 qWarning("QOpenGLShader::compile(%s): %s", type, qPrintable(log));
371 else
372 qWarning("QOpenGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log));
373
374 // Dump the source code if we got it
375 if (sourceCodeBuffer) {
376 qWarning("*** Problematic %s shader source code ***\n"
377 "%ls\n"
378 "***",
379 type, qUtf16Printable(QString::fromLatin1(sourceCodeBuffer)));
380 }
381
382 // Cleanup
383 delete [] logBuffer;
384 delete [] sourceCodeBuffer;
385 }
386
387 return compiled;
388}
389
391{
392 if (shaderGuard) {
393 shaderGuard->free();
394 shaderGuard = nullptr;
395 }
396}
397
410QOpenGLShader::QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent)
411 : QObject(*new QOpenGLShaderPrivate(QOpenGLContext::currentContext(), type), parent)
412{
413 Q_D(QOpenGLShader);
414 d->create();
415}
416
425
429QOpenGLShader::ShaderType QOpenGLShader::shaderType() const
430{
431 Q_D(const QOpenGLShader);
432 return d->shaderType;
433}
434
435static const char qualifierDefines[] =
436 "#define lowp\n"
437 "#define mediump\n"
438 "#define highp\n";
439
440#if QT_CONFIG(opengles2) && !defined(QT_OPENGL_FORCE_SHADER_DEFINES)
441// The "highp" qualifier doesn't exist in fragment shaders
442// on all ES platforms. When it doesn't exist, use "mediump".
443#define QOpenGL_REDEFINE_HIGHP 1
444static const char redefineHighp[] =
445 "#ifndef GL_FRAGMENT_PRECISION_HIGH\n"
446 "#define highp mediump\n"
447 "#endif\n";
448#endif
449
450// Boiler-plate header to have the layout attributes available we need later
451static const char blendEquationAdvancedHeader[] =
452 "#ifdef GL_KHR_blend_equation_advanced\n"
453 "#extension GL_ARB_fragment_coord_conventions : enable\n"
454 "#extension GL_KHR_blend_equation_advanced : enable\n"
455 "#endif\n";
456
458{
459 constexpr QVersionDirectivePosition(int position = 0, int line = -1)
461 , line(line)
462 {
463 }
464
465 constexpr bool hasPosition() const
466 {
467 return position > 0;
468 }
469
470 const int position;
471 const int line;
472};
473
475{
477
478 // According to the GLSL spec the #version directive must not be
479 // preceded by anything but whitespace and comments.
480 // In order to not get confused by #version directives within a
481 // multiline comment, we need to do some minimal comment parsing
482 // while searching for the directive.
483 enum {
484 Normal,
485 StartOfLine,
486 PreprocessorDirective,
487 CommentStarting,
488 MultiLineComment,
489 SingleLineComment,
490 CommentEnding
491 } state = StartOfLine;
492
493 const char *c = source;
494 while (*c) {
495 switch (state) {
496 case PreprocessorDirective:
497 if (*c == ' ' || *c == '\t')
498 break;
499 if (!strncmp(c, "version", strlen("version"))) {
500 // Found version directive
501 c += strlen("version");
502 while (*c && *c != '\n')
503 ++c;
504 int splitPosition = c - source + 1;
505 int linePosition = int(std::count(source, c, '\n')) + 1;
506 return QVersionDirectivePosition(splitPosition, linePosition);
507 } else if (*c == '/')
508 state = CommentStarting;
509 else if (*c == '\n')
510 state = StartOfLine;
511 else
512 state = Normal;
513 break;
514 case StartOfLine:
515 if (*c == ' ' || *c == '\t')
516 break;
517 else if (*c == '#') {
518 state = PreprocessorDirective;
519 break;
520 }
521 state = Normal;
523 case Normal:
524 if (*c == '/')
525 state = CommentStarting;
526 else if (*c == '\n')
527 state = StartOfLine;
528 break;
529 case CommentStarting:
530 if (*c == '*')
531 state = MultiLineComment;
532 else if (*c == '/')
533 state = SingleLineComment;
534 else
535 state = Normal;
536 break;
537 case MultiLineComment:
538 if (*c == '*')
539 state = CommentEnding;
540 break;
541 case SingleLineComment:
542 if (*c == '\n')
543 state = Normal;
544 break;
545 case CommentEnding:
546 if (*c == '/')
547 state = Normal;
548 else if (*c != u'*')
549 state = MultiLineComment;
550 break;
551 }
552 ++c;
553 }
554
555 return QVersionDirectivePosition(0, 1);
556}
557
565{
566 Q_D(QOpenGLShader);
567 // This method breaks the shader code into two parts:
568 // 1. Up to and including an optional #version directive.
569 // 2. The rest.
570 // If a #version directive exists, qualifierDefines and redefineHighp
571 // are inserted after. Otherwise they are inserted right at the start.
572 // In both cases a #line directive is appended in order to compensate
573 // for line number changes in case of compiler errors.
574
575 if (d->shaderGuard && d->shaderGuard->id() && source) {
576 const QVersionDirectivePosition versionDirectivePosition = findVersionDirectivePosition(source);
577
578 QVarLengthArray<const char *, 5> sourceChunks;
579 QVarLengthArray<GLint, 5> sourceChunkLengths;
581
582 if (versionDirectivePosition.hasPosition()) {
583 // Append source up to and including the #version directive
584 sourceChunks.append(source);
585 sourceChunkLengths.append(GLint(versionDirectivePosition.position));
586 } else {
587 // QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always
588 if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) {
589 const char *vendor = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VENDOR));
590 if (vendor && !strcmp(vendor, "Intel")) {
591 static const char version110[] = "#version 110\n";
592 sourceChunks.append(version110);
593 sourceChunkLengths.append(GLint(sizeof(version110)) - 1);
594 }
595 }
596 }
597 if (d->shaderType == Fragment) {
598 sourceChunks.append(blendEquationAdvancedHeader);
599 sourceChunkLengths.append(GLint(sizeof(blendEquationAdvancedHeader) - 1));
600 }
601
602 // The precision qualifiers are useful on OpenGL/ES systems,
603 // but usually not present on desktop systems.
604 const QSurfaceFormat currentSurfaceFormat = ctx->format();
606 if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL
607 || ctx_d->workaround_missingPrecisionQualifiers
608#ifdef QT_OPENGL_FORCE_SHADER_DEFINES
609 || true
610#endif
611 ) {
612 sourceChunks.append(qualifierDefines);
613 sourceChunkLengths.append(GLint(sizeof(qualifierDefines) - 1));
614 }
615
616#ifdef QOpenGL_REDEFINE_HIGHP
617 if (d->shaderType == Fragment && !ctx_d->workaround_missingPrecisionQualifiers
618 && QOpenGLContext::currentContext()->isOpenGLES()) {
619 sourceChunks.append(redefineHighp);
620 sourceChunkLengths.append(GLint(sizeof(redefineHighp) - 1));
621 }
622#endif
623
624 QByteArray lineDirective;
625 // #line is rejected by some drivers:
626 // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel"
627 const char *version = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VERSION));
628 if (!version || !strstr(version, "2.1 Mesa 8")) {
629 // Append #line directive in order to compensate for text insertion
630 lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8();
631 sourceChunks.append(lineDirective.constData());
632 sourceChunkLengths.append(GLint(lineDirective.size()));
633 }
634
635 // Append rest of shader code
636 sourceChunks.append(source + versionDirectivePosition.position);
637 sourceChunkLengths.append(GLint(qstrlen(source + versionDirectivePosition.position)));
638
639 d->glfuncs->glShaderSource(d->shaderGuard->id(), sourceChunks.size(), sourceChunks.data(), sourceChunkLengths.data());
640 return d->compile(this);
641 } else {
642 return false;
643 }
644}
645
655{
656 return compileSourceCode(source.constData());
657}
658
668{
669 return compileSourceCode(source.toLatin1().constData());
670}
671
680{
682 if (!file.open(QFile::ReadOnly)) {
683 qWarning() << "QOpenGLShader: Unable to open file" << fileName;
684 return false;
685 }
686
688 return compileSourceCode(contents.constData());
689}
690
697{
698 Q_D(const QOpenGLShader);
699 GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0;
700 if (!shader)
701 return QByteArray();
702 GLint size = 0;
703 d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &size);
704 if (size <= 0)
705 return QByteArray();
706 GLint len = 0;
707 char *source = new char [size];
708 d->glfuncs->glGetShaderSource(shader, size, &len, source);
710 delete [] source;
711 return src;
712}
713
720{
721 Q_D(const QOpenGLShader);
722 return d->compiled;
723}
724
731{
732 Q_D(const QOpenGLShader);
733 return d->log;
734}
735
742{
743 Q_D(const QOpenGLShader);
744 return d->shaderGuard ? d->shaderGuard->id() : 0;
745}
746
748{
749 Q_DECLARE_PUBLIC(QOpenGLShaderProgram)
750public:
764
766 bool linked;
767 bool inited;
769
771 QList<QOpenGLShader *> shaders;
772 QList<QOpenGLShader *> anonShaders;
773
775#if !QT_CONFIG(opengles2)
776 // for tessellation features not in GLES 3.2
778#endif
779
780 bool hasShader(QOpenGLShader::ShaderType type) const;
781
783 bool isCacheDisabled() const;
784 bool compileCacheable();
785 bool linkBinary();
786
788};
789
790namespace {
791 void freeProgramFunc(QOpenGLFunctions *funcs, GLuint id)
792 {
793 funcs->glDeleteProgram(id);
794 }
795}
796
797
804
805bool QOpenGLShaderProgramPrivate::hasShader(QOpenGLShader::ShaderType type) const
806{
807 for (QOpenGLShader *shader : shaders) {
808 if (shader->shaderType() == type)
809 return true;
810 }
811 return false;
812}
813
826
833
850{
851 return init();
852}
853
854bool QOpenGLShaderProgram::init()
855{
857 if ((d->programGuard && d->programGuard->id()) || d->inited)
858 return true;
859 d->inited = true;
861 if (!context)
862 return false;
863 d->glfuncs->initializeOpenGLFunctions();
864
865#if !QT_CONFIG(opengles2)
866 if (!context->isOpenGLES() && context->format().version() >= qMakePair(4, 0)) {
867 d->tessellationFuncs = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_0_Core>(context);
868 d->tessellationFuncs->initializeOpenGLFunctions();
869 }
870#endif
871
872 GLuint program = d->glfuncs->glCreateProgram();
873 if (!program) {
874 qWarning("QOpenGLShaderProgram: could not create shader program");
875 return false;
876 }
877 if (d->programGuard)
878 delete d->programGuard;
879 d->programGuard = new QOpenGLSharedResourceGuard(context, program, freeProgramFunc);
880 return true;
881}
882
896{
898 if (!init())
899 return false;
900 if (d->shaders.contains(shader))
901 return true; // Already added to this shader program.
902 if (d->programGuard && d->programGuard->id() && shader) {
903 if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id())
904 return false;
905 if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) {
906 qWarning("QOpenGLShaderProgram::addShader: Program and shader are not associated with same context.");
907 return false;
908 }
909 d->glfuncs->glAttachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
910 d->linked = false; // Program needs to be relinked.
911 d->shaders.append(shader);
912 connect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
913 return true;
914 } else {
915 return false;
916 }
917}
918
932bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
933{
935 if (!init())
936 return false;
938 if (!shader->compileSourceCode(source)) {
939 d->log = shader->log();
940 delete shader;
941 return false;
942 }
943 d->anonShaders.append(shader);
944 return addShader(shader);
945}
946
963{
964 return addShaderFromSourceCode(type, source.constData());
965}
966
983{
984 return addShaderFromSourceCode(type, source.toLatin1().constData());
985}
986
1000 (QOpenGLShader::ShaderType type, const QString& fileName)
1001{
1003 if (!init())
1004 return false;
1005 QOpenGLShader *shader = new QOpenGLShader(type, this);
1006 if (!shader->compileSourceFile(fileName)) {
1007 d->log = shader->log();
1008 delete shader;
1009 return false;
1010 }
1011 d->anonShaders.append(shader);
1012 return addShader(shader);
1013}
1014
1033bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
1034{
1036 if (!init())
1037 return false;
1038 if (d->isCacheDisabled())
1040
1042}
1043
1062
1063static inline QOpenGLShader::ShaderType qt_shaderStageToType(QShader::Stage stage)
1064{
1065 switch (stage) {
1067 return QOpenGLShader::Vertex;
1078 }
1079 return QOpenGLShader::Vertex;
1080}
1081
1103{
1105 if (!init())
1106 return false;
1107 if (d->isCacheDisabled())
1109
1111 return true;
1112}
1113
1131{
1133 if (!init())
1134 return false;
1135 if (d->isCacheDisabled())
1137
1138 return addCacheableShaderFromSourceCode(type, source.toUtf8().constData());
1139}
1140
1160{
1162 if (!init())
1163 return false;
1164 if (d->isCacheDisabled())
1166
1168 // NB! It could be tempting to defer reading the file contents and just
1169 // hash the filename as the cache key, perhaps combined with last-modified
1170 // timestamp checks. However, this would raise a number of issues (no
1171 // timestamps for files in the resource system; preference for global, not
1172 // per-application cache items (where filenames may clash); resource-based
1173 // shaders from libraries like Qt Quick; etc.), so just avoid it.
1174 QFile f(fileName);
1176 shader.source = f.readAll();
1177 f.close();
1178 } else {
1179 qWarning("QOpenGLShaderProgram: Unable to open file %s", qPrintable(fileName));
1180 return false;
1181 }
1182 d->binaryProgram.shaders.append(shader);
1183 return true;
1184}
1185
1194{
1196 if (d->programGuard && d->programGuard->id()
1197 && shader && shader->d_func()->shaderGuard)
1198 {
1199 d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
1200 }
1201 d->linked = false; // Program needs to be relinked.
1202 if (shader) {
1203 d->shaders.removeAll(shader);
1204 d->anonShaders.removeAll(shader);
1205 disconnect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
1206 }
1207}
1208
1215QList<QOpenGLShader *> QOpenGLShaderProgram::shaders() const
1216{
1217 Q_D(const QOpenGLShaderProgram);
1218 return d->shaders;
1219}
1220
1230{
1232 d->removingShaders = true;
1233 for (QOpenGLShader *shader : std::as_const(d->shaders)) {
1234 if (d->programGuard && d->programGuard->id()
1235 && shader && shader->d_func()->shaderGuard)
1236 {
1237 d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
1238 }
1239 }
1240 // Delete shader objects that were created anonymously.
1241 qDeleteAll(d->anonShaders);
1242 d->shaders.clear();
1243 d->anonShaders.clear();
1244 d->binaryProgram = QOpenGLProgramBinaryCache::ProgramDesc();
1245 d->linked = false; // Program needs to be relinked.
1246 d->removingShaders = false;
1247}
1248
1274{
1276 GLuint program = d->programGuard ? d->programGuard->id() : 0;
1277 if (!program)
1278 return false;
1279
1280 if (!d->linkBinaryRecursion && d->shaders.isEmpty() && !d->binaryProgram.shaders.isEmpty())
1281 return d->linkBinary();
1282
1283 GLint value;
1284 if (d->shaders.isEmpty()) {
1285 // If there are no explicit shaders, then it is possible that the
1286 // application added a program binary with glProgramBinaryOES(), or
1287 // otherwise populated the shaders itself. This is also the case when
1288 // we are recursively called back from linkBinary() after a successful
1289 // glProgramBinary(). Check to see if the program is already linked and
1290 // bail out if so.
1291 value = 0;
1292 d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
1293 d->linked = (value != 0);
1294 if (d->linked)
1295 return true;
1296 }
1297
1298 d->glfuncs->glLinkProgram(program);
1299 value = 0;
1300 d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
1301 d->linked = (value != 0);
1302 value = 0;
1303 d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
1304 d->log = QString();
1305 if (value > 1) {
1306 char *logbuf = new char [value];
1307 GLint len;
1308 d->glfuncs->glGetProgramInfoLog(program, value, &len, logbuf);
1309 d->log = QString::fromLatin1(logbuf);
1310 if (!d->linked && !d->linkBinaryRecursion) {
1312 if (name.isEmpty())
1313 qWarning("QOpenGLShader::link: %ls", qUtf16Printable(d->log));
1314 else
1315 qWarning("QOpenGLShader::link[%ls]: %ls", qUtf16Printable(name), qUtf16Printable(d->log));
1316 }
1317 delete [] logbuf;
1318 }
1319 return d->linked;
1320}
1321
1328{
1329 Q_D(const QOpenGLShaderProgram);
1330 return d->linked;
1331}
1332
1340{
1341 Q_D(const QOpenGLShaderProgram);
1342 return d->log;
1343}
1344
1356{
1358 GLuint program = d->programGuard ? d->programGuard->id() : 0;
1359 if (!program)
1360 return false;
1361 if (!d->linked && !link())
1362 return false;
1363#ifndef QT_NO_DEBUG
1364 if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) {
1365 qWarning("QOpenGLShaderProgram::bind: program is not valid in the current context.");
1366 return false;
1367 }
1368#endif
1369 d->glfuncs->glUseProgram(program);
1370 return true;
1371}
1372
1380{
1382#ifndef QT_NO_DEBUG
1383 if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup())
1384 qWarning("QOpenGLShaderProgram::release: program is not valid in the current context.");
1385#endif
1386 d->glfuncs->glUseProgram(0);
1387}
1388
1395{
1396 Q_D(const QOpenGLShaderProgram);
1397 GLuint id = d->programGuard ? d->programGuard->id() : 0;
1398 if (id)
1399 return id;
1400
1401 // Create the identifier if we don't have one yet. This is for
1402 // applications that want to create the attached shader configuration
1403 // themselves, particularly those using program binaries.
1404 if (!const_cast<QOpenGLShaderProgram *>(this)->init())
1405 return 0;
1406 return d->programGuard ? d->programGuard->id() : 0;
1407}
1408
1421{
1423 if (!init() || !d->programGuard || !d->programGuard->id())
1424 return;
1425 d->glfuncs->glBindAttribLocation(d->programGuard->id(), location, name);
1426 d->linked = false; // Program needs to be relinked.
1427}
1428
1446
1461{
1462 bindAttributeLocation(name.toLatin1().constData(), location);
1463}
1464
1473{
1474 Q_D(const QOpenGLShaderProgram);
1475 if (d->linked && d->programGuard && d->programGuard->id()) {
1476 return d->glfuncs->glGetAttribLocation(d->programGuard->id(), name);
1477 } else {
1478 qWarning("QOpenGLShaderProgram::attributeLocation(%s): shader program is not linked", name);
1479 return -1;
1480 }
1481}
1482
1493{
1494 return attributeLocation(name.constData());
1495}
1496
1507{
1508 return attributeLocation(name.toLatin1().constData());
1509}
1510
1517{
1519 if (location != -1)
1520 d->glfuncs->glVertexAttrib1fv(location, &value);
1521}
1522
1534
1542{
1544 if (location != -1) {
1545 GLfloat values[2] = {x, y};
1546 d->glfuncs->glVertexAttrib2fv(location, values);
1547 }
1548}
1549
1562
1571{
1573 Q_UNUSED(d);
1574 if (location != -1) {
1575 GLfloat values[3] = {x, y, z};
1576 d->glfuncs->glVertexAttrib3fv(location, values);
1577 }
1578}
1579
1593
1602{
1604 if (location != -1) {
1605 GLfloat values[4] = {x, y, z, w};
1606 d->glfuncs->glVertexAttrib4fv(location, values);
1607 }
1608}
1609
1623
1630{
1632 if (location != -1)
1633 d->glfuncs->glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
1634}
1635
1647
1654{
1656 Q_UNUSED(d);
1657 if (location != -1)
1658 d->glfuncs->glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
1659}
1660
1672
1679{
1681 Q_UNUSED(d);
1682 if (location != -1)
1683 d->glfuncs->glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
1684}
1685
1697
1704{
1706 Q_UNUSED(d);
1707 if (location != -1) {
1708 GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()),
1709 GLfloat(value.blueF()), GLfloat(value.alphaF())};
1710 d->glfuncs->glVertexAttrib4fv(location, values);
1711 }
1712}
1713
1725
1736 (int location, const GLfloat *values, int columns, int rows)
1737{
1739 Q_UNUSED(d);
1740 if (rows < 1 || rows > 4) {
1741 qWarning("QOpenGLShaderProgram::setAttributeValue: rows %d not supported", rows);
1742 return;
1743 }
1744 if (location != -1) {
1745 while (columns-- > 0) {
1746 if (rows == 1)
1747 d->glfuncs->glVertexAttrib1fv(location, values);
1748 else if (rows == 2)
1749 d->glfuncs->glVertexAttrib2fv(location, values);
1750 else if (rows == 3)
1751 d->glfuncs->glVertexAttrib3fv(location, values);
1752 else
1753 d->glfuncs->glVertexAttrib4fv(location, values);
1754 values += rows;
1755 ++location;
1756 }
1757 }
1758}
1759
1772 (const char *name, const GLfloat *values, int columns, int rows)
1773{
1775}
1776
1792 (int location, const GLfloat *values, int tupleSize, int stride)
1793{
1795 Q_UNUSED(d);
1796 if (location != -1) {
1797 d->glfuncs->glVertexAttribPointer(location, tupleSize, GL_FLOAT, GL_FALSE,
1798 stride, values);
1799 }
1800}
1801
1816 (int location, const QVector2D *values, int stride)
1817{
1819 Q_UNUSED(d);
1820 if (location != -1) {
1821 d->glfuncs->glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
1822 stride, values);
1823 }
1824}
1825
1840 (int location, const QVector3D *values, int stride)
1841{
1843 Q_UNUSED(d);
1844 if (location != -1) {
1845 d->glfuncs->glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
1846 stride, values);
1847 }
1848}
1849
1864 (int location, const QVector4D *values, int stride)
1865{
1867 Q_UNUSED(d);
1868 if (location != -1) {
1869 d->glfuncs->glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
1870 stride, values);
1871 }
1872}
1873
1898 (int location, GLenum type, const void *values, int tupleSize, int stride)
1899{
1901 Q_UNUSED(d);
1902 if (location != -1) {
1903 d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE,
1904 stride, values);
1905 }
1906}
1907
1925 (const char *name, const GLfloat *values, int tupleSize, int stride)
1926{
1928}
1929
1950
1971
1992
2016 (const char *name, GLenum type, const void *values, int tupleSize, int stride)
2017{
2019}
2020
2043 (int location, GLenum type, int offset, int tupleSize, int stride)
2044{
2046 Q_UNUSED(d);
2047 if (location != -1) {
2048 d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride,
2049 reinterpret_cast<const void *>(qintptr(offset)));
2050 }
2051}
2052
2074 (const char *name, GLenum type, int offset, int tupleSize, int stride)
2075{
2077}
2078
2088{
2090 Q_UNUSED(d);
2091 if (location != -1)
2092 d->glfuncs->glEnableVertexAttribArray(location);
2093}
2094
2109
2118{
2120 Q_UNUSED(d);
2121 if (location != -1)
2122 d->glfuncs->glDisableVertexAttribArray(location);
2123}
2124
2138
2147{
2148 Q_D(const QOpenGLShaderProgram);
2149 Q_UNUSED(d);
2150 if (d->linked && d->programGuard && d->programGuard->id()) {
2151 return d->glfuncs->glGetUniformLocation(d->programGuard->id(), name);
2152 } else {
2153 qWarning("QOpenGLShaderProgram::uniformLocation(%s): shader program is not linked", name);
2154 return -1;
2155 }
2156}
2157
2168{
2169 return uniformLocation(name.constData());
2170}
2171
2182{
2183 return uniformLocation(name.toLatin1().constData());
2184}
2185
2192{
2194 Q_UNUSED(d);
2195 if (location != -1)
2196 d->glfuncs->glUniform1fv(location, 1, &value);
2197}
2198
2211
2218{
2220 Q_UNUSED(d);
2221 if (location != -1)
2222 d->glfuncs->glUniform1i(location, value);
2223}
2224
2237
2248{
2250 Q_UNUSED(d);
2251 if (location != -1)
2252 d->glfuncs->glUniform1i(location, value);
2253}
2254
2270
2278{
2280 Q_UNUSED(d);
2281 if (location != -1) {
2282 GLfloat values[2] = {x, y};
2283 d->glfuncs->glUniform2fv(location, 1, values);
2284 }
2285}
2286
2299
2308{
2310 Q_UNUSED(d);
2311 if (location != -1) {
2312 GLfloat values[3] = {x, y, z};
2313 d->glfuncs->glUniform3fv(location, 1, values);
2314 }
2315}
2316
2330
2339{
2341 Q_UNUSED(d);
2342 if (location != -1) {
2343 GLfloat values[4] = {x, y, z, w};
2344 d->glfuncs->glUniform4fv(location, 1, values);
2345 }
2346}
2347
2361
2368{
2370 Q_UNUSED(d);
2371 if (location != -1)
2372 d->glfuncs->glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2373}
2374
2387
2394{
2396 Q_UNUSED(d);
2397 if (location != -1)
2398 d->glfuncs->glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2399}
2400
2413
2420{
2422 Q_UNUSED(d);
2423 if (location != -1)
2424 d->glfuncs->glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2425}
2426
2439
2447{
2449 Q_UNUSED(d);
2450 if (location != -1) {
2451 GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()),
2452 GLfloat(color.blueF()), GLfloat(color.alphaF())};
2453 d->glfuncs->glUniform4fv(location, 1, values);
2454 }
2455}
2456
2469
2477{
2479 Q_UNUSED(d);
2480 if (location != -1) {
2481 GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2482 d->glfuncs->glUniform2fv(location, 1, values);
2483 }
2484}
2485
2495{
2497}
2498
2506{
2508 Q_UNUSED(d);
2509 if (location != -1) {
2510 GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2511 d->glfuncs->glUniform2fv(location, 1, values);
2512 }
2513}
2514
2524{
2526}
2527
2535{
2537 Q_UNUSED(d);
2538 if (location != -1) {
2539 GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2540 d->glfuncs->glUniform2fv(location, 1, values);
2541 }
2542}
2543
2556
2564{
2566 Q_UNUSED(d);
2567 if (location != -1) {
2568 GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2569 d->glfuncs->glUniform2fv(location, 1, values);
2570 }
2571}
2572
2585
2593{
2595 Q_UNUSED(d);
2596 d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value.constData());
2597}
2598
2611
2623{
2625 Q_UNUSED(d);
2626 d->glfuncs->glUniform3fv(location, 2, value.constData());
2627}
2628
2645
2657{
2659 Q_UNUSED(d);
2660 d->glfuncs->glUniform4fv(location, 2, value.constData());
2661}
2662
2679
2691{
2693 Q_UNUSED(d);
2694 d->glfuncs->glUniform2fv(location, 3, value.constData());
2695}
2696
2713
2721{
2723 Q_UNUSED(d);
2724 d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value.constData());
2725}
2726
2739
2751{
2753 Q_UNUSED(d);
2754 d->glfuncs->glUniform4fv(location, 3, value.constData());
2755}
2756
2773
2785{
2787 Q_UNUSED(d);
2788 d->glfuncs->glUniform2fv(location, 4, value.constData());
2789}
2790
2807
2819{
2821 Q_UNUSED(d);
2822 d->glfuncs->glUniform3fv(location, 4, value.constData());
2823}
2824
2841
2849{
2851 Q_UNUSED(d);
2852 d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value.constData());
2853}
2854
2867
2878{
2880 Q_UNUSED(d);
2881 if (location != -1)
2882 d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value[0]);
2883}
2884
2895{
2897 Q_UNUSED(d);
2898 if (location != -1)
2899 d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value[0]);
2900}
2901
2912{
2914 Q_UNUSED(d);
2915 if (location != -1)
2916 d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
2917}
2918
2919
2933
2947
2961
2970{
2972 Q_UNUSED(d);
2973 if (location != -1) {
2974 GLfloat mat[3][3] = {
2975 {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())},
2976 {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())},
2977 {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())}
2978 };
2979 d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
2980 }
2981}
2982
2997
3005{
3007 Q_UNUSED(d);
3008 if (location != -1)
3009 d->glfuncs->glUniform1iv(location, count, values);
3010}
3011
3025
3037{
3039 Q_UNUSED(d);
3040 if (location != -1)
3041 d->glfuncs->glUniform1iv(location, count, reinterpret_cast<const GLint *>(values));
3042}
3043
3058
3067{
3069 Q_UNUSED(d);
3070 if (location != -1) {
3071 if (tupleSize == 1)
3072 d->glfuncs->glUniform1fv(location, count, values);
3073 else if (tupleSize == 2)
3074 d->glfuncs->glUniform2fv(location, count, values);
3075 else if (tupleSize == 3)
3076 d->glfuncs->glUniform3fv(location, count, values);
3077 else if (tupleSize == 4)
3078 d->glfuncs->glUniform4fv(location, count, values);
3079 else
3080 qWarning("QOpenGLShaderProgram::setUniformValue: size %d not supported", tupleSize);
3081 }
3082}
3083
3094 (const char *name, const GLfloat *values, int count, int tupleSize)
3095{
3097}
3098
3106{
3108 Q_UNUSED(d);
3109 if (location != -1)
3110 d->glfuncs->glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
3111}
3112
3125
3133{
3135 Q_UNUSED(d);
3136 if (location != -1)
3137 d->glfuncs->glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
3138}
3139
3152
3160{
3162 Q_UNUSED(d);
3163 if (location != -1)
3164 d->glfuncs->glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
3165}
3166
3179
3180// We have to repack matrix arrays from qreal to GLfloat.
3181#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
3182 if (location == -1 || count <= 0) \
3183 return; \
3184 if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
3185 func(location, count, GL_FALSE, \
3186 reinterpret_cast<const GLfloat *>(values[0].constData())); \
3187 } else { \
3188 QVarLengthArray<GLfloat> temp(cols * rows * count); \
3189 for (int index = 0; index < count; ++index) { \
3190 for (int index2 = 0; index2 < (cols * rows); ++index2) { \
3191 temp.data()[cols * rows * index + index2] = \
3192 values[index].constData()[index2]; \
3193 } \
3194 } \
3195 func(location, count, GL_FALSE, temp.constData()); \
3196 }
3197#define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \
3198 if (location == -1 || count <= 0) \
3199 return; \
3200 if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
3201 const GLfloat *data = reinterpret_cast<const GLfloat *> \
3202 (values[0].constData()); \
3203 colfunc(location, count * cols, data); \
3204 } else { \
3205 QVarLengthArray<GLfloat> temp(cols * rows * count); \
3206 for (int index = 0; index < count; ++index) { \
3207 for (int index2 = 0; index2 < (cols * rows); ++index2) { \
3208 temp.data()[cols * rows * index + index2] = \
3209 values[index].constData()[index2]; \
3210 } \
3211 } \
3212 colfunc(location, count * cols, temp.constData()); \
3213 }
3214
3222{
3224 Q_UNUSED(d);
3226 (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
3227}
3228
3241
3249{
3251 Q_UNUSED(d);
3253 (d->glfuncs->glUniform3fv, location, values, count,
3254 QMatrix2x3, 2, 3);
3255}
3256
3269
3277{
3279 Q_UNUSED(d);
3281 (d->glfuncs->glUniform4fv, location, values, count,
3282 QMatrix2x4, 2, 4);
3283}
3284
3297
3305{
3307 Q_UNUSED(d);
3309 (d->glfuncs->glUniform2fv, location, values, count,
3310 QMatrix3x2, 3, 2);
3311}
3312
3325
3333{
3335 Q_UNUSED(d);
3337 (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
3338}
3339
3352
3360{
3362 Q_UNUSED(d);
3364 (d->glfuncs->glUniform4fv, location, values, count,
3365 QMatrix3x4, 3, 4);
3366}
3367
3380
3388{
3390 Q_UNUSED(d);
3392 (d->glfuncs->glUniform2fv, location, values, count,
3393 QMatrix4x2, 4, 2);
3394}
3395
3408
3416{
3418 Q_UNUSED(d);
3420 (d->glfuncs->glUniform3fv, location, values, count,
3421 QMatrix4x3, 4, 3);
3422}
3423
3436
3444{
3446 Q_UNUSED(d);
3448 (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
3449}
3450
3463
3469{
3470 GLint n = 0;
3471 Q_D(const QOpenGLShaderProgram);
3472 d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n);
3473 return n;
3474}
3475
3495{
3497 d->glfuncs->glPatchParameteri(GL_PATCH_VERTICES, count);
3498}
3499
3509{
3510 int patchVertices = 0;
3511 Q_D(const QOpenGLShaderProgram);
3512 d->glfuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices);
3513 return patchVertices;
3514}
3515
3537{
3538#if !QT_CONFIG(opengles2)
3540 if (d->tessellationFuncs) {
3541 QList<float> tessLevels = levels;
3542
3543 // Ensure we have the required 4 outer tessellation levels
3544 // Use default of 1 for missing entries (same as spec)
3545 const int argCount = 4;
3546 if (tessLevels.size() < argCount) {
3547 tessLevels.reserve(argCount);
3548 for (int i = tessLevels.size(); i < argCount; ++i)
3549 tessLevels.append(1.0f);
3550 }
3551 d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
3552 }
3553#else
3555#endif
3556}
3557
3577{
3578#if !QT_CONFIG(opengles2)
3579 QList<float> tessLevels(4, 1.0f);
3580 Q_D(const QOpenGLShaderProgram);
3581 if (d->tessellationFuncs)
3582 d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
3583 return tessLevels;
3584#else
3585 return QList<float>();
3586#endif
3587}
3588
3610{
3611#if !QT_CONFIG(opengles2)
3613 if (d->tessellationFuncs) {
3614 QList<float> tessLevels = levels;
3615
3616 // Ensure we have the required 2 inner tessellation levels
3617 // Use default of 1 for missing entries (same as spec)
3618 const int argCount = 2;
3619 if (tessLevels.size() < argCount) {
3620 tessLevels.reserve(argCount);
3621 for (int i = tessLevels.size(); i < argCount; ++i)
3622 tessLevels.append(1.0f);
3623 }
3624 d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
3625 }
3626#else
3628#endif
3629}
3630
3650{
3651#if !QT_CONFIG(opengles2)
3652 QList<float> tessLevels(2, 1.0f);
3653 Q_D(const QOpenGLShaderProgram);
3654 if (d->tessellationFuncs)
3655 d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
3656 return tessLevels;
3657#else
3658 return QList<float>();
3659#endif
3660}
3661
3662
3679
3683void QOpenGLShaderProgram::shaderDestroyed()
3684{
3686 QOpenGLShader *shader = qobject_cast<QOpenGLShader *>(sender());
3687 if (shader && !d->removingShaders)
3689}
3690
3700{
3701 if (!context)
3703 if (!context)
3704 return false;
3705
3707 return false;
3708
3710 return supportsGeometry(context->format());
3712 return supportsTessellation(context->format());
3713 else if (type & QOpenGLShader::Compute)
3714 return supportsCompute(context->format());
3715
3716 // Unconditional support of vertex and fragment shaders implicitly assumes
3717 // a minimum OpenGL version of 2.0
3718 return true;
3719}
3720
3722{
3723 static QOpenGLProgramBinarySupportCheckWrapper binSupportCheck;
3724 return !binSupportCheck.get(QOpenGLContext::currentContext())->isSupported();
3725}
3726
3728{
3731 auto s = std::make_unique<QOpenGLShader>(qt_shaderStageToType(shader.stage), q);
3732 if (!s->compileSourceCode(shader.source)) {
3733 log = s->log();
3734 return false;
3735 }
3736 anonShaders.append(s.release());
3737 if (!q->addShader(anonShaders.last()))
3738 return false;
3739 }
3740 return true;
3741}
3742
3744{
3745 static QOpenGLProgramBinaryCache binCache;
3746
3748
3750 if (lcOpenGLProgramDiskCache().isEnabled(QtDebugMsg))
3751 qCDebug(lcOpenGLProgramDiskCache, "program with %d shaders, cache key %s",
3752 int(binaryProgram.shaders.size()), cacheKey.constData());
3753
3754 bool needsCompile = true;
3755 if (binCache.load(cacheKey, q->programId())) {
3756 qCDebug(lcOpenGLProgramDiskCache, "Program binary received from cache");
3757 needsCompile = false;
3758 }
3759
3760 bool needsSave = false;
3761 if (needsCompile) {
3762 qCDebug(lcOpenGLProgramDiskCache, "Program binary not in cache, compiling");
3763 if (compileCacheable())
3764 needsSave = true;
3765 else
3766 return false;
3767 }
3768
3769 linkBinaryRecursion = true;
3770 bool ok = q->link();
3771 linkBinaryRecursion = false;
3772 if (ok && needsSave)
3773 binCache.save(cacheKey, q->programId());
3774
3775 return ok;
3776}
3777
3779
3780#include "moc_qopenglshaderprogram.cpp"
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
The QGenericMatrix class is a template class that represents a NxM transformation matrix with N colum...
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
T & last()
Definition qlist.h:648
void append(parameter_type t)
Definition qlist.h:458
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
QString objectName
the name of this object
Definition qobject.h:107
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
static QOpenGLContextGroup * currentContextGroup()
Returns the QOpenGLContextGroup corresponding to the current context.
static QOpenGLContextPrivate * get(QOpenGLContext *context)
\inmodule QtGui
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLExtraFunctions class provides cross-platform access to the OpenGL ES 3....
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, char *source)
Convenience function that calls glGetShaderSource(shader, bufsize, length, source).
void glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
Convenience function that calls glGetShaderiv(shader, pname, params).
GLuint glCreateShader(GLenum type)
Convenience function that calls glCreateShader(type).
void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, char *infolog)
Convenience function that calls glGetShaderInfoLog(shader, bufsize, length, infolog).
bool hasOpenGLFeature(QOpenGLFunctions::OpenGLFeature feature) const
Returns true if feature is present on this system's OpenGL implementation; false otherwise.
void glCompileShader(GLuint shader)
Convenience function that calls glCompileShader(shader).
QOpenGLProgramBinarySupportCheck * get(QOpenGLContext *context)
QOpenGLShader::ShaderType shaderType
QOpenGLExtraFunctions * glfuncs
QOpenGLSharedResourceGuard * shaderGuard
QOpenGLShaderPrivate(QOpenGLContext *ctx, QOpenGLShader::ShaderType type)
bool compile(QOpenGLShader *q)
QList< QOpenGLShader * > shaders
QOpenGLSharedResourceGuard * programGuard
bool hasShader(QOpenGLShader::ShaderType type) const
QOpenGLFunctions_4_0_Core * tessellationFuncs
QOpenGLProgramBinaryCache::ProgramDesc binaryProgram
QList< QOpenGLShader * > anonShaders
The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used.
void setPatchVertexCount(int count)
Use this function to specify to OpenGL the number of vertices in a patch to count.
void release()
Releases the active shader program from the current QOpenGLContext.
int maxGeometryOutputVertices() const
Returns the hardware limit for how many vertices a geometry shader can output.
int patchVertexCount() const
Returns the number of vertices per-patch to be used when rendering.
void bindAttributeLocation(const char *name, int location)
Binds the attribute name to the specified location.
bool addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
Compiles source as a shader of the specified type and adds it to this shader program.
void enableAttributeArray(int location)
Enables the vertex array at location in this shader program so that the value set by setAttributeArra...
virtual bool link()
Links together the shaders that were added to this program with addShader().
bool create()
Requests the shader program's id to be created immediately.
int uniformLocation(const char *name) const
Returns the location of the uniform variable name within this shader program's parameter list.
QList< float > defaultOuterTessellationLevels() const
Returns the default outer tessellation levels to be used by the tessellation primitive generator in t...
void setDefaultInnerTessellationLevels(const QList< float > &levels)
Sets the default outer tessellation levels to be used by the tessellation primitive generator in the ...
QList< float > defaultInnerTessellationLevels() const
Returns the default inner tessellation levels to be used by the tessellation primitive generator in t...
void removeShader(QOpenGLShader *shader)
Removes shader from this shader program.
void setUniformValue(int location, GLfloat value)
Sets the uniform variable at location in the current context to value.
void removeAllShaders()
Removes all of the shaders that were added to this program previously.
QString log() const
Returns the errors and warnings that occurred during the last link() or addShader() with explicitly s...
void setDefaultOuterTessellationLevels(const QList< float > &levels)
Sets the default outer tessellation levels to be used by the tessellation primitive generator in the ...
bool addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName)
Registers the shader of the specified type and fileName to this program.
void disableAttributeArray(int location)
Disables the vertex array at location in this shader program that was enabled by a previous call to e...
static bool hasOpenGLShaderPrograms(QOpenGLContext *context=nullptr)
Returns true if shader programs written in the OpenGL Shading Language (GLSL) are supported on this s...
bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
Registers the shader of the specified type and source to this program.
void setAttributeArray(int location, const GLfloat *values, int tupleSize, int stride=0)
Sets an array of vertex values on the attribute at location in this shader program.
int attributeLocation(const char *name) const
Returns the location of the attribute name within this shader program's parameter list.
bool addShader(QOpenGLShader *shader)
Adds a compiled shader to this shader program.
QOpenGLShaderProgram(QObject *parent=nullptr)
Constructs a new shader program and attaches it to parent.
QList< QOpenGLShader * > shaders() const
Returns a list of all shaders that have been added to this shader program using addShader().
void setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize)
Sets the uniform variable array at location in the current context to the count elements of values.
bool isLinked() const
Returns true if this shader program has been linked; false otherwise.
~QOpenGLShaderProgram()
Deletes this shader program.
GLuint programId() const
Returns the OpenGL identifier associated with this shader program.
bool bind()
Binds this shader program to the active QOpenGLContext and makes it the current shader program.
void setAttributeValue(int location, GLfloat value)
Sets the attribute at location in the current context to value.
bool addShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName)
Compiles the contents of fileName as a shader of the specified type and adds it to this shader progra...
void setAttributeBuffer(int location, GLenum type, int offset, int tupleSize, int stride=0)
Sets an array of vertex values on the attribute at location in this shader program,...
The QOpenGLShader class allows OpenGL shaders to be compiled.
bool compileSourceFile(const QString &fileName)
Sets the source code for this shader to the contents of fileName and compiles it.
bool isCompiled() const
Returns true if this shader has been compiled; false otherwise.
QByteArray sourceCode() const
Returns the source code for this shader.
QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent=nullptr)
Constructs a new QOpenGLShader object of the specified type and attaches it to parent.
~QOpenGLShader()
Deletes this shader.
QOpenGLShader::ShaderType shaderType() const
Returns the type of this shader.
GLuint shaderId() const
Returns the OpenGL identifier associated with this shader.
QString log() const
Returns the errors and warnings that occurred during the last compile.
static bool hasOpenGLShaders(ShaderType type, QOpenGLContext *context=nullptr)
Returns true if shader programs of type type are supported on this system; false otherwise.
bool compileSourceCode(const char *source)
Sets the source code for this shader and compiles it.
The QOpenGLSharedResourceGuard class is a convenience sub-class of QOpenGLSharedResource to be used t...
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
Stage
Describes the stage of the graphics pipeline the shader is suitable for.
Definition qshader.h:83
@ GeometryStage
Definition qshader.h:87
@ ComputeStage
Definition qshader.h:89
@ TessellationEvaluationStage
Definition qshader.h:86
@ VertexStage
Definition qshader.h:84
@ FragmentStage
Definition qshader.h:88
@ TessellationControlStage
Definition qshader.h:85
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
EGLContext ctx
static VulkanServerBufferGlFunctions * funcs
qDeleteAll(list.begin(), list.end())
else opt state
[0]
Combined button and popup list for selecting options.
static void * context
size_t qstrlen(const char *str)
#define Q_FALLTHROUGH()
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QByteArray cacheKey(Args &&...args)
@ QtDebugMsg
Definition qlogging.h:30
#define qWarning
Definition qlogging.h:166
#define qCDebug(category,...)
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLint location
GLenum GLsizei GLsizei GLint * values
[15]
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
typedef GLfloat(GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC)(GLuint path
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLenum * types
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLsizei levels
GLenum src
const void GLsizei GLsizei stride
GLuint color
[2]
GLenum type
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLuint program
GLenum GLuint GLintptr offset
GLuint name
GLfloat n
GLint y
GLsizei GLsizei GLchar * source
GLdouble s
[6]
Definition qopenglext.h:235
#define GL_FRAGMENT_SHADER
Definition qopenglext.h:609
const GLubyte * c
GLuint shader
Definition qopenglext.h:665
#define GL_PATCH_DEFAULT_INNER_LEVEL
#define GL_SHADER_SOURCE_LENGTH
Definition qopenglext.h:644
#define GL_COMPILE_STATUS
Definition qopenglext.h:637
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define GL_PATCH_DEFAULT_OUTER_LEVEL
GLenum GLsizei len
#define GL_MAX_GEOMETRY_OUTPUT_VERTICES
#define GL_VERTEX_SHADER
Definition qopenglext.h:610
#define GL_PATCH_VERTICES
#define GL_LINK_STATUS
Definition qopenglext.h:638
#define GL_INFO_LOG_LENGTH
Definition qopenglext.h:640
#define setUniformGenericMatrixArray(colfunc, location, values, count, type, cols, rows)
static bool supportsTessellation(const QSurfaceFormat &f)
static QVersionDirectivePosition findVersionDirectivePosition(const char *source)
#define GL_GEOMETRY_SHADER
static QShader::Stage qt_shaderTypeToStage(QOpenGLShader::ShaderType type)
#define GL_TESS_CONTROL_SHADER
static bool isFormatGLES(const QSurfaceFormat &f)
static bool supportsGeometry(const QSurfaceFormat &f)
#define GL_COMPUTE_SHADER
#define GL_TESS_EVALUATION_SHADER
#define setUniformMatrixArray(func, location, values, count, type, cols, rows)
static const char blendEquationAdvancedHeader[]
static const char qualifierDefines[]
static QOpenGLShader::ShaderType qt_shaderStageToType(QShader::Stage stage)
static bool supportsCompute(const QSurfaceFormat &f)
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define GLuint
#define GL_FLOAT
#define qPrintable(string)
Definition qstring.h:1531
#define qUtf16Printable(string)
Definition qstring.h:1543
#define QStringLiteral(str)
#define QT_CONFIG(feature)
#define Q_UNUSED(x)
ptrdiff_t qintptr
Definition qtypes.h:166
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QObject::connect nullptr
myObject disconnect()
[26]
constexpr QVersionDirectivePosition(int position=0, int line=-1)
constexpr bool hasPosition() const
\qmltype MapCircle \instantiates QDeclarativeCircleMapItem \inqmlmodule QtLocation