source: trunk/src/opengl/gl2paintengineex/qglengineshadermanager.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 30.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qglengineshadermanager_p.h"
43#include "qglengineshadersource_p.h"
44
45#if defined(QT_DEBUG)
46#include <QMetaEnum>
47#endif
48
49
50QT_BEGIN_NAMESPACE
51
52static void qt_shared_shaders_free(void *data)
53{
54 delete reinterpret_cast<QGLEngineSharedShaders *>(data);
55}
56
57Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_shaders, (qt_shared_shaders_free))
58
59QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context)
60{
61 QGLEngineSharedShaders *p = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->value(context));
62 if (!p) {
63 QGLShareContextScope scope(context);
64 qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context));
65 }
66 return p;
67}
68
69const char* QGLEngineSharedShaders::qShaderSnippets[] = {
70 0,0,0,0,0,0,0,0,0,0,
71 0,0,0,0,0,0,0,0,0,0,
72 0,0,0,0,0,0,0,0,0,0,
73 0,0,0,0,0
74};
75
76QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
77 : ctxGuard(context)
78 , blitShaderProg(0)
79 , simpleShaderProg(0)
80{
81
82/*
83 Rather than having the shader source array statically initialised, it is initialised
84 here instead. This is to allow new shader names to be inserted or existing names moved
85 around without having to change the order of the glsl strings. It is hoped this will
86 make future hard-to-find runtime bugs more obvious and generally give more solid code.
87*/
88 static bool snippetsPopulated = false;
89 if (!snippetsPopulated) {
90
91 const char** code = qShaderSnippets; // shortcut
92
93 code[MainVertexShader] = qglslMainVertexShader;
94 code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
95 code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
96
97 code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
98 code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
99 code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
100 code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
101 code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader;
102 code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader;
103 code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader;
104 code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader;
105 code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader;
106 code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader;
107 code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader;
108 code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader;
109
110 code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO;
111 code[MainFragmentShader_CM] = qglslMainFragmentShader_CM;
112 code[MainFragmentShader_MO] = qglslMainFragmentShader_MO;
113 code[MainFragmentShader_M] = qglslMainFragmentShader_M;
114 code[MainFragmentShader_CO] = qglslMainFragmentShader_CO;
115 code[MainFragmentShader_C] = qglslMainFragmentShader_C;
116 code[MainFragmentShader_O] = qglslMainFragmentShader_O;
117 code[MainFragmentShader] = qglslMainFragmentShader;
118 code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
119
120 code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
121 code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
122 code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
123 code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
124 code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
125 code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
126 code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
127 code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
128 code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
129 code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
130 code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
131 code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
132
133 code[NoMaskFragmentShader] = "";
134 code[MaskFragmentShader] = qglslMaskFragmentShader;
135 code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1;
136 code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2;
137 code[RgbMaskWithGammaFragmentShader] = ""; //###
138
139 code[NoCompositionModeFragmentShader] = "";
140 code[MultiplyCompositionModeFragmentShader] = ""; //###
141 code[ScreenCompositionModeFragmentShader] = ""; //###
142 code[OverlayCompositionModeFragmentShader] = ""; //###
143 code[DarkenCompositionModeFragmentShader] = ""; //###
144 code[LightenCompositionModeFragmentShader] = ""; //###
145 code[ColorDodgeCompositionModeFragmentShader] = ""; //###
146 code[ColorBurnCompositionModeFragmentShader] = ""; //###
147 code[HardLightCompositionModeFragmentShader] = ""; //###
148 code[SoftLightCompositionModeFragmentShader] = ""; //###
149 code[DifferenceCompositionModeFragmentShader] = ""; //###
150 code[ExclusionCompositionModeFragmentShader] = ""; //###
151
152#if defined(QT_DEBUG)
153 // Check that all the elements have been filled:
154 for (int i = 0; i < TotalSnippetCount; ++i) {
155 if (qShaderSnippets[i] == 0) {
156 qFatal("Shader snippet for %s (#%d) is missing!",
157 snippetNameStr(SnippetName(i)).constData(), i);
158 }
159 }
160#endif
161 snippetsPopulated = true;
162 }
163
164 QGLShader* fragShader;
165 QGLShader* vertexShader;
166 QByteArray source;
167
168 // Compile up the simple shader:
169 source.clear();
170 source.append(qShaderSnippets[MainVertexShader]);
171 source.append(qShaderSnippets[PositionOnlyVertexShader]);
172 vertexShader = new QGLShader(QGLShader::Vertex, context, this);
173 if (!vertexShader->compileSourceCode(source))
174 qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
175
176 source.clear();
177 source.append(qShaderSnippets[MainFragmentShader]);
178 source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
179 fragShader = new QGLShader(QGLShader::Fragment, context, this);
180 if (!fragShader->compileSourceCode(source))
181 qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
182
183 simpleShaderProg = new QGLShaderProgram(context, this);
184 simpleShaderProg->addShader(vertexShader);
185 simpleShaderProg->addShader(fragShader);
186 simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
187 simpleShaderProg->link();
188 if (!simpleShaderProg->isLinked()) {
189 qCritical() << "Errors linking simple shader:"
190 << simpleShaderProg->log();
191 }
192
193 // Compile the blit shader:
194 source.clear();
195 source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
196 source.append(qShaderSnippets[UntransformedPositionVertexShader]);
197 vertexShader = new QGLShader(QGLShader::Vertex, context, this);
198 if (!vertexShader->compileSourceCode(source))
199 qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
200
201 source.clear();
202 source.append(qShaderSnippets[MainFragmentShader]);
203 source.append(qShaderSnippets[ImageSrcFragmentShader]);
204 fragShader = new QGLShader(QGLShader::Fragment, context, this);
205 if (!fragShader->compileSourceCode(source))
206 qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
207
208 blitShaderProg = new QGLShaderProgram(context, this);
209 blitShaderProg->addShader(vertexShader);
210 blitShaderProg->addShader(fragShader);
211 blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
212 blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
213 blitShaderProg->link();
214 if (!blitShaderProg->isLinked()) {
215 qCritical() << "Errors linking blit shader:"
216 << simpleShaderProg->log();
217 }
218
219}
220
221#if defined (QT_DEBUG)
222QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name)
223{
224 QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
225 return QByteArray(m.valueToKey(name));
226}
227#endif
228
229// The address returned here will only be valid until next time this function is called.
230QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
231{
232 for (int i = 0; i < cachedPrograms.size(); ++i) {
233 QGLEngineShaderProg *cachedProg = cachedPrograms[i];
234 if (*cachedProg == prog) {
235 // Move the program to the top of the list as a poor-man's cache algo
236 cachedPrograms.move(i, 0);
237 return cachedProg;
238 }
239 }
240
241 QGLShader *vertexShader = 0;
242 QGLShader *fragShader = 0;
243 QGLEngineShaderProg *newProg = 0;
244 bool success = false;
245
246 do {
247 QByteArray source;
248 source.append(qShaderSnippets[prog.mainFragShader]);
249 source.append(qShaderSnippets[prog.srcPixelFragShader]);
250 if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
251 source.append(prog.customStageSource);
252 if (prog.compositionFragShader)
253 source.append(qShaderSnippets[prog.compositionFragShader]);
254 if (prog.maskFragShader)
255 source.append(qShaderSnippets[prog.maskFragShader]);
256 fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
257 QByteArray description;
258#if defined(QT_DEBUG)
259 // Name the shader for easier debugging
260 description.append("Fragment shader: main=");
261 description.append(snippetNameStr(prog.mainFragShader));
262 description.append(", srcPixel=");
263 description.append(snippetNameStr(prog.srcPixelFragShader));
264 if (prog.compositionFragShader) {
265 description.append(", composition=");
266 description.append(snippetNameStr(prog.compositionFragShader));
267 }
268 if (prog.maskFragShader) {
269 description.append(", mask=");
270 description.append(snippetNameStr(prog.maskFragShader));
271 }
272 fragShader->setObjectName(QString::fromLatin1(description));
273#endif
274 if (!fragShader->compileSourceCode(source)) {
275 qWarning() << "Warning:" << description << "failed to compile!";
276 break;
277 }
278
279 source.clear();
280 source.append(qShaderSnippets[prog.mainVertexShader]);
281 source.append(qShaderSnippets[prog.positionVertexShader]);
282 vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
283#if defined(QT_DEBUG)
284 // Name the shader for easier debugging
285 description.clear();
286 description.append("Vertex shader: main=");
287 description.append(snippetNameStr(prog.mainVertexShader));
288 description.append(", position=");
289 description.append(snippetNameStr(prog.positionVertexShader));
290 vertexShader->setObjectName(QString::fromLatin1(description));
291#endif
292 if (!vertexShader->compileSourceCode(source)) {
293 qWarning() << "Warning:" << description << "failed to compile!";
294 break;
295 }
296
297 newProg = new QGLEngineShaderProg(prog);
298
299 // If the shader program's not found in the cache, create it now.
300 newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
301 newProg->program->addShader(vertexShader);
302 newProg->program->addShader(fragShader);
303
304 // We have to bind the vertex attribute names before the program is linked:
305 newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
306 if (newProg->useTextureCoords)
307 newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
308 if (newProg->useOpacityAttribute)
309 newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
310
311 newProg->program->link();
312 if (!newProg->program->isLinked()) {
313 QLatin1String none("none");
314 QLatin1String br("\n");
315 QString error;
316 error = QLatin1String("Shader program failed to link,")
317#if defined(QT_DEBUG)
318 + br
319 + QLatin1String(" Shaders Used:") + br
320 + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br
321 + QLatin1String(vertexShader->sourceCode()) + br
322 + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br
323 + QLatin1String(fragShader->sourceCode()) + br
324#endif
325 + QLatin1String(" Error Log:\n")
326 + QLatin1String(" ") + newProg->program->log();
327 qWarning() << error;
328 break;
329 }
330 if (cachedPrograms.count() > 30) {
331 // The cache is full, so delete the last 5 programs in the list.
332 // These programs will be least used, as a program us bumped to
333 // the top of the list when it's used.
334 for (int i = 0; i < 5; ++i) {
335 delete cachedPrograms.last();
336 cachedPrograms.removeLast();
337 }
338 }
339
340 cachedPrograms.insert(0, newProg);
341
342 success = true;
343 } while (false);
344
345 // Clean up everything if we weren't successful
346 if (!success) {
347 if (newProg) {
348 delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders
349 newProg = 0;
350 }
351 else {
352 if (vertexShader)
353 delete vertexShader;
354 if (fragShader)
355 delete fragShader;
356 }
357 }
358
359 return newProg;
360}
361
362void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage)
363{
364 // Remove any shader programs which has this as the custom shader src:
365 for (int i = 0; i < cachedPrograms.size(); ++i) {
366 QGLEngineShaderProg *cachedProg = cachedPrograms[i];
367 if (cachedProg->customStageSource == stage->source()) {
368 delete cachedProg;
369 cachedPrograms.removeAt(i);
370 i--;
371 }
372 }
373}
374
375
376QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
377 : ctx(context),
378 shaderProgNeedsChanging(true),
379 srcPixelType(Qt::NoBrush),
380 opacityMode(NoOpacity),
381 maskType(NoMask),
382 compositionMode(QPainter::CompositionMode_SourceOver),
383 customSrcStage(0),
384 currentShaderProg(0)
385{
386 sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
387 connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot()));
388}
389
390QGLEngineShaderManager::~QGLEngineShaderManager()
391{
392 //###
393 removeCustomStage();
394}
395
396GLuint QGLEngineShaderManager::getUniformLocation(const Uniform id)
397{
398 if (!currentShaderProg)
399 return 0;
400
401 QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
402 if (uniformLocations.isEmpty())
403 uniformLocations.fill(GLuint(-1), NumUniforms);
404
405 static const char *uniformNames[] = {
406 "imageTexture",
407 "patternColor",
408 "globalOpacity",
409 "depth",
410 "pmvMatrix",
411 "maskTexture",
412 "fragmentColor",
413 "linearData",
414 "angle",
415 "halfViewportSize",
416 "fmp",
417 "fmp2_m_radius2",
418 "inverse_2_fmp2_m_radius2",
419 "invertedTextureSize",
420 "brushTransform",
421 "brushTexture"
422 };
423
424 if (uniformLocations.at(id) == GLuint(-1))
425 uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]);
426
427 return uniformLocations.at(id);
428}
429
430
431void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform::TransformationType transformType)
432{
433 Q_UNUSED(transformType); // Currently ignored
434}
435
436void QGLEngineShaderManager::setDirty()
437{
438 shaderProgNeedsChanging = true;
439}
440
441void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
442{
443 Q_ASSERT(style != Qt::NoBrush);
444 if (srcPixelType == PixelSrcType(style))
445 return;
446
447 srcPixelType = style;
448 shaderProgNeedsChanging = true; //###
449}
450
451void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
452{
453 if (srcPixelType == type)
454 return;
455
456 srcPixelType = type;
457 shaderProgNeedsChanging = true; //###
458}
459
460void QGLEngineShaderManager::setOpacityMode(OpacityMode mode)
461{
462 if (opacityMode == mode)
463 return;
464
465 opacityMode = mode;
466 shaderProgNeedsChanging = true; //###
467}
468
469void QGLEngineShaderManager::setMaskType(MaskType type)
470{
471 if (maskType == type)
472 return;
473
474 maskType = type;
475 shaderProgNeedsChanging = true; //###
476}
477
478void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
479{
480 if (compositionMode == mode)
481 return;
482
483 compositionMode = mode;
484 shaderProgNeedsChanging = true; //###
485}
486
487void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage)
488{
489 if (customSrcStage)
490 removeCustomStage();
491 customSrcStage = stage;
492 shaderProgNeedsChanging = true;
493}
494
495void QGLEngineShaderManager::removeCustomStage()
496{
497 if (customSrcStage)
498 customSrcStage->setInactive();
499 customSrcStage = 0;
500 shaderProgNeedsChanging = true;
501}
502
503QGLShaderProgram* QGLEngineShaderManager::currentProgram()
504{
505 if (currentShaderProg)
506 return currentShaderProg->program;
507 else
508 return simpleProgram();
509}
510
511QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
512{
513 return sharedShaders->simpleProgram();
514}
515
516QGLShaderProgram* QGLEngineShaderManager::blitProgram()
517{
518 return sharedShaders->blitProgram();
519}
520
521
522
523// Select & use the correct shader program using the current state.
524// Returns true if program needed changing.
525bool QGLEngineShaderManager::useCorrectShaderProg()
526{
527 if (!shaderProgNeedsChanging)
528 return false;
529
530 bool useCustomSrc = customSrcStage != 0;
531 if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
532 useCustomSrc = false;
533 qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src");
534 }
535
536 QGLEngineShaderProg requiredProgram;
537
538 bool texCoords = false;
539
540 // Choose vertex shader shader position function (which typically also sets
541 // varyings) and the source pixel (srcPixel) fragment shader function:
542 requiredProgram.positionVertexShader = QGLEngineSharedShaders::InvalidSnippetName;
543 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::InvalidSnippetName;
544 bool isAffine = brushTransform.isAffine();
545 if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
546 if (isAffine)
547 requiredProgram.positionVertexShader = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
548 else
549 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
550
551 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::PatternBrushSrcFragmentShader;
552 }
553 else switch (srcPixelType) {
554 default:
555 case Qt::NoBrush:
556 qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
557 break;
558 case QGLEngineShaderManager::ImageSrc:
559 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcFragmentShader;
560 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
561 texCoords = true;
562 break;
563 case QGLEngineShaderManager::NonPremultipliedImageSrc:
564 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
565 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
566 texCoords = true;
567 break;
568 case QGLEngineShaderManager::PatternSrc:
569 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
570 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
571 texCoords = true;
572 break;
573 case QGLEngineShaderManager::TextureSrcWithPattern:
574 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
575 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
576 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
577 break;
578 case Qt::SolidPattern:
579 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::SolidBrushSrcFragmentShader;
580 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
581 break;
582 case Qt::LinearGradientPattern:
583 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
584 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
585 : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
586 break;
587 case Qt::ConicalGradientPattern:
588 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
589 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
590 : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
591 break;
592 case Qt::RadialGradientPattern:
593 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
594 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
595 : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
596 break;
597 case Qt::TexturePattern:
598 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcFragmentShader;
599 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
600 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
601 break;
602 };
603
604 if (useCustomSrc) {
605 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::CustomImageSrcFragmentShader;
606 requiredProgram.customStageSource = customSrcStage->source();
607 }
608
609 const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
610 const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
611
612 // Choose fragment shader main function:
613 if (opacityMode == AttributeOpacity) {
614 Q_ASSERT(!hasCompose && !hasMask);
615 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
616 } else {
617 bool useGlobalOpacity = (opacityMode == UniformOpacity);
618 if (hasCompose && hasMask && useGlobalOpacity)
619 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CMO;
620 if (hasCompose && hasMask && !useGlobalOpacity)
621 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CM;
622 if (!hasCompose && hasMask && useGlobalOpacity)
623 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_MO;
624 if (!hasCompose && hasMask && !useGlobalOpacity)
625 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_M;
626 if (hasCompose && !hasMask && useGlobalOpacity)
627 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CO;
628 if (hasCompose && !hasMask && !useGlobalOpacity)
629 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_C;
630 if (!hasCompose && !hasMask && useGlobalOpacity)
631 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_O;
632 if (!hasCompose && !hasMask && !useGlobalOpacity)
633 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader;
634 }
635
636 if (hasMask) {
637 if (maskType == PixelMask) {
638 requiredProgram.maskFragShader = QGLEngineSharedShaders::MaskFragmentShader;
639 texCoords = true;
640 } else if (maskType == SubPixelMaskPass1) {
641 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
642 texCoords = true;
643 } else if (maskType == SubPixelMaskPass2) {
644 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
645 texCoords = true;
646 } else if (maskType == SubPixelWithGammaMask) {
647 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
648 texCoords = true;
649 } else {
650 qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
651 }
652 } else {
653 requiredProgram.maskFragShader = QGLEngineSharedShaders::NoMaskFragmentShader;
654 }
655
656 if (hasCompose) {
657 switch (compositionMode) {
658 case QPainter::CompositionMode_Multiply:
659 requiredProgram.compositionFragShader = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
660 break;
661 case QPainter::CompositionMode_Screen:
662 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
663 break;
664 case QPainter::CompositionMode_Overlay:
665 requiredProgram.compositionFragShader = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
666 break;
667 case QPainter::CompositionMode_Darken:
668 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
669 break;
670 case QPainter::CompositionMode_Lighten:
671 requiredProgram.compositionFragShader = QGLEngineSharedShaders::LightenCompositionModeFragmentShader;
672 break;
673 case QPainter::CompositionMode_ColorDodge:
674 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
675 break;
676 case QPainter::CompositionMode_ColorBurn:
677 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
678 break;
679 case QPainter::CompositionMode_HardLight:
680 requiredProgram.compositionFragShader = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
681 break;
682 case QPainter::CompositionMode_SoftLight:
683 requiredProgram.compositionFragShader = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
684 break;
685 case QPainter::CompositionMode_Difference:
686 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
687 break;
688 case QPainter::CompositionMode_Exclusion:
689 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
690 break;
691 default:
692 qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
693 }
694 } else {
695 requiredProgram.compositionFragShader = QGLEngineSharedShaders::NoCompositionModeFragmentShader;
696 }
697
698 // Choose vertex shader main function
699 if (opacityMode == AttributeOpacity) {
700 Q_ASSERT(texCoords);
701 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
702 } else if (texCoords) {
703 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
704 } else {
705 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainVertexShader;
706 }
707 requiredProgram.useTextureCoords = texCoords;
708 requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
709
710 // At this point, requiredProgram is fully populated so try to find the program in the cache
711 currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
712
713 if (currentShaderProg) {
714 currentShaderProg->program->bind();
715 if (useCustomSrc)
716 customSrcStage->setUniforms(currentShaderProg->program);
717 }
718
719 shaderProgNeedsChanging = false;
720 return true;
721}
722
723QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.