src/opengl/gl2paintengineex/qglengineshadermanager.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    64         qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context));
    64         qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context));
    65     }
    65     }
    66     return p;
    66     return p;
    67 }
    67 }
    68 
    68 
    69 const char* QGLEngineSharedShaders::qglEngineShaderSourceCode[] = {
    69 const char* QGLEngineSharedShaders::qShaderSnippets[] = {
    70     0,0,0,0,0,0,0,0,0,0,
    70     0,0,0,0,0,0,0,0,0,0,
    71     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,
    72     0,0,0,0,0,0,0,0,0,0,
    73     0,0,0,0,0
    73     0,0,0,0,0
    74 };
    74 };
    76 QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
    76 QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
    77     : ctxGuard(context)
    77     : ctxGuard(context)
    78     , blitShaderProg(0)
    78     , blitShaderProg(0)
    79     , simpleShaderProg(0)
    79     , simpleShaderProg(0)
    80 {
    80 {
    81     memset(compiledShaders, 0, sizeof(compiledShaders));
       
    82 
    81 
    83 /*
    82 /*
    84     Rather than having the shader source array statically initialised, it is initialised
    83     Rather than having the shader source array statically initialised, it is initialised
    85     here instead. This is to allow new shader names to be inserted or existing names moved
    84     here instead. This is to allow new shader names to be inserted or existing names moved
    86     around without having to change the order of the glsl strings. It is hoped this will
    85     around without having to change the order of the glsl strings. It is hoped this will
    87     make future hard-to-find runtime bugs more obvious and generally give more solid code.
    86     make future hard-to-find runtime bugs more obvious and generally give more solid code.
    88 */
    87 */
    89     static bool qglEngineShaderSourceCodePopulated = false;
    88     static bool snippetsPopulated = false;
    90     if (!qglEngineShaderSourceCodePopulated) {
    89     if (!snippetsPopulated) {
    91 
    90 
    92         const char** code = qglEngineShaderSourceCode; // shortcut
    91         const char** code = qShaderSnippets; // shortcut
    93 
    92 
    94         code[MainVertexShader] = qglslMainVertexShader;
    93         code[MainVertexShader] = qglslMainVertexShader;
    95         code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
    94         code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
    96         code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
    95         code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
    97 
    96 
   119         code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
   118         code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
   120 
   119 
   121         code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
   120         code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
   122         code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
   121         code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
   123         code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
   122         code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
   124         code[CustomImageSrcFragmentShader] = ""; // Supplied by app.
   123         code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
   125         code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
   124         code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
   126         code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
   125         code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
   127         code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
   126         code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
   128         code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
   127         code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
   129         code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
   128         code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
   130         code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
   129         code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
   131         code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
   130         code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
   132         code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
   131         code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
   133 
   132 
       
   133         code[NoMaskFragmentShader] = "";
   134         code[MaskFragmentShader] = qglslMaskFragmentShader;
   134         code[MaskFragmentShader] = qglslMaskFragmentShader;
   135         code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1;
   135         code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1;
   136         code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2;
   136         code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2;
   137         code[RgbMaskWithGammaFragmentShader] = ""; //###
   137         code[RgbMaskWithGammaFragmentShader] = ""; //###
   138 
   138 
       
   139         code[NoCompositionModeFragmentShader] = "";
   139         code[MultiplyCompositionModeFragmentShader] = ""; //###
   140         code[MultiplyCompositionModeFragmentShader] = ""; //###
   140         code[ScreenCompositionModeFragmentShader] = ""; //###
   141         code[ScreenCompositionModeFragmentShader] = ""; //###
   141         code[OverlayCompositionModeFragmentShader] = ""; //###
   142         code[OverlayCompositionModeFragmentShader] = ""; //###
   142         code[DarkenCompositionModeFragmentShader] = ""; //###
   143         code[DarkenCompositionModeFragmentShader] = ""; //###
   143         code[LightenCompositionModeFragmentShader] = ""; //###
   144         code[LightenCompositionModeFragmentShader] = ""; //###
   148         code[DifferenceCompositionModeFragmentShader] = ""; //###
   149         code[DifferenceCompositionModeFragmentShader] = ""; //###
   149         code[ExclusionCompositionModeFragmentShader] = ""; //###
   150         code[ExclusionCompositionModeFragmentShader] = ""; //###
   150 
   151 
   151 #if defined(QT_DEBUG)
   152 #if defined(QT_DEBUG)
   152         // Check that all the elements have been filled:
   153         // Check that all the elements have been filled:
   153         for (int i = 0; i < TotalShaderCount; ++i) {
   154         for (int i = 0; i < TotalSnippetCount; ++i) {
   154             if (qglEngineShaderSourceCode[i] == 0) {
   155             if (qShaderSnippets[i] == 0) {
   155                 int enumIndex = staticMetaObject.indexOfEnumerator("ShaderName");
   156                 qFatal("Shader snippet for %s (#%d) is missing!",
   156                 QMetaEnum m = staticMetaObject.enumerator(enumIndex);
   157                        snippetNameStr(SnippetName(i)).constData(), i);
   157 
       
   158                 qCritical() << "qglEngineShaderSourceCode: Source for" << m.valueToKey(i)
       
   159                             << "(shader" << i << ") missing!";
       
   160             }
   158             }
   161         }
   159         }
   162 #endif
   160 #endif
   163         qglEngineShaderSourceCodePopulated = true;
   161         snippetsPopulated = true;
   164     }
   162     }
       
   163 
       
   164     QGLShader* fragShader;
       
   165     QGLShader* vertexShader;
       
   166     QByteArray source;
   165 
   167 
   166     // Compile up the simple shader:
   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     vertexShader->compileSourceCode(source);
       
   174 
       
   175     source.clear();
       
   176     source.append(qShaderSnippets[MainFragmentShader]);
       
   177     source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
       
   178     fragShader = new QGLShader(QGLShader::Fragment, context, this);
       
   179     fragShader->compileSourceCode(source);
       
   180 
   167     simpleShaderProg = new QGLShaderProgram(context, this);
   181     simpleShaderProg = new QGLShaderProgram(context, this);
   168     compileNamedShader(MainVertexShader,              QGLShader::PartialVertexShader);
   182     simpleShaderProg->addShader(vertexShader);
   169     compileNamedShader(PositionOnlyVertexShader,      QGLShader::PartialVertexShader);
   183     simpleShaderProg->addShader(fragShader);
   170     compileNamedShader(MainFragmentShader,            QGLShader::PartialFragmentShader);
       
   171     compileNamedShader(ShockingPinkSrcFragmentShader, QGLShader::PartialFragmentShader);
       
   172     simpleShaderProg->addShader(compiledShaders[MainVertexShader]);
       
   173     simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]);
       
   174     simpleShaderProg->addShader(compiledShaders[MainFragmentShader]);
       
   175     simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]);
       
   176     simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   184     simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   177     simpleShaderProg->link();
   185     simpleShaderProg->link();
   178     if (!simpleShaderProg->isLinked()) {
   186     if (!simpleShaderProg->isLinked()) {
   179         qCritical() << "Errors linking simple shader:"
   187         qCritical() << "Errors linking simple shader:"
   180                     << simpleShaderProg->log();
   188                     << simpleShaderProg->log();
   181     }
   189     }
   182 
   190 
   183     // Compile the blit shader:
   191     // Compile the blit shader:
       
   192     source.clear();
       
   193     source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
       
   194     source.append(qShaderSnippets[UntransformedPositionVertexShader]);
       
   195     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
       
   196     vertexShader->compileSourceCode(source);
       
   197 
       
   198     source.clear();
       
   199     source.append(qShaderSnippets[MainFragmentShader]);
       
   200     source.append(qShaderSnippets[ImageSrcFragmentShader]);
       
   201     fragShader = new QGLShader(QGLShader::Fragment, context, this);
       
   202     fragShader->compileSourceCode(source);
       
   203 
   184     blitShaderProg = new QGLShaderProgram(context, this);
   204     blitShaderProg = new QGLShaderProgram(context, this);
   185     compileNamedShader(MainWithTexCoordsVertexShader,     QGLShader::PartialVertexShader);
   205     blitShaderProg->addShader(vertexShader);
   186     compileNamedShader(UntransformedPositionVertexShader, QGLShader::PartialVertexShader);
   206     blitShaderProg->addShader(fragShader);
   187     compileNamedShader(MainFragmentShader,                QGLShader::PartialFragmentShader);
       
   188     compileNamedShader(ImageSrcFragmentShader,            QGLShader::PartialFragmentShader);
       
   189     blitShaderProg->addShader(compiledShaders[MainWithTexCoordsVertexShader]);
       
   190     blitShaderProg->addShader(compiledShaders[UntransformedPositionVertexShader]);
       
   191     blitShaderProg->addShader(compiledShaders[MainFragmentShader]);
       
   192     blitShaderProg->addShader(compiledShaders[ImageSrcFragmentShader]);
       
   193     blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   207     blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   194     blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   208     blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   195     blitShaderProg->link();
   209     blitShaderProg->link();
   196     if (!blitShaderProg->isLinked()) {
   210     if (!blitShaderProg->isLinked()) {
   197         qCritical() << "Errors linking blit shader:"
   211         qCritical() << "Errors linking blit shader:"
   198                     << blitShaderProg->log();
   212                     << simpleShaderProg->log();
   199     }
   213     }
   200 }
   214 
   201 
   215 }
   202 void QGLEngineSharedShaders::shaderDestroyed(QObject *shader)
   216 
   203 {
   217 #if defined (QT_DEBUG)
   204     // Remove any shader programs which has this as the srcPixel shader:
   218 QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name)
   205     for (int i = 0; i < cachedPrograms.size(); ++i) {
   219 {
   206         if (cachedPrograms.at(i).srcPixelFragShader == shader) {
   220     QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
   207             delete cachedPrograms.at(i).program;
   221     return QByteArray(m.valueToKey(name));
   208             cachedPrograms.removeAt(i--);
   222 }
   209         }
       
   210     }
       
   211 
       
   212     emit shaderProgNeedsChanging();
       
   213 }
       
   214 
       
   215 QGLShader *QGLEngineSharedShaders::compileNamedShader(ShaderName name, QGLShader::ShaderType type)
       
   216 {
       
   217     Q_ASSERT(name != CustomImageSrcFragmentShader);
       
   218     Q_ASSERT(name < InvalidShaderName);
       
   219 
       
   220     if (compiledShaders[name])
       
   221         return compiledShaders[name];
       
   222 
       
   223     QByteArray source = qglEngineShaderSourceCode[name];
       
   224     QGLShader *newShader = new QGLShader(type, ctxGuard.context(), this);
       
   225     newShader->compile(source);
       
   226 
       
   227 #if defined(QT_DEBUG)
       
   228     // Name the shader for easier debugging
       
   229     QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName"));
       
   230     newShader->setObjectName(QLatin1String(m.valueToKey(name)));
       
   231 #endif
   223 #endif
   232 
       
   233     compiledShaders[name] = newShader;
       
   234     return newShader;
       
   235 }
       
   236 
       
   237 QGLShader *QGLEngineSharedShaders::compileCustomShader(QGLCustomShaderStage *stage, QGLShader::ShaderType type)
       
   238 {
       
   239     QByteArray source = stage->source();
       
   240     source += qglslCustomSrcFragmentShader;
       
   241 
       
   242     QGLShader *newShader = customShaderCache.object(source);
       
   243     if (newShader)
       
   244         return newShader;
       
   245 
       
   246     newShader = new QGLShader(type, ctxGuard.context(), this);
       
   247     newShader->compile(source);
       
   248     customShaderCache.insert(source, newShader);
       
   249 
       
   250     connect(newShader, SIGNAL(destroyed(QObject *)),
       
   251             this, SLOT(shaderDestroyed(QObject *)));
       
   252 
       
   253 #if defined(QT_DEBUG)
       
   254     // Name the shader for easier debugging
       
   255     QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName"));
       
   256     newShader->setObjectName(QLatin1String(m.valueToKey(CustomImageSrcFragmentShader)));
       
   257 #endif
       
   258 
       
   259     return newShader;
       
   260 }
       
   261 
   224 
   262 // The address returned here will only be valid until next time this function is called.
   225 // The address returned here will only be valid until next time this function is called.
   263 QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
   226 QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
   264 {
   227 {
   265     for (int i = 0; i < cachedPrograms.size(); ++i) {
   228     for (int i = 0; i < cachedPrograms.size(); ++i) {
   266         if (cachedPrograms[i] == prog)
   229         QGLEngineShaderProg *cachedProg = cachedPrograms[i];
   267             return &cachedPrograms[i];
   230         if (*cachedProg == prog) {
   268     }
   231             // Move the program to the top of the list as a poor-man's cache algo
   269 
   232             cachedPrograms.move(i, 0);
   270     cachedPrograms.append(prog);
   233             return cachedProg;
   271     QGLEngineShaderProg &cached = cachedPrograms.last();
   234         }
       
   235     }
       
   236 
       
   237     QByteArray source;
       
   238     source.append(qShaderSnippets[prog.mainFragShader]);
       
   239     source.append(qShaderSnippets[prog.srcPixelFragShader]);
       
   240     if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
       
   241         source.append(prog.customStageSource);
       
   242     if (prog.compositionFragShader)
       
   243         source.append(qShaderSnippets[prog.compositionFragShader]);
       
   244     if (prog.maskFragShader)
       
   245         source.append(qShaderSnippets[prog.maskFragShader]);
       
   246     QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
       
   247     fragShader->compileSourceCode(source);
       
   248 
       
   249     source.clear();
       
   250     source.append(qShaderSnippets[prog.mainVertexShader]);
       
   251     source.append(qShaderSnippets[prog.positionVertexShader]);
       
   252     QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
       
   253     vertexShader->compileSourceCode(source);
       
   254 
       
   255 #if defined(QT_DEBUG)
       
   256     // Name the shaders for easier debugging
       
   257     QByteArray description;
       
   258     description.append("Fragment shader: main=");
       
   259     description.append(snippetNameStr(prog.mainFragShader));
       
   260     description.append(", srcPixel=");
       
   261     description.append(snippetNameStr(prog.srcPixelFragShader));
       
   262     if (prog.compositionFragShader) {
       
   263         description.append(", composition=");
       
   264         description.append(snippetNameStr(prog.compositionFragShader));
       
   265     }
       
   266     if (prog.maskFragShader) {
       
   267         description.append(", mask=");
       
   268         description.append(snippetNameStr(prog.maskFragShader));
       
   269     }
       
   270     fragShader->setObjectName(QString::fromLatin1(description));
       
   271 
       
   272     description.clear();
       
   273     description.append("Vertex shader: main=");
       
   274     description.append(snippetNameStr(prog.mainVertexShader));
       
   275     description.append(", position=");
       
   276     description.append(snippetNameStr(prog.positionVertexShader));
       
   277     vertexShader->setObjectName(QString::fromLatin1(description));
       
   278 #endif
       
   279 
       
   280     QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog);
   272 
   281 
   273     // If the shader program's not found in the cache, create it now.
   282     // If the shader program's not found in the cache, create it now.
   274     cached.program = new QGLShaderProgram(ctxGuard.context(), this);
   283     newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
   275     cached.program->addShader(cached.mainVertexShader);
   284     newProg->program->addShader(vertexShader);
   276     cached.program->addShader(cached.positionVertexShader);
   285     newProg->program->addShader(fragShader);
   277     cached.program->addShader(cached.mainFragShader);
       
   278     cached.program->addShader(cached.srcPixelFragShader);
       
   279     cached.program->addShader(cached.maskFragShader);
       
   280     cached.program->addShader(cached.compositionFragShader);
       
   281 
   286 
   282     // We have to bind the vertex attribute names before the program is linked:
   287     // We have to bind the vertex attribute names before the program is linked:
   283     cached.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   288     newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   284     if (cached.useTextureCoords)
   289     if (newProg->useTextureCoords)
   285         cached.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   290         newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   286     if (cached.useOpacityAttribute)
   291     if (newProg->useOpacityAttribute)
   287         cached.program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
   292         newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
   288 
   293 
   289     cached.program->link();
   294     newProg->program->link();
   290     if (!cached.program->isLinked()) {
   295     if (!newProg->program->isLinked()) {
   291         QLatin1String none("none");
   296         QLatin1String none("none");
   292         QLatin1String br("\n");
   297         QLatin1String br("\n");
   293         QString error;
   298         QString error;
   294         error = QLatin1String("Shader program failed to link,")
   299         error = QLatin1String("Shader program failed to link,")
   295 #if defined(QT_DEBUG)
   300 #if defined(QT_DEBUG)
   296             + br
   301             + br
   297             + QLatin1String("  Shaders Used:\n")
   302             + QLatin1String("  Shaders Used:") + br
   298             + QLatin1String("    mainVertexShader = ")
   303             + QLatin1String("    ") + vertexShader->objectName() + QLatin1String(": ") + br
   299             + (cached.mainVertexShader ?
   304             + QLatin1String(vertexShader->sourceCode()) + br
   300                 cached.mainVertexShader->objectName() : none) + br
   305             + QLatin1String("    ") + fragShader->objectName() + QLatin1String(": ") + br
   301             + QLatin1String("    positionVertexShader = ")
   306             + QLatin1String(fragShader->sourceCode()) + br
   302             + (cached.positionVertexShader ?
       
   303                 cached.positionVertexShader->objectName() : none) + br
       
   304             + QLatin1String("    mainFragShader = ")
       
   305             + (cached.mainFragShader ?
       
   306                 cached.mainFragShader->objectName() : none) + br
       
   307             + QLatin1String("    srcPixelFragShader = ")
       
   308             + (cached.srcPixelFragShader ?
       
   309                 cached.srcPixelFragShader->objectName() : none) + br
       
   310             + QLatin1String("    maskFragShader = ")
       
   311             + (cached.maskFragShader ?
       
   312                 cached.maskFragShader->objectName() : none) + br
       
   313             + QLatin1String("    compositionFragShader = ")
       
   314             + (cached.compositionFragShader ?
       
   315                 cached.compositionFragShader->objectName() : none) + br
       
   316 #endif
   307 #endif
   317             + QLatin1String("  Error Log:\n")
   308             + QLatin1String("  Error Log:\n")
   318             + QLatin1String("    ") + cached.program->log();
   309             + QLatin1String("    ") + newProg->program->log();
   319         qWarning() << error;
   310         qWarning() << error;
   320         delete cached.program;
   311         delete newProg; // Deletes the QGLShaderProgram in it's destructor
   321         cachedPrograms.removeLast();
   312         newProg = 0;
   322         return 0;
   313     }
   323     } else {
   314     else {
   324         // taking the address here is safe since
   315         if (cachedPrograms.count() > 30) {
   325         // cachePrograms isn't resized anywhere else
   316             // The cache is full, so delete the last 5 programs in the list.
   326         return &cached;
   317             // These programs will be least used, as a program us bumped to
   327     }
   318             // the top of the list when it's used.
   328 }
   319             for (int i = 0; i < 5; ++i) {
       
   320                 delete cachedPrograms.last();
       
   321                 cachedPrograms.removeLast();
       
   322             }
       
   323         }
       
   324 
       
   325         cachedPrograms.insert(0, newProg);
       
   326     }
       
   327 
       
   328     return newProg;
       
   329 }
       
   330 
       
   331 void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage)
       
   332 {
       
   333     // Remove any shader programs which has this as the custom shader src:
       
   334     for (int i = 0; i < cachedPrograms.size(); ++i) {
       
   335         QGLEngineShaderProg *cachedProg = cachedPrograms[i];
       
   336         if (cachedProg->customStageSource == stage->source()) {
       
   337             delete cachedProg;
       
   338             cachedPrograms.removeAt(i);
       
   339             i--;
       
   340         }
       
   341     }
       
   342 }
       
   343 
   329 
   344 
   330 QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
   345 QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
   331     : ctx(context),
   346     : ctx(context),
   332       shaderProgNeedsChanging(true),
   347       shaderProgNeedsChanging(true),
   333       srcPixelType(Qt::NoBrush),
   348       srcPixelType(Qt::NoBrush),
   334       opacityMode(NoOpacity),
   349       opacityMode(NoOpacity),
   335       maskType(NoMask),
   350       maskType(NoMask),
   336       compositionMode(QPainter::CompositionMode_SourceOver),
   351       compositionMode(QPainter::CompositionMode_SourceOver),
   337       customSrcStage(0),
   352       customSrcStage(0),
   338       currentShaderProg(0),
   353       currentShaderProg(0)
   339       customShader(0)
       
   340 {
   354 {
   341     sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
   355     sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
   342     connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot()));
   356     connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot()));
   343 }
   357 }
   344 
   358 
   345 QGLEngineShaderManager::~QGLEngineShaderManager()
   359 QGLEngineShaderManager::~QGLEngineShaderManager()
   346 {
   360 {
   347     //###
   361     //###
       
   362     removeCustomStage();
   348 }
   363 }
   349 
   364 
   350 uint QGLEngineShaderManager::getUniformLocation(Uniform id)
   365 uint QGLEngineShaderManager::getUniformLocation(Uniform id)
   351 {
   366 {
   352     QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
   367     QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
   389     shaderProgNeedsChanging = true;
   404     shaderProgNeedsChanging = true;
   390 }
   405 }
   391 
   406 
   392 void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
   407 void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
   393 {
   408 {
       
   409     Q_ASSERT(style != Qt::NoBrush);
   394     if (srcPixelType == PixelSrcType(style))
   410     if (srcPixelType == PixelSrcType(style))
   395         return;
   411         return;
   396 
   412 
   397     srcPixelType = style;
   413     srcPixelType = style;
   398     shaderProgNeedsChanging = true; //###
   414     shaderProgNeedsChanging = true; //###
   434     shaderProgNeedsChanging = true; //###
   450     shaderProgNeedsChanging = true; //###
   435 }
   451 }
   436 
   452 
   437 void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage)
   453 void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage)
   438 {
   454 {
       
   455     if (customSrcStage)
       
   456         removeCustomStage();
   439     customSrcStage = stage;
   457     customSrcStage = stage;
   440     customShader = 0; // Will be compiled from 'customSrcStage' later.
       
   441     shaderProgNeedsChanging = true;
   458     shaderProgNeedsChanging = true;
   442 }
   459 }
   443 
   460 
   444 void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage)
   461 void QGLEngineShaderManager::removeCustomStage()
   445 {
   462 {
   446     Q_UNUSED(stage); // Currently we only support one at a time...
   463     if (customSrcStage)
   447 
   464         customSrcStage->setInactive();
   448     customSrcStage = 0;
   465     customSrcStage = 0;
   449     customShader = 0;
       
   450     shaderProgNeedsChanging = true;
   466     shaderProgNeedsChanging = true;
   451 }
   467 }
   452 
       
   453 
   468 
   454 QGLShaderProgram* QGLEngineShaderManager::currentProgram()
   469 QGLShaderProgram* QGLEngineShaderManager::currentProgram()
   455 {
   470 {
   456     return currentShaderProg->program;
   471     return currentShaderProg->program;
   457 }
   472 }
   474 {
   489 {
   475     if (!shaderProgNeedsChanging)
   490     if (!shaderProgNeedsChanging)
   476         return false;
   491         return false;
   477 
   492 
   478     bool useCustomSrc = customSrcStage != 0;
   493     bool useCustomSrc = customSrcStage != 0;
   479     if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc) {
   494     if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
   480         useCustomSrc = false;
   495         useCustomSrc = false;
   481         qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src");
   496         qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src");
   482     }
   497     }
   483 
   498 
   484     QGLEngineShaderProg requiredProgram;
   499     QGLEngineShaderProg requiredProgram;
   485     requiredProgram.program = 0;
       
   486 
   500 
   487     bool texCoords = false;
   501     bool texCoords = false;
   488 
   502 
   489     // Choose vertex shader shader position function (which typically also sets
   503     // Choose vertex shader shader position function (which typically also sets
   490     // varyings) and the source pixel (srcPixel) fragment shader function:
   504     // varyings) and the source pixel (srcPixel) fragment shader function:
   491     QGLEngineSharedShaders::ShaderName positionVertexShaderName = QGLEngineSharedShaders::InvalidShaderName;
   505     requiredProgram.positionVertexShader = QGLEngineSharedShaders::InvalidSnippetName;
   492     QGLEngineSharedShaders::ShaderName srcPixelFragShaderName = QGLEngineSharedShaders::InvalidShaderName;
   506     requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::InvalidSnippetName;
   493     bool isAffine = brushTransform.isAffine();
   507     bool isAffine = brushTransform.isAffine();
   494     if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
   508     if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
   495         if (isAffine)
   509         if (isAffine)
   496             positionVertexShaderName = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
   510             requiredProgram.positionVertexShader = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
   497         else
   511         else
   498             positionVertexShaderName = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
   512             requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
   499 
   513 
   500         srcPixelFragShaderName = QGLEngineSharedShaders::PatternBrushSrcFragmentShader;
   514         requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::PatternBrushSrcFragmentShader;
   501     }
   515     }
   502     else switch (srcPixelType) {
   516     else switch (srcPixelType) {
   503         default:
   517         default:
   504         case Qt::NoBrush:
   518         case Qt::NoBrush:
   505             qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
   519             qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
   506             break;
   520             break;
   507         case QGLEngineShaderManager::ImageSrc:
   521         case QGLEngineShaderManager::ImageSrc:
   508             srcPixelFragShaderName = QGLEngineSharedShaders::ImageSrcFragmentShader;
   522             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcFragmentShader;
   509             positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader;
   523             requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
   510             texCoords = true;
   524             texCoords = true;
   511             break;
   525             break;
   512         case QGLEngineShaderManager::NonPremultipliedImageSrc:
   526         case QGLEngineShaderManager::NonPremultipliedImageSrc:
   513             srcPixelFragShaderName = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
   527             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
   514             positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader;
   528             requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
   515             texCoords = true;
   529             texCoords = true;
   516             break;
   530             break;
   517         case QGLEngineShaderManager::PatternSrc:
   531         case QGLEngineShaderManager::PatternSrc:
   518             srcPixelFragShaderName = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
   532             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
   519             positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader;
   533             requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
   520             texCoords = true;
   534             texCoords = true;
   521             break;
   535             break;
   522         case QGLEngineShaderManager::TextureSrcWithPattern:
   536         case QGLEngineShaderManager::TextureSrcWithPattern:
   523             srcPixelFragShaderName = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
   537             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
   524             positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
   538             requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
   525                                                 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
   539                                                 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
   526             break;
   540             break;
   527         case Qt::SolidPattern:
   541         case Qt::SolidPattern:
   528             srcPixelFragShaderName = QGLEngineSharedShaders::SolidBrushSrcFragmentShader;
   542             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::SolidBrushSrcFragmentShader;
   529             positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader;
   543             requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
   530             break;
   544             break;
   531         case Qt::LinearGradientPattern:
   545         case Qt::LinearGradientPattern:
   532             srcPixelFragShaderName = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
   546             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
   533             positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
   547             requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
   534                                                 : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
   548                                                 : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
   535             break;
   549             break;
   536         case Qt::ConicalGradientPattern:
   550         case Qt::ConicalGradientPattern:
   537             srcPixelFragShaderName = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
   551             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
   538             positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
   552             requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
   539                                                 : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
   553                                                 : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
   540             break;
   554             break;
   541         case Qt::RadialGradientPattern:
   555         case Qt::RadialGradientPattern:
   542             srcPixelFragShaderName = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
   556             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
   543             positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
   557             requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
   544                                                 : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
   558                                                 : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
   545             break;
   559             break;
   546         case Qt::TexturePattern:
   560         case Qt::TexturePattern:
   547             srcPixelFragShaderName = QGLEngineSharedShaders::TextureBrushSrcFragmentShader;
   561             requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcFragmentShader;
   548             positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
   562             requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
   549                                                 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
   563                                                 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
   550             break;
   564             break;
   551     };
   565     };
   552     requiredProgram.positionVertexShader = sharedShaders->compileNamedShader(positionVertexShaderName, QGLShader::PartialVertexShader);
   566 
   553     if (useCustomSrc) {
   567     if (useCustomSrc) {
   554         if (!customShader)
   568         requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::CustomImageSrcFragmentShader;
   555             customShader = sharedShaders->compileCustomShader(customSrcStage, QGLShader::PartialFragmentShader);
   569         requiredProgram.customStageSource = customSrcStage->source();
   556         requiredProgram.srcPixelFragShader = customShader;
       
   557     } else {
       
   558         requiredProgram.srcPixelFragShader = sharedShaders->compileNamedShader(srcPixelFragShaderName, QGLShader::PartialFragmentShader);
       
   559     }
   570     }
   560 
   571 
   561     const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
   572     const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
   562     const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
   573     const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
   563 
   574 
   564     // Choose fragment shader main function:
   575     // Choose fragment shader main function:
   565     QGLEngineSharedShaders::ShaderName mainFragShaderName;
       
   566 
       
   567     if (opacityMode == AttributeOpacity) {
   576     if (opacityMode == AttributeOpacity) {
   568         Q_ASSERT(!hasCompose && !hasMask);
   577         Q_ASSERT(!hasCompose && !hasMask);
   569         mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
   578         requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
   570     } else {
   579     } else {
   571         bool useGlobalOpacity = (opacityMode == UniformOpacity);
   580         bool useGlobalOpacity = (opacityMode == UniformOpacity);
   572         if (hasCompose && hasMask && useGlobalOpacity)
   581         if (hasCompose && hasMask && useGlobalOpacity)
   573             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CMO;
   582             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CMO;
   574         if (hasCompose && hasMask && !useGlobalOpacity)
   583         if (hasCompose && hasMask && !useGlobalOpacity)
   575             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CM;
   584             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CM;
   576         if (!hasCompose && hasMask && useGlobalOpacity)
   585         if (!hasCompose && hasMask && useGlobalOpacity)
   577             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_MO;
   586             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_MO;
   578         if (!hasCompose && hasMask && !useGlobalOpacity)
   587         if (!hasCompose && hasMask && !useGlobalOpacity)
   579             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_M;
   588             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_M;
   580         if (hasCompose && !hasMask && useGlobalOpacity)
   589         if (hasCompose && !hasMask && useGlobalOpacity)
   581             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CO;
   590             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CO;
   582         if (hasCompose && !hasMask && !useGlobalOpacity)
   591         if (hasCompose && !hasMask && !useGlobalOpacity)
   583             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_C;
   592             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_C;
   584         if (!hasCompose && !hasMask && useGlobalOpacity)
   593         if (!hasCompose && !hasMask && useGlobalOpacity)
   585             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_O;
   594             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_O;
   586         if (!hasCompose && !hasMask && !useGlobalOpacity)
   595         if (!hasCompose && !hasMask && !useGlobalOpacity)
   587             mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader;
   596             requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader;
   588     }
   597     }
   589 
       
   590     requiredProgram.mainFragShader = sharedShaders->compileNamedShader(mainFragShaderName, QGLShader::PartialFragmentShader);
       
   591 
   598 
   592     if (hasMask) {
   599     if (hasMask) {
   593         QGLEngineSharedShaders::ShaderName maskShaderName = QGLEngineSharedShaders::InvalidShaderName;
       
   594         if (maskType == PixelMask) {
   600         if (maskType == PixelMask) {
   595             maskShaderName = QGLEngineSharedShaders::MaskFragmentShader;
   601             requiredProgram.maskFragShader = QGLEngineSharedShaders::MaskFragmentShader;
   596             texCoords = true;
   602             texCoords = true;
   597         } else if (maskType == SubPixelMaskPass1) {
   603         } else if (maskType == SubPixelMaskPass1) {
   598             maskShaderName = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
   604             requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
   599             texCoords = true;
   605             texCoords = true;
   600         } else if (maskType == SubPixelMaskPass2) {
   606         } else if (maskType == SubPixelMaskPass2) {
   601             maskShaderName = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
   607             requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
   602             texCoords = true;
   608             texCoords = true;
   603         } else if (maskType == SubPixelWithGammaMask) {
   609         } else if (maskType == SubPixelWithGammaMask) {
   604             maskShaderName = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
   610             requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
   605             texCoords = true;
   611             texCoords = true;
   606         } else {
   612         } else {
   607             qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
   613             qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
   608         }
   614         }
   609 
       
   610         requiredProgram.maskFragShader = sharedShaders->compileNamedShader(maskShaderName, QGLShader::PartialFragmentShader);
       
   611     } else {
   615     } else {
   612         requiredProgram.maskFragShader = 0;
   616         requiredProgram.maskFragShader = QGLEngineSharedShaders::NoMaskFragmentShader;
   613     }
   617     }
   614 
   618 
   615     if (hasCompose) {
   619     if (hasCompose) {
   616         QGLEngineSharedShaders::ShaderName compositionShaderName = QGLEngineSharedShaders::InvalidShaderName;
       
   617         switch (compositionMode) {
   620         switch (compositionMode) {
   618             case QPainter::CompositionMode_Multiply:
   621             case QPainter::CompositionMode_Multiply:
   619                 compositionShaderName = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
   622                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
   620                 break;
   623                 break;
   621             case QPainter::CompositionMode_Screen:
   624             case QPainter::CompositionMode_Screen:
   622                 compositionShaderName = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
   625                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
   623                 break;
   626                 break;
   624             case QPainter::CompositionMode_Overlay:
   627             case QPainter::CompositionMode_Overlay:
   625                 compositionShaderName = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
   628                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
   626                 break;
   629                 break;
   627             case QPainter::CompositionMode_Darken:
   630             case QPainter::CompositionMode_Darken:
   628                 compositionShaderName = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
   631                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
   629                 break;
   632                 break;
   630             case QPainter::CompositionMode_Lighten:
   633             case QPainter::CompositionMode_Lighten:
   631                 compositionShaderName = QGLEngineSharedShaders::LightenCompositionModeFragmentShader;
   634                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::LightenCompositionModeFragmentShader;
   632                 break;
   635                 break;
   633             case QPainter::CompositionMode_ColorDodge:
   636             case QPainter::CompositionMode_ColorDodge:
   634                 compositionShaderName = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
   637                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
   635                 break;
   638                 break;
   636             case QPainter::CompositionMode_ColorBurn:
   639             case QPainter::CompositionMode_ColorBurn:
   637                 compositionShaderName = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
   640                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
   638                 break;
   641                 break;
   639             case QPainter::CompositionMode_HardLight:
   642             case QPainter::CompositionMode_HardLight:
   640                 compositionShaderName = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
   643                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
   641                 break;
   644                 break;
   642             case QPainter::CompositionMode_SoftLight:
   645             case QPainter::CompositionMode_SoftLight:
   643                 compositionShaderName = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
   646                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
   644                 break;
   647                 break;
   645             case QPainter::CompositionMode_Difference:
   648             case QPainter::CompositionMode_Difference:
   646                 compositionShaderName = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
   649                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
   647                 break;
   650                 break;
   648             case QPainter::CompositionMode_Exclusion:
   651             case QPainter::CompositionMode_Exclusion:
   649                 compositionShaderName = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
   652                 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
   650                 break;
   653                 break;
   651             default:
   654             default:
   652                 qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
   655                 qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
   653         }
   656         }
   654         requiredProgram.compositionFragShader = sharedShaders->compileNamedShader(compositionShaderName, QGLShader::PartialFragmentShader);
       
   655     } else {
   657     } else {
   656         requiredProgram.compositionFragShader = 0;
   658         requiredProgram.compositionFragShader = QGLEngineSharedShaders::NoCompositionModeFragmentShader;
   657     }
   659     }
   658 
   660 
   659         // Choose vertex shader main function
   661     // Choose vertex shader main function
   660     QGLEngineSharedShaders::ShaderName mainVertexShaderName = QGLEngineSharedShaders::InvalidShaderName;
       
   661     if (opacityMode == AttributeOpacity) {
   662     if (opacityMode == AttributeOpacity) {
   662         Q_ASSERT(texCoords);
   663         Q_ASSERT(texCoords);
   663         mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
   664         requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
   664     } else if (texCoords) {
   665     } else if (texCoords) {
   665         mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
   666         requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
   666     } else {
   667     } else {
   667         mainVertexShaderName = QGLEngineSharedShaders::MainVertexShader;
   668         requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainVertexShader;
   668     }
   669     }
   669     requiredProgram.mainVertexShader = sharedShaders->compileNamedShader(mainVertexShaderName, QGLShader::PartialVertexShader);
       
   670     requiredProgram.useTextureCoords = texCoords;
   670     requiredProgram.useTextureCoords = texCoords;
   671     requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
   671     requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
   672 
   672 
   673 
       
   674     // At this point, requiredProgram is fully populated so try to find the program in the cache
   673     // At this point, requiredProgram is fully populated so try to find the program in the cache
   675     currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
   674     currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
   676 
   675 
   677     if (currentShaderProg) {
   676     if (currentShaderProg) {
   678         currentShaderProg->program->enable();
   677         currentShaderProg->program->bind();
   679         if (useCustomSrc)
   678         if (useCustomSrc)
   680             customSrcStage->setUniforms(currentShaderProg->program);
   679             customSrcStage->setUniforms(currentShaderProg->program);
   681     }
   680     }
   682 
   681 
   683     shaderProgNeedsChanging = false;
   682     shaderProgNeedsChanging = false;