diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-12-26 19:49:55 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-12-26 19:49:55 (GMT) |
commit | 24270550463fbc81c7725595719e6e21eade2819 (patch) | |
tree | 4e7c118ed3c4b42e43403960365a2672441ea05e /src/opengl/gl2paintengineex | |
parent | 4376f8871b4422830e9ffb7f3acbc29766d8d218 (diff) | |
parent | 444fb94e02308bedc7b37a702adb95b740168a94 (diff) | |
download | Qt-24270550463fbc81c7725595719e6e21eade2819.zip Qt-24270550463fbc81c7725595719e6e21eade2819.tar.gz Qt-24270550463fbc81c7725595719e6e21eade2819.tar.bz2 |
Merge branch '4.6'
Conflicts:
examples/webkit/fancybrowser/main.cpp
src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
tools/assistant/tools/assistant/bookmarkmanager.cpp
Diffstat (limited to 'src/opengl/gl2paintengineex')
6 files changed, 226 insertions, 181 deletions
diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h index e319389..e0033be 100644 --- a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h @@ -68,7 +68,7 @@ class Q_OPENGL_EXPORT QGLCustomShaderStage public: QGLCustomShaderStage(); virtual ~QGLCustomShaderStage(); - virtual void setUniforms(QGLShaderProgram*) = 0; + virtual void setUniforms(QGLShaderProgram*) {} void setUniformsDirty(); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 8a8f483..9d545b9 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -170,13 +170,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); - vertexShader->compileSourceCode(source); + if (!vertexShader->compileSourceCode(source)) + qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); - fragShader->compileSourceCode(source); + if (!fragShader->compileSourceCode(source)) + qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); simpleShaderProg = new QGLShaderProgram(context, this); simpleShaderProg->addShader(vertexShader); @@ -193,13 +195,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); vertexShader = new QGLShader(QGLShader::Vertex, context, this); - vertexShader->compileSourceCode(source); + if (!vertexShader->compileSourceCode(source)) + qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); source.clear(); source.append(qShaderSnippets[MainFragmentShader]); source.append(qShaderSnippets[ImageSrcFragmentShader]); fragShader = new QGLShader(QGLShader::Fragment, context, this); - fragShader->compileSourceCode(source); + if (!fragShader->compileSourceCode(source)) + qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); blitShaderProg = new QGLShaderProgram(context, this); blitShaderProg->addShader(vertexShader); @@ -234,84 +238,95 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS } } - QByteArray source; - source.append(qShaderSnippets[prog.mainFragShader]); - source.append(qShaderSnippets[prog.srcPixelFragShader]); - if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) - source.append(prog.customStageSource); - if (prog.compositionFragShader) - source.append(qShaderSnippets[prog.compositionFragShader]); - if (prog.maskFragShader) - source.append(qShaderSnippets[prog.maskFragShader]); - QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); - fragShader->compileSourceCode(source); - - source.clear(); - source.append(qShaderSnippets[prog.mainVertexShader]); - source.append(qShaderSnippets[prog.positionVertexShader]); - QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); - vertexShader->compileSourceCode(source); + QGLShader *vertexShader = 0; + QGLShader *fragShader = 0; + QGLEngineShaderProg *newProg = 0; + bool success = false; + + do { + QByteArray source; + source.append(qShaderSnippets[prog.mainFragShader]); + source.append(qShaderSnippets[prog.srcPixelFragShader]); + if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) + source.append(prog.customStageSource); + if (prog.compositionFragShader) + source.append(qShaderSnippets[prog.compositionFragShader]); + if (prog.maskFragShader) + source.append(qShaderSnippets[prog.maskFragShader]); + fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); + 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)); +#endif + if (!fragShader->compileSourceCode(source)) { + qWarning() << "Warning:" << description << "failed to compile!"; + break; + } + source.clear(); + source.append(qShaderSnippets[prog.mainVertexShader]); + source.append(qShaderSnippets[prog.positionVertexShader]); + vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); #if defined(QT_DEBUG) - // Name the shaders for easier debugging - QByteArray 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)); - } - fragShader->setObjectName(QString::fromLatin1(description)); - - 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)); + // 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)); #endif + if (!vertexShader->compileSourceCode(source)) { + qWarning() << "Warning:" << description << "failed to compile!"; + break; + } - QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog); - - // If the shader program's not found in the cache, create it now. - newProg->program = new QGLShaderProgram(ctxGuard.context(), this); - newProg->program->addShader(vertexShader); - newProg->program->addShader(fragShader); - - // We have to bind the vertex attribute names before the program is linked: - newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - if (newProg->useTextureCoords) - newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - if (newProg->useOpacityAttribute) - newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); - - newProg->program->link(); - if (!newProg->program->isLinked()) { - QLatin1String none("none"); - QLatin1String br("\n"); - QString error; - error = QLatin1String("Shader program failed to link,") + newProg = new QGLEngineShaderProg(prog); + + // If the shader program's not found in the cache, create it now. + newProg->program = new QGLShaderProgram(ctxGuard.context(), this); + newProg->program->addShader(vertexShader); + newProg->program->addShader(fragShader); + + // We have to bind the vertex attribute names before the program is linked: + newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + if (newProg->useTextureCoords) + newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + if (newProg->useOpacityAttribute) + newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); + + newProg->program->link(); + if (!newProg->program->isLinked()) { + QLatin1String none("none"); + QLatin1String br("\n"); + QString error; + error = QLatin1String("Shader program failed to link,") #if defined(QT_DEBUG) - + br - + QLatin1String(" Shaders Used:") + br - + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br - + QLatin1String(vertexShader->sourceCode()) + br - + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br - + QLatin1String(fragShader->sourceCode()) + br + + br + + QLatin1String(" Shaders Used:") + br + + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br + + QLatin1String(vertexShader->sourceCode()) + br + + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br + + QLatin1String(fragShader->sourceCode()) + br #endif - + QLatin1String(" Error Log:\n") - + QLatin1String(" ") + newProg->program->log(); - qWarning() << error; - delete newProg; // Deletes the QGLShaderProgram in it's destructor - newProg = 0; - } - else { + + QLatin1String(" Error Log:\n") + + QLatin1String(" ") + newProg->program->log(); + qWarning() << error; + break; + } if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to @@ -323,6 +338,22 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS } cachedPrograms.insert(0, newProg); + + success = true; + } while (false); + + // Clean up everything if we weren't successful + if (!success) { + if (newProg) { + delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders + newProg = 0; + } + else { + if (vertexShader) + delete vertexShader; + if (fragShader) + delete fragShader; + } } return newProg; @@ -364,6 +395,9 @@ QGLEngineShaderManager::~QGLEngineShaderManager() uint QGLEngineShaderManager::getUniformLocation(Uniform id) { + if (!currentShaderProg) + return 0; + QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; if (uniformLocations.isEmpty()) uniformLocations.fill(GLuint(-1), NumUniforms); @@ -406,6 +440,7 @@ void QGLEngineShaderManager::setDirty() void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) { + Q_ASSERT(style != Qt::NoBrush); if (srcPixelType == PixelSrcType(style)) return; @@ -467,7 +502,10 @@ void QGLEngineShaderManager::removeCustomStage() QGLShaderProgram* QGLEngineShaderManager::currentProgram() { - return currentShaderProg->program; + if (currentShaderProg) + return currentShaderProg->program; + else + return simpleProgram(); } QGLShaderProgram* QGLEngineShaderManager::simpleProgram() diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 2407979..46de124 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -99,12 +99,15 @@ static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ opacity = opacityArray; \ }"; +// NOTE: We let GL do the perspective correction so texture lookups in the fragment +// shader are also perspective corrected. static const char* const qglslPositionOnlyVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ void setPosition(void)\ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \ }"; static const char* const qglslUntransformedPositionVertexShader = "\ @@ -116,20 +119,19 @@ static const char* const qglslUntransformedPositionVertexShader = "\ // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 static const char* const qglslPositionWithPatternBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 patternTexCoords; \ void setPosition(void) { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \ }"; @@ -147,20 +149,19 @@ static const char* const qglslPatternBrushSrcFragmentShader = "\ // Linear Gradient Brush static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec3 linearData; \ uniform highp mat3 brushTransform; \ varying mediump float index; \ void setPosition() { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \ }"; @@ -178,20 +179,19 @@ static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ // Conical Gradient Brush static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 A; \ void setPosition(void)\ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ A = hTexCoords.xy * invertedHTexCoordsZ; \ }"; @@ -215,8 +215,8 @@ static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ // Radial Gradient Brush static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - uniform highp mat4 pmvMatrix;\ + attribute highp vec2 vertexCoordsArray;\ + uniform highp mat3 pmvMatrix;\ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ uniform highp vec2 fmp; \ @@ -224,13 +224,12 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ varying highp vec2 A; \ void setPosition(void) \ {\ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ A = hTexCoords.xy * invertedHTexCoordsZ; \ b = 2.0 * dot(A, fmp); \ }"; @@ -253,20 +252,19 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ // Texture Brush static const char* const qglslPositionWithTextureBrushVertexShader = "\ - attribute highp vec4 vertexCoordsArray; \ - uniform highp mat4 pmvMatrix; \ + attribute highp vec2 vertexCoordsArray; \ + uniform highp mat3 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 textureCoords; \ void setPosition(void) { \ - gl_Position = pmvMatrix * vertexCoordsArray;\ - gl_Position.xy = gl_Position.xy / gl_Position.w; \ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ + gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \ - gl_Position.w = invertedHTexCoordsZ; \ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ }"; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index f9c41b1..abe52fe 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -387,19 +387,25 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity) } -void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush) +void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush) { + Q_ASSERT(brush.style() != Qt::NoBrush); + + if (qbrush_fast_equals(currentBrush, brush)) + return; + currentBrush = brush; + brushTextureDirty = true; brushUniformsDirty = true; - if (currentBrush->style() == Qt::TexturePattern - && qHasPixmapTexture(*brush) && brush->texture().isQBitmap()) + if (currentBrush.style() == Qt::TexturePattern + && qHasPixmapTexture(brush) && brush.texture().isQBitmap()) { shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern); } else { - shaderManager->setSrcPixelType(currentBrush->style()); + shaderManager->setSrcPixelType(currentBrush.style()); } - shaderManager->optimiseForBrushTransform(currentBrush->transform()); + shaderManager->optimiseForBrushTransform(currentBrush.transform()); } @@ -421,7 +427,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() { Q_Q(QGL2PaintEngineEx); // qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()"); - Qt::BrushStyle style = currentBrush->style(); + Qt::BrushStyle style = currentBrush.style(); if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) { // Get the image data for the pattern @@ -434,7 +440,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { // Gradiant brush: All the gradiants use the same texture - const QGradient* g = currentBrush->gradient(); + const QGradient* g = currentBrush.gradient(); // We apply global opacity in the fragment shaders, so we always pass 1.0 // for opacity to the cache. @@ -451,7 +457,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style == Qt::TexturePattern) { - const QPixmap& texPixmap = currentBrush->texture(); + const QPixmap& texPixmap = currentBrush.texture(); glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QGLTexture *tex = ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); @@ -465,15 +471,15 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() void QGL2PaintEngineExPrivate::updateBrushUniforms() { // qDebug("QGL2PaintEngineExPrivate::updateBrushUniforms()"); - Qt::BrushStyle style = currentBrush->style(); + Qt::BrushStyle style = currentBrush.style(); if (style == Qt::NoBrush) return; - QTransform brushQTransform = currentBrush->transform(); + QTransform brushQTransform = currentBrush.transform(); if (style == Qt::SolidPattern) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col); } else { @@ -481,7 +487,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QPointF translationPoint; if (style <= Qt::DiagCrossPattern) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); @@ -489,7 +495,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::LinearGradientPattern) { - const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient()); + const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient()); QPointF realStart = g->start(); QPointF realFinal = g->finalStop(); @@ -509,7 +515,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::ConicalGradientPattern) { - const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient()); + const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient()); translationPoint = g->center(); GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0; @@ -520,7 +526,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::RadialGradientPattern) { - const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient()); + const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient()); QPointF realCenter = g->center(); QPointF realFocal = g->focalPoint(); qreal realRadius = g->radius(); @@ -538,10 +544,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::TexturePattern) { - const QPixmap& texPixmap = currentBrush->texture(); + const QPixmap& texPixmap = currentBrush.texture(); - if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) { - QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); + if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) { + QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } @@ -562,7 +568,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QTransform gl_to_qt(1, 0, 0, -1, 0, height); QTransform inv_matrix; if (style == Qt::TexturePattern && textureInvertedY == -1) - inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush->texture().height()) * brushQTransform * matrix).inverted() * translate; + inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate; else inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate; @@ -578,37 +584,37 @@ void QGL2PaintEngineExPrivate::updateMatrix() { // qDebug("QGL2PaintEngineExPrivate::updateMatrix()"); - // We set up the 4x4 transformation matrix on the vertex shaders to - // be the equivalent of glOrtho(0, w, h, 0, -1, 1) * transform: + const QTransform& transform = q->state()->matrix; + + // The projection matrix converts from Qt's coordinate system to GL's coordinate system + // * GL's viewport is 2x2, Qt's is width x height + // * GL has +y -> -y going from bottom -> top, Qt is the other way round + // * GL has [0,0] in the center, Qt has it in the top-left // - // | 2/width 0 0 -1 | | m11 m21 0 dx | - // | 0 -2/height 0 1 | | m12 m22 0 dy | - // | 0 0 -1 0 | * | 0 0 1 0 | - // | 0 0 0 1 | | m13 m23 0 m33 | + // This results in the Projection matrix below, which is multiplied by the painter's + // transformation matrix, as shown below: // - // We expand out the multiplication to save the cost of a full 4x4 - // matrix multiplication as most of the components are trivial. - const QTransform& transform = q->state()->matrix; + // Projection Matrix Painter Transform + // ------------------------------------------------ ------------------------ + // | 2.0 / width | 0.0 | -1.0 | | m11 | m21 | dx | + // | 0.0 | -2.0 / height | 1.0 | * | m12 | m22 | dy | + // | 0.0 | 0.0 | 1.0 | | m13 | m23 | m33 | + // ------------------------------------------------ ------------------------ + // + // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies + + const GLfloat wfactor = 2.0f / width; + const GLfloat hfactor = -2.0f / height; - qreal wfactor = 2.0 / width; - qreal hfactor = -2.0 / height; - - pmvMatrix[0][0] = wfactor * transform.m11() - transform.m13(); - pmvMatrix[0][1] = hfactor * transform.m12() + transform.m13(); - pmvMatrix[0][2] = 0.0; - pmvMatrix[0][3] = transform.m13(); - pmvMatrix[1][0] = wfactor * transform.m21() - transform.m23(); - pmvMatrix[1][1] = hfactor * transform.m22() + transform.m23(); - pmvMatrix[1][2] = 0.0; - pmvMatrix[1][3] = transform.m23(); - pmvMatrix[2][0] = 0.0; - pmvMatrix[2][1] = 0.0; - pmvMatrix[2][2] = -1.0; - pmvMatrix[2][3] = 0.0; - pmvMatrix[3][0] = wfactor * transform.dx() - transform.m33(); - pmvMatrix[3][1] = hfactor * transform.dy() + transform.m33(); - pmvMatrix[3][2] = 0.0; - pmvMatrix[3][3] = transform.m33(); + pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); + pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); + pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33(); + pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13(); + pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23(); + pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33(); + pmvMatrix[0][2] = transform.m13(); + pmvMatrix[1][2] = transform.m23(); + pmvMatrix[2][2] = transform.m33(); // 1/10000 == 0.0001, so we have good enough res to cover curves // that span the entire widget... @@ -876,7 +882,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) // Check to see if there's any hints if (path.shape() == QVectorPath::RectangleHint) { QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); composite(rect); } else if (path.isConvex()) { @@ -931,7 +937,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) #endif } - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); #ifdef QT_OPENGL_CACHE_AS_VBOS glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); @@ -948,7 +954,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) path.makeCacheable(); vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); } @@ -1019,7 +1025,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) #endif } - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); #ifdef QT_OPENGL_CACHE_AS_VBOS glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); @@ -1059,7 +1065,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); } - prepareForDraw(currentBrush->isOpaque()); + prepareForDraw(currentBrush.isOpaque()); if (inRenderText) prepareDepthRangeForRenderText(); @@ -1257,10 +1263,10 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) : QGLEngineShaderManager::NoOpacity; if (stateHasOpacity && (mode != ImageDrawingMode)) { // Using a brush - bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) && - (currentBrush->style() <= Qt::DiagCrossPattern); + bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) && + (currentBrush.style() <= Qt::DiagCrossPattern); - if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern) + if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern) opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader } } @@ -1388,7 +1394,7 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) d->matrixDirty = true; } - d->setBrush(&brush); + d->setBrush(brush); d->fill(path); if (doOffset) { @@ -1427,7 +1433,7 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) } bool opaque = penBrush.isOpaque() && s->opacity > 0.99; - d->setBrush(&penBrush); + d->setBrush(penBrush); d->transferMode(BrushDrawingMode); // updateMatrix() is responsible for setting the inverse scale on @@ -1706,7 +1712,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); QBrush pensBrush = q->state()->pen.brush(); - setBrush(&pensBrush); + setBrush(pensBrush); if (inRenderText) prepareDepthRangeForRenderText(); @@ -1751,7 +1757,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly q->state()->opacity = 1; opacityUniformDirty = true; pensBrush = Qt::white; - setBrush(&pensBrush); + setBrush(pensBrush); } compositionModeDirty = false; // I can handle this myself, thank you very much @@ -1772,7 +1778,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly q->state()->opacity = oldOpacity; opacityUniformDirty = true; pensBrush = q->state()->pen.brush(); - setBrush(&pensBrush); + setBrush(pensBrush); } compositionModeDirty = false; @@ -1917,6 +1923,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->opacityUniformDirty = true; d->needsSync = true; d->use_system_clip = !systemClip().isEmpty(); + d->currentBrush = QBrush(); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); d->stencilClean = true; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 844d42b..c78b011 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -171,7 +171,6 @@ public: q(q_ptr), width(0), height(0), ctx(0), - currentBrush(0), inverseScale(1), shaderManager(0), inRenderText(false) @@ -185,7 +184,7 @@ public: void updateCompositionMode(); void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1); - void setBrush(const QBrush* brush); + void setBrush(const QBrush& brush); void transferMode(EngineMode newMode); void resetGLState(); @@ -244,7 +243,7 @@ public: QRect currentScissorBounds; uint maxClip; - const QBrush* currentBrush; // May not be the state's brush! + QBrush currentBrush; // May not be the state's brush! GLfloat inverseScale; @@ -255,7 +254,7 @@ public: GLfloat staticVertexCoordinateArray[8]; GLfloat staticTextureCoordinateArray[8]; - GLfloat pmvMatrix[4][4]; + GLfloat pmvMatrix[3][3]; QGLEngineShaderManager* shaderManager; @@ -291,10 +290,7 @@ public: QScopedPointer<QPixmapFilter> convolutionFilter; QScopedPointer<QPixmapFilter> colorizeFilter; QScopedPointer<QPixmapFilter> blurFilter; - QScopedPointer<QPixmapFilter> animationBlurFilter; - QScopedPointer<QPixmapFilter> fastBlurFilter; QScopedPointer<QPixmapFilter> dropShadowFilter; - QScopedPointer<QPixmapFilter> fastDropShadowFilter; QSet<QVectorPath::CacheEntry *> pathCaches; QVector<GLuint> unusedVBOSToClean; diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp index 6082f49..395b8a3 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp @@ -62,8 +62,14 @@ void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal * endCap(cur); } int count = m_vertices.size(); - m_vertices.add(m_vertices.at(count-2)); - m_vertices.add(m_vertices.at(count-1)); + + // Copy the (x, y) values because QDataBuffer::add(const float& t) + // may resize the buffer, which will leave t pointing at the + // previous buffer's memory region if we don't copy first. + float x = m_vertices.at(count-2); + float y = m_vertices.at(count-1); + m_vertices.add(x); + m_vertices.add(y); } |