src/opengl/gl2paintengineex/qglengineshadermanager.cpp
branchRCL_3
changeset 4 3b1da2848fc7
parent 3 41300fa6a67c
child 5 d3bac044e0f0
equal deleted inserted replaced
3:41300fa6a67c 4:3b1da2848fc7
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     8 **
     8 **
   168     // Compile up the simple shader:
   168     // Compile up the simple shader:
   169     source.clear();
   169     source.clear();
   170     source.append(qShaderSnippets[MainVertexShader]);
   170     source.append(qShaderSnippets[MainVertexShader]);
   171     source.append(qShaderSnippets[PositionOnlyVertexShader]);
   171     source.append(qShaderSnippets[PositionOnlyVertexShader]);
   172     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
   172     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
   173     vertexShader->compileSourceCode(source);
   173     if (!vertexShader->compileSourceCode(source))
       
   174         qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
   174 
   175 
   175     source.clear();
   176     source.clear();
   176     source.append(qShaderSnippets[MainFragmentShader]);
   177     source.append(qShaderSnippets[MainFragmentShader]);
   177     source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
   178     source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
   178     fragShader = new QGLShader(QGLShader::Fragment, context, this);
   179     fragShader = new QGLShader(QGLShader::Fragment, context, this);
   179     fragShader->compileSourceCode(source);
   180     if (!fragShader->compileSourceCode(source))
       
   181         qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
   180 
   182 
   181     simpleShaderProg = new QGLShaderProgram(context, this);
   183     simpleShaderProg = new QGLShaderProgram(context, this);
   182     simpleShaderProg->addShader(vertexShader);
   184     simpleShaderProg->addShader(vertexShader);
   183     simpleShaderProg->addShader(fragShader);
   185     simpleShaderProg->addShader(fragShader);
   184     simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   186     simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
   191     // Compile the blit shader:
   193     // Compile the blit shader:
   192     source.clear();
   194     source.clear();
   193     source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
   195     source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
   194     source.append(qShaderSnippets[UntransformedPositionVertexShader]);
   196     source.append(qShaderSnippets[UntransformedPositionVertexShader]);
   195     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
   197     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
   196     vertexShader->compileSourceCode(source);
   198     if (!vertexShader->compileSourceCode(source))
       
   199         qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
   197 
   200 
   198     source.clear();
   201     source.clear();
   199     source.append(qShaderSnippets[MainFragmentShader]);
   202     source.append(qShaderSnippets[MainFragmentShader]);
   200     source.append(qShaderSnippets[ImageSrcFragmentShader]);
   203     source.append(qShaderSnippets[ImageSrcFragmentShader]);
   201     fragShader = new QGLShader(QGLShader::Fragment, context, this);
   204     fragShader = new QGLShader(QGLShader::Fragment, context, this);
   202     fragShader->compileSourceCode(source);
   205     if (!fragShader->compileSourceCode(source))
       
   206         qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
   203 
   207 
   204     blitShaderProg = new QGLShaderProgram(context, this);
   208     blitShaderProg = new QGLShaderProgram(context, this);
   205     blitShaderProg->addShader(vertexShader);
   209     blitShaderProg->addShader(vertexShader);
   206     blitShaderProg->addShader(fragShader);
   210     blitShaderProg->addShader(fragShader);
   207     blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   211     blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
   212                     << simpleShaderProg->log();
   216                     << simpleShaderProg->log();
   213     }
   217     }
   214 
   218 
   215 }
   219 }
   216 
   220 
       
   221 QGLEngineSharedShaders::~QGLEngineSharedShaders()
       
   222 {
       
   223     QList<QGLEngineShaderProg*>::iterator itr;
       
   224     for (itr = cachedPrograms.begin(); itr != cachedPrograms.end(); ++itr)
       
   225         delete *itr;
       
   226 
       
   227     if (blitShaderProg) {
       
   228         delete blitShaderProg;
       
   229         blitShaderProg = 0;
       
   230     }
       
   231 
       
   232     if (simpleShaderProg) {
       
   233         delete simpleShaderProg;
       
   234         simpleShaderProg = 0;
       
   235     }
       
   236 }
       
   237 
   217 #if defined (QT_DEBUG)
   238 #if defined (QT_DEBUG)
   218 QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name)
   239 QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name)
   219 {
   240 {
   220     QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
   241     QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
   221     return QByteArray(m.valueToKey(name));
   242     return QByteArray(m.valueToKey(name));
   232             cachedPrograms.move(i, 0);
   253             cachedPrograms.move(i, 0);
   233             return cachedProg;
   254             return cachedProg;
   234         }
   255         }
   235     }
   256     }
   236 
   257 
   237     QByteArray source;
   258     QGLShader *vertexShader = 0;
   238     source.append(qShaderSnippets[prog.mainFragShader]);
   259     QGLShader *fragShader = 0;
   239     source.append(qShaderSnippets[prog.srcPixelFragShader]);
   260     QGLEngineShaderProg *newProg = 0;
   240     if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
   261     bool success = false;
   241         source.append(prog.customStageSource);
   262 
   242     if (prog.compositionFragShader)
   263     do {
   243         source.append(qShaderSnippets[prog.compositionFragShader]);
   264         QByteArray source;
   244     if (prog.maskFragShader)
   265         source.append(qShaderSnippets[prog.mainFragShader]);
   245         source.append(qShaderSnippets[prog.maskFragShader]);
   266         source.append(qShaderSnippets[prog.srcPixelFragShader]);
   246     QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
   267         if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
   247     fragShader->compileSourceCode(source);
   268             source.append(prog.customStageSource);
   248 
   269         if (prog.compositionFragShader)
   249     source.clear();
   270             source.append(qShaderSnippets[prog.compositionFragShader]);
   250     source.append(qShaderSnippets[prog.mainVertexShader]);
   271         if (prog.maskFragShader)
   251     source.append(qShaderSnippets[prog.positionVertexShader]);
   272             source.append(qShaderSnippets[prog.maskFragShader]);
   252     QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
   273         fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
   253     vertexShader->compileSourceCode(source);
   274         QByteArray description;
   254 
       
   255 #if defined(QT_DEBUG)
   275 #if defined(QT_DEBUG)
   256     // Name the shaders for easier debugging
   276         // Name the shader for easier debugging
   257     QByteArray description;
   277         description.append("Fragment shader: main=");
   258     description.append("Fragment shader: main=");
   278         description.append(snippetNameStr(prog.mainFragShader));
   259     description.append(snippetNameStr(prog.mainFragShader));
   279         description.append(", srcPixel=");
   260     description.append(", srcPixel=");
   280         description.append(snippetNameStr(prog.srcPixelFragShader));
   261     description.append(snippetNameStr(prog.srcPixelFragShader));
   281         if (prog.compositionFragShader) {
   262     if (prog.compositionFragShader) {
   282             description.append(", composition=");
   263         description.append(", composition=");
   283             description.append(snippetNameStr(prog.compositionFragShader));
   264         description.append(snippetNameStr(prog.compositionFragShader));
   284         }
   265     }
   285         if (prog.maskFragShader) {
   266     if (prog.maskFragShader) {
   286             description.append(", mask=");
   267         description.append(", mask=");
   287             description.append(snippetNameStr(prog.maskFragShader));
   268         description.append(snippetNameStr(prog.maskFragShader));
   288         }
   269     }
   289         fragShader->setObjectName(QString::fromLatin1(description));
   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
   290 #endif
   279 
   291         if (!fragShader->compileSourceCode(source)) {
   280     QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog);
   292             qWarning() << "Warning:" << description << "failed to compile!";
   281 
   293             break;
   282     // If the shader program's not found in the cache, create it now.
   294         }
   283     newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
   295 
   284     newProg->program->addShader(vertexShader);
   296         source.clear();
   285     newProg->program->addShader(fragShader);
   297         source.append(qShaderSnippets[prog.mainVertexShader]);
   286 
   298         source.append(qShaderSnippets[prog.positionVertexShader]);
   287     // We have to bind the vertex attribute names before the program is linked:
   299         vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
   288     newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
       
   289     if (newProg->useTextureCoords)
       
   290         newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
       
   291     if (newProg->useOpacityAttribute)
       
   292         newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
       
   293 
       
   294     newProg->program->link();
       
   295     if (!newProg->program->isLinked()) {
       
   296         QLatin1String none("none");
       
   297         QLatin1String br("\n");
       
   298         QString error;
       
   299         error = QLatin1String("Shader program failed to link,")
       
   300 #if defined(QT_DEBUG)
   300 #if defined(QT_DEBUG)
   301             + br
   301         // Name the shader for easier debugging
   302             + QLatin1String("  Shaders Used:") + br
   302         description.clear();
   303             + QLatin1String("    ") + vertexShader->objectName() + QLatin1String(": ") + br
   303         description.append("Vertex shader: main=");
   304             + QLatin1String(vertexShader->sourceCode()) + br
   304         description.append(snippetNameStr(prog.mainVertexShader));
   305             + QLatin1String("    ") + fragShader->objectName() + QLatin1String(": ") + br
   305         description.append(", position=");
   306             + QLatin1String(fragShader->sourceCode()) + br
   306         description.append(snippetNameStr(prog.positionVertexShader));
       
   307         vertexShader->setObjectName(QString::fromLatin1(description));
   307 #endif
   308 #endif
   308             + QLatin1String("  Error Log:\n")
   309         if (!vertexShader->compileSourceCode(source)) {
   309             + QLatin1String("    ") + newProg->program->log();
   310             qWarning() << "Warning:" << description << "failed to compile!";
   310         qWarning() << error;
   311             break;
   311         delete newProg; // Deletes the QGLShaderProgram in it's destructor
   312         }
   312         newProg = 0;
   313 
   313     }
   314         newProg = new QGLEngineShaderProg(prog);
   314     else {
   315 
       
   316         // If the shader program's not found in the cache, create it now.
       
   317         newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
       
   318         newProg->program->addShader(vertexShader);
       
   319         newProg->program->addShader(fragShader);
       
   320 
       
   321         // We have to bind the vertex attribute names before the program is linked:
       
   322         newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
       
   323         if (newProg->useTextureCoords)
       
   324             newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
       
   325         if (newProg->useOpacityAttribute)
       
   326             newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
       
   327 
       
   328         newProg->program->link();
       
   329         if (!newProg->program->isLinked()) {
       
   330             QLatin1String none("none");
       
   331             QLatin1String br("\n");
       
   332             QString error;
       
   333             error = QLatin1String("Shader program failed to link,")
       
   334 #if defined(QT_DEBUG)
       
   335                 + br
       
   336                 + QLatin1String("  Shaders Used:") + br
       
   337                 + QLatin1String("    ") + vertexShader->objectName() + QLatin1String(": ") + br
       
   338                 + QLatin1String(vertexShader->sourceCode()) + br
       
   339                 + QLatin1String("    ") + fragShader->objectName() + QLatin1String(": ") + br
       
   340                 + QLatin1String(fragShader->sourceCode()) + br
       
   341 #endif
       
   342                 + QLatin1String("  Error Log:\n")
       
   343                 + QLatin1String("    ") + newProg->program->log();
       
   344             qWarning() << error;
       
   345             break;
       
   346         }
   315         if (cachedPrograms.count() > 30) {
   347         if (cachedPrograms.count() > 30) {
   316             // The cache is full, so delete the last 5 programs in the list.
   348             // The cache is full, so delete the last 5 programs in the list.
   317             // These programs will be least used, as a program us bumped to
   349             // These programs will be least used, as a program us bumped to
   318             // the top of the list when it's used.
   350             // the top of the list when it's used.
   319             for (int i = 0; i < 5; ++i) {
   351             for (int i = 0; i < 5; ++i) {
   321                 cachedPrograms.removeLast();
   353                 cachedPrograms.removeLast();
   322             }
   354             }
   323         }
   355         }
   324 
   356 
   325         cachedPrograms.insert(0, newProg);
   357         cachedPrograms.insert(0, newProg);
       
   358 
       
   359         success = true;
       
   360     } while (false);
       
   361 
       
   362     // Clean up everything if we weren't successful
       
   363     if (!success) {
       
   364         if (newProg) {
       
   365             delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders
       
   366             newProg = 0;
       
   367         }
       
   368         else {
       
   369             if (vertexShader)
       
   370                 delete vertexShader;
       
   371             if (fragShader)
       
   372                 delete fragShader;
       
   373         }
   326     }
   374     }
   327 
   375 
   328     return newProg;
   376     return newProg;
   329 }
   377 }
   330 
   378 
   360 {
   408 {
   361     //###
   409     //###
   362     removeCustomStage();
   410     removeCustomStage();
   363 }
   411 }
   364 
   412 
   365 uint QGLEngineShaderManager::getUniformLocation(Uniform id)
   413 GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
   366 {
   414 {
       
   415     if (!currentShaderProg)
       
   416         return 0;
       
   417 
   367     QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
   418     QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
   368     if (uniformLocations.isEmpty())
   419     if (uniformLocations.isEmpty())
   369         uniformLocations.fill(GLuint(-1), NumUniforms);
   420         uniformLocations.fill(GLuint(-1), NumUniforms);
   370 
   421 
   371     static const char *uniformNames[] = {
   422     static const char *uniformNames[] = {
   392 
   443 
   393     return uniformLocations.at(id);
   444     return uniformLocations.at(id);
   394 }
   445 }
   395 
   446 
   396 
   447 
   397 void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform)
   448 void QGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType)
   398 {
   449 {
   399     Q_UNUSED(transform); // Currently ignored
   450     Q_UNUSED(transformType); // Currently ignored
   400 }
   451 }
   401 
   452 
   402 void QGLEngineShaderManager::setDirty()
   453 void QGLEngineShaderManager::setDirty()
   403 {
   454 {
   404     shaderProgNeedsChanging = true;
   455     shaderProgNeedsChanging = true;
   466     shaderProgNeedsChanging = true;
   517     shaderProgNeedsChanging = true;
   467 }
   518 }
   468 
   519 
   469 QGLShaderProgram* QGLEngineShaderManager::currentProgram()
   520 QGLShaderProgram* QGLEngineShaderManager::currentProgram()
   470 {
   521 {
   471     return currentShaderProg->program;
   522     if (currentShaderProg)
       
   523         return currentShaderProg->program;
       
   524     else
       
   525         return sharedShaders->simpleProgram();
       
   526 }
       
   527 
       
   528 void QGLEngineShaderManager::useSimpleProgram()
       
   529 {
       
   530     sharedShaders->simpleProgram()->bind();
       
   531     QGLContextPrivate* ctx_d = ctx->d_func();
       
   532     ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
       
   533     ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
       
   534     ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
       
   535     shaderProgNeedsChanging = true;
       
   536 }
       
   537 
       
   538 void QGLEngineShaderManager::useBlitProgram()
       
   539 {
       
   540     sharedShaders->blitProgram()->bind();
       
   541     QGLContextPrivate* ctx_d = ctx->d_func();
       
   542     ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
       
   543     ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
       
   544     ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
       
   545     shaderProgNeedsChanging = true;
   472 }
   546 }
   473 
   547 
   474 QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
   548 QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
   475 {
   549 {
   476     return sharedShaders->simpleProgram();
   550     return sharedShaders->simpleProgram();
   677         currentShaderProg->program->bind();
   751         currentShaderProg->program->bind();
   678         if (useCustomSrc)
   752         if (useCustomSrc)
   679             customSrcStage->setUniforms(currentShaderProg->program);
   753             customSrcStage->setUniforms(currentShaderProg->program);
   680     }
   754     }
   681 
   755 
       
   756     // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it
       
   757     // doesn't use are disabled)
       
   758     QGLContextPrivate* ctx_d = ctx->d_func();
       
   759     ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
       
   760     ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg->useTextureCoords);
       
   761     ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg->useOpacityAttribute);
       
   762 
   682     shaderProgNeedsChanging = false;
   763     shaderProgNeedsChanging = false;
   683     return true;
   764     return true;
   684 }
   765 }
   685 
   766 
   686 QT_END_NAMESPACE
   767 QT_END_NAMESPACE