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
qopenglengineshadermanager.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
7#include <private/qopenglshadercache_p.h>
8
9#include <QtGui/private/qopenglcontext_p.h>
10#include <QtCore/qthreadstorage.h>
11
12#include <algorithm>
13#include <memory>
14
15#if defined(QT_DEBUG)
16#include <QMetaEnum>
17#endif
18
19// #define QT_GL_SHARED_SHADER_DEBUG
20
22
24{
25public:
31
33 {
34 delete m_shaders;
35 }
36
37 void invalidateResource() override
38 {
39 delete m_shaders;
40 m_shaders = nullptr;
41 }
42
44 {
45 }
46
47 QOpenGLEngineSharedShaders *shaders() const { return m_shaders; }
48
49private:
51};
52
54{
55public:
64
65private:
66 QThreadStorage<QOpenGLMultiGroupSharedResource *> m_storage;
67};
68
70
75
76const char* QOpenGLEngineSharedShaders::qShaderSnippets[] = {
77 0,0,0,0,0,0,0,0,0,0,
78 0,0,0,0,0,0,0,0,0,0,
79 0,0,0,0,0,0,0,0,0,0,
80 0,0,0,0,0
81};
82
84 : blitShaderProg(nullptr)
85 , simpleShaderProg(nullptr)
86{
87
88/*
89 Rather than having the shader source array statically initialised, it is initialised
90 here instead. This is to allow new shader names to be inserted or existing names moved
91 around without having to change the order of the glsl strings. It is hoped this will
92 make future hard-to-find runtime bugs more obvious and generally give more solid code.
93*/
94
95 // Check if the user has requested an OpenGL 3.2 Core Profile or higher
96 // and if so use GLSL 1.50 core shaders instead of legacy ones.
97 const QSurfaceFormat &fmt = context->format();
98 const bool isCoreProfile = fmt.profile() == QSurfaceFormat::CoreProfile && fmt.version() >= qMakePair(3,2);
99
100 const char** code = qShaderSnippets; // shortcut
101
102 if (isCoreProfile) {
103 code[MainVertexShader] = qopenglslMainVertexShader_core;
104 code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader_core;
105 code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader_core;
106
107 code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader_core;
108 code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader_core;
109 code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader_core;
110 code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader_core;
111 code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader_core;
112 code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader_core;
113 code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader_core;
114 code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader_core;
115 code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader_core;
116 code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader_core;
117 code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader_core;
118 code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader_core;
119 code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader_core;
120
121 code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO_core;
122 code[MainFragmentShader_M] = qopenglslMainFragmentShader_M_core;
123 code[MainFragmentShader_O] = qopenglslMainFragmentShader_O_core;
124 code[MainFragmentShader] = qopenglslMainFragmentShader_core;
125 code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays_core;
126
127 code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader_core;
128 code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader_core;
129 code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader_core;
130 code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader_core;
131 code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader_core;
132 code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended
133 code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core;
134
135 code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_core;
136 code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core;
137 code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core;
138 code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core;
139 code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader_core;
140 code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader_core;
141 code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader_core;
142
143 code[NoMaskFragmentShader] = "";
144 code[MaskFragmentShader] = qopenglslMaskFragmentShader_core;
145 code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1_core;
146 code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2_core;
147 code[RgbMaskWithGammaFragmentShader] = ""; //###
148 } else {
152
159 code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader;
166
172
178 code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
187
188 code[NoMaskFragmentShader] = "";
192 code[RgbMaskWithGammaFragmentShader] = ""; //###
193 }
194
195 // The composition shaders are just layout qualifiers and the same
196 // for all profiles that support them.
198 code[MultiplyCompositionModeFragmentShader] = qopenglslMultiplyCompositionModeFragmentShader;
199 code[ScreenCompositionModeFragmentShader] = qopenglslScreenCompositionModeFragmentShader;
200 code[OverlayCompositionModeFragmentShader] = qopenglslOverlayCompositionModeFragmentShader;
201 code[DarkenCompositionModeFragmentShader] = qopenglslDarkenCompositionModeFragmentShader;
202 code[LightenCompositionModeFragmentShader] = qopenglslLightenCompositionModeFragmentShader;
203 code[ColorDodgeCompositionModeFragmentShader] = qopenglslColorDodgeCompositionModeFragmentShader;
204 code[ColorBurnCompositionModeFragmentShader] = qopenglslColorBurnCompositionModeFragmentShader;
205 code[HardLightCompositionModeFragmentShader] = qopenglslHardLightCompositionModeFragmentShader;
206 code[SoftLightCompositionModeFragmentShader] = qopenglslSoftLightCompositionModeFragmentShader;
207 code[DifferenceCompositionModeFragmentShader] = qopenglslDifferenceCompositionModeFragmentShader;
208 code[ExclusionCompositionModeFragmentShader] = qopenglslExclusionCompositionModeFragmentShader;
209
210#if defined(QT_DEBUG)
211 // Check that all the elements have been filled:
212 for (int i = 0; i < TotalSnippetCount; ++i) {
213 if (Q_UNLIKELY(!qShaderSnippets[i])) {
214 qFatal("Shader snippet for %s (#%d) is missing!",
215 snippetNameStr(SnippetName(i)).constData(), i);
216 }
217 }
218#endif
219
220 QByteArray vertexSource;
221 QByteArray fragSource;
222
223 // Compile up the simple shader:
224#ifdef Q_OS_WASM
225 vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
226 vertexSource.append(qShaderSnippets[MainVertexShader]);
227#else
228 vertexSource.append(qShaderSnippets[MainVertexShader]);
229 vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
230#endif
231 fragSource.append(qShaderSnippets[MainFragmentShader]);
232 fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
233
234 simpleShaderProg = new QOpenGLShaderProgram;
235
236 CachedShader simpleShaderCache(fragSource, vertexSource);
237
238 bool inCache = simpleShaderCache.load(simpleShaderProg, context);
239
240 if (!inCache) {
241 if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
242 qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
243 if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
244 qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
245
246 simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
247 simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
248 simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
249 simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
250 }
251
252 simpleShaderProg->link();
253
254 if (Q_UNLIKELY(!simpleShaderProg->isLinked())) {
255 qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log()));
256 } else {
257 if (!inCache)
258 simpleShaderCache.store(simpleShaderProg, context);
259 }
260
261 // Compile the blit shader:
262 vertexSource.clear();
263 vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
264 vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]);
265
266 fragSource.clear();
267 fragSource.append(qShaderSnippets[MainFragmentShader]);
268 fragSource.append(qShaderSnippets[ImageSrcFragmentShader]);
269
270 blitShaderProg = new QOpenGLShaderProgram;
271
272 CachedShader blitShaderCache(fragSource, vertexSource);
273
274 inCache = blitShaderCache.load(blitShaderProg, context);
275
276 if (!inCache) {
277 if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
278 qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
279 if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
280 qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
281
282 blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
283 blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
284 }
285
286 blitShaderProg->link();
287 if (Q_UNLIKELY(!blitShaderProg->isLinked())) {
288 qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log()));
289 } else {
290 if (!inCache)
291 blitShaderCache.store(blitShaderProg, context);
292 }
293
294#ifdef QT_GL_SHARED_SHADER_DEBUG
295 qDebug(" -> QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
296#endif
297}
298
300{
301#ifdef QT_GL_SHARED_SHADER_DEBUG
302 qDebug(" -> ~QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
303#endif
304 qDeleteAll(cachedPrograms);
305 cachedPrograms.clear();
306
307 if (blitShaderProg) {
308 delete blitShaderProg;
309 blitShaderProg = nullptr;
310 }
311
312 if (simpleShaderProg) {
313 delete simpleShaderProg;
314 simpleShaderProg = nullptr;
315 }
316}
317
318#if defined (QT_DEBUG)
319QByteArray QOpenGLEngineSharedShaders::snippetNameStr(SnippetName name)
320{
321 QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
322 return QByteArray(m.valueToKey(name));
323}
324#endif
325
326// The address returned here will only be valid until next time this function is called.
327// The program is return bound.
329{
330 for (int i = 0; i < cachedPrograms.size(); ++i) {
331 QOpenGLEngineShaderProg *cachedProg = cachedPrograms[i];
332 if (*cachedProg == prog) {
333 // Move the program to the top of the list as a poor-man's cache algo
334 cachedPrograms.move(i, 0);
335 cachedProg->program->bind();
336 return cachedProg;
337 }
338 }
339
340 std::unique_ptr<QOpenGLEngineShaderProg> newProg;
341
342 do {
343 QByteArray fragSource;
344 // Insert the custom stage before the srcPixel shader to work around an ATI driver bug
345 // where you cannot forward declare a function that takes a sampler as argument.
346 if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
347 fragSource.append(prog.customStageSource);
348 fragSource.append(qShaderSnippets[prog.mainFragShader]);
349 fragSource.append(qShaderSnippets[prog.srcPixelFragShader]);
350 if (prog.compositionFragShader)
351 fragSource.append(qShaderSnippets[prog.compositionFragShader]);
352 if (prog.maskFragShader)
353 fragSource.append(qShaderSnippets[prog.maskFragShader]);
354
355 QByteArray vertexSource;
356#ifdef Q_OS_WASM
357 vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
358 vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
359#else
360 vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
361 vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
362#endif
363 auto shaderProgram = std::make_unique<QOpenGLShaderProgram>();
364
365 CachedShader shaderCache(fragSource, vertexSource);
366 bool inCache = shaderCache.load(shaderProgram.get(), QOpenGLContext::currentContext());
367
368 if (!inCache) {
369 if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) {
370 QByteArray description;
371#if defined(QT_DEBUG)
372 description.append("Vertex shader: main=");
373 description.append(snippetNameStr(prog.mainVertexShader));
374 description.append(", position=");
375 description.append(snippetNameStr(prog.positionVertexShader));
376#endif
377 qWarning("Warning: \"%s\" failed to compile!", description.constData());
378 break;
379 }
380 if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) {
381 QByteArray description;
382#if defined(QT_DEBUG)
383 description.append("Fragment shader: main=");
384 description.append(snippetNameStr(prog.mainFragShader));
385 description.append(", srcPixel=");
386 description.append(snippetNameStr(prog.srcPixelFragShader));
387 if (prog.compositionFragShader) {
388 description.append(", composition=");
389 description.append(snippetNameStr(prog.compositionFragShader));
390 }
391 if (prog.maskFragShader) {
392 description.append(", mask=");
393 description.append(snippetNameStr(prog.maskFragShader));
394 }
395#endif
396 qWarning("Warning: \"%s\" failed to compile!", description.constData());
397 break;
398 }
399
400 // We have to bind the vertex attribute names before the program is linked:
401 shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
402 if (prog.useTextureCoords)
403 shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
404 if (prog.useOpacityAttribute)
405 shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
406 if (prog.usePmvMatrixAttribute) {
407 shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
408 shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
409 shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
410 }
411 }
412
413 newProg.reset(new QOpenGLEngineShaderProg(prog));
414 newProg->program = shaderProgram.release();
415
416 newProg->program->link();
417 if (newProg->program->isLinked()) {
418 if (!inCache)
419 shaderCache.store(newProg->program, QOpenGLContext::currentContext());
420 } else {
421 qWarning("Shader program failed to link\n"
422 " Error Log:\n"
423 " %ls", qUtf16Printable(newProg->program->log()));
424 break;
425 }
426
427 newProg->program->bind();
428
429 if (newProg->maskFragShader != QOpenGLEngineSharedShaders::NoMaskFragmentShader) {
430 GLuint location = newProg->program->uniformLocation("maskTexture");
431 newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT);
432 }
433
434 if (cachedPrograms.size() > 30) {
435 // The cache is full, so delete the last 5 programs in the list.
436 // These programs will be least used, as a program us bumped to
437 // the top of the list when it's used.
438 for (int i = 0; i < 5; ++i) {
439 delete cachedPrograms.last();
440 cachedPrograms.removeLast();
441 }
442 }
443
444 cachedPrograms.insert(0, newProg.get());
445 } while (false);
446
447 return newProg.release();
448}
449
451{
452 auto hasStageAsCustomShaderSouce = [stage](QOpenGLEngineShaderProg *cachedProg) -> bool {
453 if (cachedProg->customStageSource == stage->source()) {
454 delete cachedProg;
455 return true;
456 }
457 return false;
458 };
459 cachedPrograms.removeIf(hasStageAsCustomShaderSouce);
460}
461
462
464 : ctx(context),
465 shaderProgNeedsChanging(true),
466 complexGeometry(false),
467 srcPixelType(Qt::NoBrush),
468 opacityMode(NoOpacity),
469 maskType(NoMask),
470 compositionMode(QPainter::CompositionMode_SourceOver),
471 customSrcStage(nullptr),
472 currentShaderProg(nullptr)
473{
475}
476
482
484{
485 if (!currentShaderProg)
486 return 0;
487
488 QList<uint> &uniformLocations = currentShaderProg->uniformLocations;
489 if (uniformLocations.isEmpty())
490 uniformLocations.fill(GLuint(-1), NumUniforms);
491
492 const char uniformNames[][26] = {
493 "imageTexture",
494 "patternColor",
495 "globalOpacity",
496 "depth",
497 "maskTexture",
498 "fragmentColor",
499 "linearData",
500 "angle",
501 "halfViewportSize",
502 "fmp",
503 "fmp2_m_radius2",
504 "inverse_2_fmp2_m_radius2",
505 "sqrfr",
506 "bradius",
507 "invertedTextureSize",
508 "brushTransform",
509 "brushTexture",
510 "matrix"
511 };
512
513 if (uniformLocations.at(id) == GLuint(-1))
514 uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]);
515
516 return uniformLocations.at(id);
517}
518
519
524
526{
527 shaderProgNeedsChanging = true;
528}
529
531{
532 Q_ASSERT(style != Qt::NoBrush);
533 if (srcPixelType == PixelSrcType(style))
534 return;
535
536 srcPixelType = style;
537 shaderProgNeedsChanging = true; //###
538}
539
541{
542 if (srcPixelType == type)
543 return;
544
545 srcPixelType = type;
546 shaderProgNeedsChanging = true; //###
547}
548
550{
551 if (opacityMode == mode)
552 return;
553
554 opacityMode = mode;
555 shaderProgNeedsChanging = true; //###
556}
557
559{
560 if (maskType == type)
561 return;
562
563 maskType = type;
564 shaderProgNeedsChanging = true; //###
565}
566
568{
569 if (compositionMode == mode)
570 return;
571
572 bool wasAdvanced = compositionMode > QPainter::CompositionMode_Plus;
573 bool isAdvanced = mode > QPainter::CompositionMode_Plus;
574
575 compositionMode = mode;
576 shaderProgNeedsChanging = shaderProgNeedsChanging || wasAdvanced || isAdvanced;
577}
578
580{
581 if (customSrcStage)
583 customSrcStage = stage;
584 shaderProgNeedsChanging = true;
585}
586
588{
589 if (customSrcStage)
590 customSrcStage->setInactive();
591 customSrcStage = nullptr;
592 shaderProgNeedsChanging = true;
593}
594
596{
597 if (currentShaderProg)
598 return currentShaderProg->program;
599 else
601}
602
604{
606 QOpenGLContextPrivate* ctx_d = ctx->d_func();
607 Q_UNUSED(ctx_d);
608
609 QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
610
611 active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
612 active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
613 active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
614
615 shaderProgNeedsChanging = true;
616}
617
619{
621 QOpenGLContextPrivate* ctx_d = ctx->d_func();
622 QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
623 active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
624 active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
625 active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
626 shaderProgNeedsChanging = true;
627}
628
633
638
639
640
641// Select & use the correct shader program using the current state.
642// Returns \c true if program needed changing.
644{
645 if (!shaderProgNeedsChanging)
646 return false;
647
648 bool useCustomSrc = customSrcStage != nullptr;
649 if (useCustomSrc && srcPixelType != QOpenGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
650 useCustomSrc = false;
651 qWarning("QOpenGLEngineShaderManager - Ignoring custom shader stage for non image src");
652 }
653
654 QOpenGLEngineShaderProg requiredProgram;
655
656 bool texCoords = false;
657
658 // Choose vertex shader shader position function (which typically also sets
659 // varyings) and the source pixel (srcPixel) fragment shader function:
661 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::InvalidSnippetName;
662 bool isAffine = brushTransform.isAffine();
663 if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
664 if (isAffine)
666 else
667 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
668
669 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::PatternBrushSrcFragmentShader;
670 }
671 else switch (srcPixelType) {
672 default:
673 case Qt::NoBrush:
674 qFatal("QOpenGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
675 break;
677 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcFragmentShader;
678 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
679 texCoords = true;
680 break;
683 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
684 texCoords = true;
685 break;
687 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::GrayscaleImageSrcFragmentShader;
688 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
689 texCoords = true;
690 break;
692 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::AlphaImageSrcFragmentShader;
693 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
694 texCoords = true;
695 break;
697 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
698 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
699 texCoords = true;
700 break;
703 requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
705 break;
706 case Qt::SolidPattern:
707 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::SolidBrushSrcFragmentShader;
708 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
709 break;
711 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
712 requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
714 break;
717 requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
719 break;
721 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
722 requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
724 break;
726 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::TextureBrushSrcFragmentShader;
727 requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
729 break;
730 };
731
732 if (useCustomSrc) {
733 requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::CustomImageSrcFragmentShader;
734 requiredProgram.customStageSource = customSrcStage->source();
735 }
736
737 const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
738 const bool hasMask = maskType != QOpenGLEngineShaderManager::NoMask;
739
740 // Choose fragment shader main function:
741 if (opacityMode == AttributeOpacity) {
742 Q_ASSERT(!hasCompose && !hasMask);
743 requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_ImageArrays;
744 } else {
745 bool useGlobalOpacity = (opacityMode == UniformOpacity);
746 if (hasMask && useGlobalOpacity)
747 requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_MO;
748 if (hasMask && !useGlobalOpacity)
749 requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_M;
750 if (!hasMask && useGlobalOpacity)
751 requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_O;
752 if (!hasMask && !useGlobalOpacity)
753 requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader;
754 }
755
756 if (hasMask) {
757 if (maskType == PixelMask) {
758 requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::MaskFragmentShader;
759 texCoords = true;
760 } else if (maskType == SubPixelMaskPass1) {
761 requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
762 texCoords = true;
763 } else if (maskType == SubPixelMaskPass2) {
764 requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
765 texCoords = true;
766 } else if (maskType == SubPixelWithGammaMask) {
767 requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
768 texCoords = true;
769 } else {
770 qCritical("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
771 }
772 } else {
773 requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::NoMaskFragmentShader;
774 }
775
776 if (hasCompose) {
777 switch (compositionMode) {
779 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
780 break;
782 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
783 break;
785 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
786 break;
788 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
789 break;
791 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::LightenCompositionModeFragmentShader;
792 break;
794 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
795 break;
797 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
798 break;
800 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
801 break;
803 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
804 break;
806 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
807 break;
809 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
810 break;
811 default:
812 qWarning("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
813 }
814 } else {
815 requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::NoCompositionModeFragmentShader;
816 }
817
818 // Choose vertex shader main function
819 if (opacityMode == AttributeOpacity) {
820 Q_ASSERT(texCoords);
822 } else if (texCoords) {
823 requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsVertexShader;
824 } else {
825 requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainVertexShader;
826 }
827 requiredProgram.useTextureCoords = texCoords;
828 requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
829 if (complexGeometry && srcPixelType == Qt::SolidPattern) {
830 requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader;
831 requiredProgram.usePmvMatrixAttribute = false;
832 } else {
833 requiredProgram.usePmvMatrixAttribute = true;
834
835 // Force complexGeometry off, since we currently don't support that mode for
836 // non-solid brushes
837 complexGeometry = false;
838 }
839
840 // At this point, requiredProgram is fully populated so try to find the program in the cache
841 currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
842
843 if (currentShaderProg && useCustomSrc) {
844 customSrcStage->setUniforms(currentShaderProg->program);
845 }
846
847 // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it
848 // doesn't use are disabled)
849 QOpenGLContextPrivate* ctx_d = ctx->d_func();
850 QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
851 active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
852 active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
853 active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
854
855 shaderProgNeedsChanging = false;
856 return true;
857}
858
860
861#include "moc_qopenglengineshadermanager_p.cpp"
bool store(QOpenGLShaderProgram *, QOpenGLContext *)
bool load(QOpenGLShaderProgram *, QOpenGLContext *)
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype size() const noexcept
Definition qlist.h:397
T & last()
Definition qlist.h:648
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
void move(qsizetype from, qsizetype to)
Definition qlist.h:610
qsizetype removeIf(Predicate pred)
Definition qlist.h:604
void removeLast() noexcept
Definition qlist.h:815
void clear()
Definition qlist.h:434
\inmodule QtCore
\inmodule QtGui
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
virtual void setUniforms(QOpenGLShaderProgram *)
QOpenGLEngineSharedShaders * sharedShaders
QOpenGLEngineShaderManager(QOpenGLContext *context)
void optimiseForBrushTransform(QTransform::TransformationType transformType)
void setCustomStage(QOpenGLCustomShaderStage *stage)
void setCompositionMode(QPainter::CompositionMode)
QOpenGLEngineSharedShaders::SnippetName positionVertexShader
void freeResource(QOpenGLContext *) override
QOpenGLEngineSharedShaders * shaders() const
QOpenGLEngineShaderProg * findProgramInCache(const QOpenGLEngineShaderProg &prog)
void cleanupCustomStage(QOpenGLCustomShaderStage *stage)
static QOpenGLEngineSharedShaders * shadersForContext(QOpenGLContext *context)
QOpenGLEngineSharedShaders(QOpenGLContext *context)
The QOpenGLMultiGroupSharedResource keeps track of a shared resource that might be needed from multip...
The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used.
void bindAttributeLocation(const char *name, int location)
Binds the attribute name to the specified location.
virtual bool link()
Links together the shaders that were added to this program with addShader().
int uniformLocation(const char *name) const
Returns the location of the uniform variable name within this shader program's parameter list.
QString log() const
Returns the errors and warnings that occurred during the last link() or addShader() with explicitly s...
bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
Registers the shader of the specified type and source to this program.
bool isLinked() const
Returns true if this shader program has been linked; false otherwise.
bool bind()
Binds this shader program to the active QOpenGLContext and makes it the current shader program.
QOpenGLEngineSharedShaders * shadersForThread(QOpenGLContext *context)
The QOpenGLSharedResource class is used to keep track of resources that are shared between OpenGL con...
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
CompositionMode
Defines the modes supported for digital image compositing.
Definition qpainter.h:97
@ CompositionMode_Lighten
Definition qpainter.h:117
@ CompositionMode_ColorDodge
Definition qpainter.h:118
@ CompositionMode_Plus
Definition qpainter.h:112
@ CompositionMode_Overlay
Definition qpainter.h:115
@ CompositionMode_Multiply
Definition qpainter.h:113
@ CompositionMode_Darken
Definition qpainter.h:116
@ CompositionMode_HardLight
Definition qpainter.h:120
@ CompositionMode_Exclusion
Definition qpainter.h:123
@ CompositionMode_ColorBurn
Definition qpainter.h:119
@ CompositionMode_Difference
Definition qpainter.h:122
@ CompositionMode_SoftLight
Definition qpainter.h:121
@ CompositionMode_Screen
Definition qpainter.h:114
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
T & localData()
Returns a reference to the data that was set by the calling thread.
static QThread * currentThread()
Definition qthread.cpp:1039
bool isAffine() const
Returns true if the matrix represent an affine transformation, otherwise returns false.
Definition qtransform.h:165
TransformationType
\value TxNone \value TxTranslate \value TxScale \value TxRotate \value TxShear \value TxProject
Definition qtransform.h:22
EGLContext ctx
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
Definition qcompare.h:63
BrushStyle
@ DiagCrossPattern
@ SolidPattern
@ RadialGradientPattern
@ Dense1Pattern
@ TexturePattern
@ LinearGradientPattern
@ NoBrush
@ ConicalGradientPattern
static void * context
#define Q_UNLIKELY(x)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCritical
Definition qlogging.h:167
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
static const GLuint QT_TEXTURE_COORDS_ATTR
static const GLuint QT_PMV_MATRIX_2_ATTR
static const GLuint QT_OPACITY_ATTR
static const GLuint QT_PMV_MATRIX_1_ATTR
static QT_BEGIN_NAMESPACE const GLuint QT_VERTEX_COORDS_ATTR
static const GLuint QT_PMV_MATRIX_3_ATTR
static const char *const qopenglslConicalGradientBrushSrcFragmentShader
static QT_BEGIN_NAMESPACE const char *const qopenglslMainVertexShader
static const char *const qopenglslPatternBrushSrcFragmentShader
static const char *const qopenglslMainFragmentShader_M
static const char *const qopenglslPositionWithConicalGradientBrushVertexShader
static const char *const qopenglslImageSrcWithPatternFragmentShader
static const char *const qopenglslSolidBrushSrcFragmentShader
static const char *const qopenglslImageSrcFragmentShader
static const char *const qopenglslAffinePositionWithLinearGradientBrushVertexShader
static const char *const qopenglslMainFragmentShader_ImageArrays
static const char *const qopenglslAlphaImageSrcFragmentShader
static const char *const qopenglslLinearGradientBrushSrcFragmentShader
static const char *const qopenglslPositionOnlyVertexShader
static const char *const qopenglslShockingPinkSrcFragmentShader
static const char *const qopenglslPositionWithPatternBrushVertexShader
static const char *const qopenglslMainFragmentShader_MO
static const char *const qopenglslMainWithTexCoordsAndOpacityVertexShader
static const char *const qopenglslRgbMaskFragmentShaderPass2
static const char *const qopenglslRgbMaskFragmentShaderPass1
static const char *const qopenglslCustomSrcFragmentShader
static const char *const qopenglslAffinePositionWithRadialGradientBrushVertexShader
static const char *const qopenglslGrayscaleImageSrcFragmentShader
static const char *const qopenglslAffinePositionWithTextureBrushVertexShader
static const char *const qopenglslAffinePositionWithConicalGradientBrushVertexShader
static const char *const qopenglslUntransformedPositionVertexShader
static const char *const qopenglslMainFragmentShader
static const char *const qopenglslAffinePositionWithPatternBrushVertexShader
static const char *const qopenglslTextureBrushSrcWithPatternFragmentShader
static const char *const qopenglslRadialGradientBrushSrcFragmentShader
static const char *const qopenglslTextureBrushSrcFragmentShader
static const char *const qopenglslMainFragmentShader_O
static const char *const qopenglslPositionWithLinearGradientBrushVertexShader
static const char *const qopenglslComplexGeometryPositionOnlyVertexShader
static const char *const qopenglslMaskFragmentShader
static const char *const qopenglslPositionWithTextureBrushVertexShader
static const char *const qopenglslMainWithTexCoordsVertexShader
static const char *const qopenglslNonPremultipliedImageSrcFragmentShader
GLint location
GLenum mode
const GLfloat * m
GLenum GLuint id
[7]
GLenum type
GLuint name
GLuint GLenum transformType
GLsizei GLsizei GLuint * shaders
Definition qopenglext.h:677
GLsizei const GLchar *const * uniformNames
#define QT_MASK_TEXTURE_UNIT
static bool isCoreProfile()
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 qPrintable(string)
Definition qstring.h:1531
#define qUtf16Printable(string)
Definition qstring.h:1543
#define Q_UNUSED(x)
QVideoFrameFormat::PixelFormat fmt
QObject::connect nullptr