diff options
Diffstat (limited to 'src/gui/opengl/qopenglengineshadermanager.cpp')
-rw-r--r-- | src/gui/opengl/qopenglengineshadermanager.cpp | 199 |
1 files changed, 106 insertions, 93 deletions
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp index 1d3e47f93b..dd9e8e9d1e 100644 --- a/src/gui/opengl/qopenglengineshadermanager.cpp +++ b/src/gui/opengl/qopenglengineshadermanager.cpp @@ -126,11 +126,65 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) around without having to change the order of the glsl strings. It is hoped this will make future hard-to-find runtime bugs more obvious and generally give more solid code. */ - static bool snippetsPopulated = false; - if (!snippetsPopulated) { - const char** code = qShaderSnippets; // shortcut + // Check if the user has requested an OpenGL 3.2 Core Profile or higher + // and if so use GLSL 1.50 core shaders instead of legacy ones. + const QSurfaceFormat &fmt = context->format(); + const bool isCoreProfile = fmt.profile() == QSurfaceFormat::CoreProfile && fmt.version() >= qMakePair(3,2); + + const char** code = qShaderSnippets; // shortcut + + if (isCoreProfile) { + code[MainVertexShader] = qopenglslMainVertexShader_core; + code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader_core; + code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader_core; + + code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader_core; + code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader_core; + code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader_core; + code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader_core; + code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader_core; + code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader_core; + code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader_core; + code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader_core; + code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader_core; + code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader_core; + code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader_core; + code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader_core; + code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader_core; + + code[MainFragmentShader_CMO] = qopenglslMainFragmentShader_CMO_core; + code[MainFragmentShader_CM] = qopenglslMainFragmentShader_CM_core; + code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO_core; + code[MainFragmentShader_M] = qopenglslMainFragmentShader_M_core; + code[MainFragmentShader_CO] = qopenglslMainFragmentShader_CO_core; + code[MainFragmentShader_C] = qopenglslMainFragmentShader_C_core; + code[MainFragmentShader_O] = qopenglslMainFragmentShader_O_core; + code[MainFragmentShader] = qopenglslMainFragmentShader_core; + code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays_core; + + code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader_core; + code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader_core; + code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader_core; + code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader_core; + code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader_core; + code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended + code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core; + + code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_desktop_core; + code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core; + code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core; + code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core; + code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader_core; + code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader_core; + code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader_core; + code[NoMaskFragmentShader] = ""; + code[MaskFragmentShader] = qopenglslMaskFragmentShader_core; + code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1_core; + code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2_core; + code[RgbMaskWithGammaFragmentShader] = ""; //### + } else { code[MainVertexShader] = qopenglslMainVertexShader; code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader; code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader; @@ -182,34 +236,34 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1; code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2; code[RgbMaskWithGammaFragmentShader] = ""; //### + } - code[NoCompositionModeFragmentShader] = ""; - code[MultiplyCompositionModeFragmentShader] = ""; //### - code[ScreenCompositionModeFragmentShader] = ""; //### - code[OverlayCompositionModeFragmentShader] = ""; //### - code[DarkenCompositionModeFragmentShader] = ""; //### - code[LightenCompositionModeFragmentShader] = ""; //### - code[ColorDodgeCompositionModeFragmentShader] = ""; //### - code[ColorBurnCompositionModeFragmentShader] = ""; //### - code[HardLightCompositionModeFragmentShader] = ""; //### - code[SoftLightCompositionModeFragmentShader] = ""; //### - code[DifferenceCompositionModeFragmentShader] = ""; //### - code[ExclusionCompositionModeFragmentShader] = ""; //### + // These shaders are not implemented yet and therefore are the same + // for all profiles. Implementations should make a version for both + // profiles and put the appropriate lines in the if-statement above. + code[NoCompositionModeFragmentShader] = ""; + code[MultiplyCompositionModeFragmentShader] = ""; //### + code[ScreenCompositionModeFragmentShader] = ""; //### + code[OverlayCompositionModeFragmentShader] = ""; //### + code[DarkenCompositionModeFragmentShader] = ""; //### + code[LightenCompositionModeFragmentShader] = ""; //### + code[ColorDodgeCompositionModeFragmentShader] = ""; //### + code[ColorBurnCompositionModeFragmentShader] = ""; //### + code[HardLightCompositionModeFragmentShader] = ""; //### + code[SoftLightCompositionModeFragmentShader] = ""; //### + code[DifferenceCompositionModeFragmentShader] = ""; //### + code[ExclusionCompositionModeFragmentShader] = ""; //### #if defined(QT_DEBUG) - // Check that all the elements have been filled: - for (int i = 0; i < TotalSnippetCount; ++i) { - if (Q_UNLIKELY(!qShaderSnippets[i])) { - qFatal("Shader snippet for %s (#%d) is missing!", - snippetNameStr(SnippetName(i)).constData(), i); - } + // Check that all the elements have been filled: + for (int i = 0; i < TotalSnippetCount; ++i) { + if (Q_UNLIKELY(!qShaderSnippets[i])) { + qFatal("Shader snippet for %s (#%d) is missing!", + snippetNameStr(SnippetName(i)).constData(), i); } -#endif - snippetsPopulated = true; } +#endif - QOpenGLShader* fragShader; - QOpenGLShader* vertexShader; QByteArray vertexSource; QByteArray fragSource; @@ -227,19 +281,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) bool inCache = simpleShaderCache.load(simpleShaderProg, context); if (!inCache) { - vertexShader = new QOpenGLShader(QOpenGLShader::Vertex); - shaders.append(vertexShader); - if (!vertexShader->compileSourceCode(vertexSource)) + if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); - - fragShader = new QOpenGLShader(QOpenGLShader::Fragment); - shaders.append(fragShader); - if (!fragShader->compileSourceCode(fragSource)) + if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); - simpleShaderProg->addShader(vertexShader); - simpleShaderProg->addShader(fragShader); - simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); @@ -271,19 +317,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) inCache = blitShaderCache.load(blitShaderProg, context); if (!inCache) { - vertexShader = new QOpenGLShader(QOpenGLShader::Vertex); - shaders.append(vertexShader); - if (!vertexShader->compileSourceCode(vertexSource)) + if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); - - fragShader = new QOpenGLShader(QOpenGLShader::Fragment); - shaders.append(fragShader); - if (!fragShader->compileSourceCode(fragSource)) + if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); - blitShaderProg->addShader(vertexShader); - blitShaderProg->addShader(fragShader); - blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); } @@ -306,9 +344,6 @@ QOpenGLEngineSharedShaders::~QOpenGLEngineSharedShaders() #ifdef QT_GL_SHARED_SHADER_DEBUG qDebug(" -> ~QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); #endif - qDeleteAll(shaders); - shaders.clear(); - qDeleteAll(cachedPrograms); cachedPrograms.clear(); @@ -370,50 +405,37 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO bool inCache = shaderCache.load(shaderProgram.data(), QOpenGLContext::currentContext()); if (!inCache) { - - QScopedPointer<QOpenGLShader> fragShader(new QOpenGLShader(QOpenGLShader::Fragment)); - QByteArray description; + if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) { + QByteArray description; #if defined(QT_DEBUG) - // Name the shader for easier debugging - description.append("Fragment shader: main="); - description.append(snippetNameStr(prog.mainFragShader)); - description.append(", srcPixel="); - description.append(snippetNameStr(prog.srcPixelFragShader)); - if (prog.compositionFragShader) { - description.append(", composition="); - description.append(snippetNameStr(prog.compositionFragShader)); - } - if (prog.maskFragShader) { - description.append(", mask="); - description.append(snippetNameStr(prog.maskFragShader)); - } - fragShader->setObjectName(QString::fromLatin1(description)); + description.append("Vertex shader: main="); + description.append(snippetNameStr(prog.mainVertexShader)); + description.append(", position="); + description.append(snippetNameStr(prog.positionVertexShader)); #endif - if (!fragShader->compileSourceCode(fragSource)) { qWarning("Warning: \"%s\" failed to compile!", description.constData()); break; } - - QScopedPointer<QOpenGLShader> vertexShader(new QOpenGLShader(QOpenGLShader::Vertex)); + if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) { + QByteArray description; #if defined(QT_DEBUG) - // Name the shader for easier debugging - description.clear(); - description.append("Vertex shader: main="); - description.append(snippetNameStr(prog.mainVertexShader)); - description.append(", position="); - description.append(snippetNameStr(prog.positionVertexShader)); - vertexShader->setObjectName(QString::fromLatin1(description)); + description.append("Fragment shader: main="); + description.append(snippetNameStr(prog.mainFragShader)); + description.append(", srcPixel="); + description.append(snippetNameStr(prog.srcPixelFragShader)); + if (prog.compositionFragShader) { + description.append(", composition="); + description.append(snippetNameStr(prog.compositionFragShader)); + } + if (prog.maskFragShader) { + description.append(", mask="); + description.append(snippetNameStr(prog.maskFragShader)); + } #endif - if (!vertexShader->compileSourceCode(vertexSource)) { qWarning("Warning: \"%s\" failed to compile!", description.constData()); break; } - shaders.append(vertexShader.data()); - shaders.append(fragShader.data()); - shaderProgram->addShader(vertexShader.take()); - shaderProgram->addShader(fragShader.take()); - // We have to bind the vertex attribute names before the program is linked: shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (prog.useTextureCoords) @@ -436,18 +458,9 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO shaderCache.store(newProg->program, QOpenGLContext::currentContext()); } else { QString error; - error = QLatin1String("Shader program failed to link,"); -#if defined(QT_DEBUG) - QLatin1String br("\n"); - error += QLatin1String("\n Shaders Used:\n"); - for (int i = 0; i < newProg->program->shaders().count(); ++i) { - QOpenGLShader *shader = newProg->program->shaders().at(i); - error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n") - + QLatin1String(shader->sourceCode()) + br; - } -#endif - error += QLatin1String(" Error Log:\n") - + QLatin1String(" ") + newProg->program->log(); + error = QLatin1String("Shader program failed to link") + + QLatin1String(" Error Log:\n") + + QLatin1String(" ") + newProg->program->log(); qWarning() << error; break; } |