diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-06-30 07:45:14 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-06-30 12:20:11 (GMT) |
commit | 351e890aa13faac69a0ceaa8cb02660b2275cf82 (patch) | |
tree | caf61d0d83735128390759638b20011d3b150cf7 /src/opengl | |
parent | 9dd82fcebc50ca802e9e24a50283152e1dc35508 (diff) | |
download | Qt-351e890aa13faac69a0ceaa8cb02660b2275cf82.zip Qt-351e890aa13faac69a0ceaa8cb02660b2275cf82.tar.gz Qt-351e890aa13faac69a0ceaa8cb02660b2275cf82.tar.bz2 |
Added custom shader hook to the GL 2 paint engine.
This will make it easier to implement pixmap filters, YUV->RGB
conversions, etc in other parts of Qt.
Diffstat (limited to 'src/opengl')
5 files changed, 107 insertions, 24 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 4b73ca9..068f804 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -49,6 +49,30 @@ QT_BEGIN_NAMESPACE +QGLCustomShader::QGLCustomShader(QGLShader *shader) + : m_shader(shader) +{ +} + +QGLCustomShader::~QGLCustomShader() +{ + delete m_shader; +} + +void QGLCustomShader::updateUniforms(QGLShaderProgram *) +{ +} + +void QGLCustomShader::setShader(QGLShader *shader) +{ + m_shader = shader; +} + +QGLShader *QGLCustomShader::shader() const +{ + return m_shader; +} + const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, @@ -66,7 +90,8 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) compositionMode(QPainter::CompositionMode_SourceOver), blitShaderProg(0), simpleShaderProg(0), - currentShaderProg(0) + currentShaderProg(0), + customShader(0) { memset(compiledShaders, 0, sizeof(compiledShaders)); @@ -107,6 +132,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) code[MainFragmentShader] = qglslMainFragmentShader; code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; + code[CustomSrcFragmentShader] = qglslCustomSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; @@ -228,7 +254,7 @@ void QGLEngineShaderManager::setDirty() void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) { - if (srcPixelType == PixelSrcType(style)) + if (customShader || srcPixelType == PixelSrcType(style)) return; srcPixelType = style; @@ -237,13 +263,20 @@ void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type) { - if (srcPixelType == type) + if (customShader || srcPixelType == type) return; srcPixelType = type; shaderProgNeedsChanging = true; //### } +void QGLEngineShaderManager::setCustomShader(QGLCustomShader *shader) +{ + srcPixelType = CustomSrc; + shaderProgNeedsChanging = true; + customShader = shader; +} + void QGLEngineShaderManager::setTextureCoordsEnabled(bool enabled) { if (useTextureCoords == enabled) @@ -338,6 +371,10 @@ bool QGLEngineShaderManager::useCorrectShaderProg() srcPixelFragShaderName = ImageSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; break; + case QGLEngineShaderManager::CustomSrc: + srcPixelFragShaderName = CustomSrcFragmentShader; + positionVertexShaderName = PositionOnlyVertexShader; + break; case QGLEngineShaderManager::PatternSrc: srcPixelFragShaderName = ImageSrcWithPatternFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; @@ -381,7 +418,6 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.positionVertexShader = compiledShaders[positionVertexShaderName]; requiredProgram.srcPixelFragShader = compiledShaders[srcPixelFragShaderName]; - const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; const bool hasMask = maskType != QGLEngineShaderManager::NoMask; @@ -483,6 +519,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() currentShaderProg = &prog; currentShaderProg->program->enable(); shaderProgNeedsChanging = false; + return true; } } @@ -496,6 +533,9 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.program->addShader(requiredProgram.maskFragShader); requiredProgram.program->addShader(requiredProgram.compositionFragShader); + if (customShader) + requiredProgram.program->addShader(customShader->shader()); + // We have to bind the vertex attribute names before the program is linked: requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (useTextureCoords) @@ -520,11 +560,20 @@ bool QGLEngineShaderManager::useCorrectShaderProg() qWarning() << error; } else { - cachedPrograms.append(requiredProgram); - // taking the address here is safe since - // cachePrograms isn't resized anywhere else - currentShaderProg = &cachedPrograms.last(); + if (customShader) { + // don't cache custom shaders + customShaderProg = requiredProgram; + currentShaderProg = &customShaderProg; + } else { + cachedPrograms.append(requiredProgram); + // taking the address here is safe since + // cachePrograms isn't resized anywhere else + currentShaderProg = &cachedPrograms.last(); + } currentShaderProg->program->enable(); + + if (customShader) + customShader->updateUniforms(currentShaderProg->program); } shaderProgNeedsChanging = false; return true; diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 34f0768..891776f 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -199,18 +199,19 @@ O = Global Opacity - CUSTOM SHADER CODE (idea, depricated) + CUSTOM SHADER CODE ================== The use of custom shader code is supported by the engine for drawImage and drawPixmap calls. This is implemented via hooks in the fragment pipeline. - The custom shader is passed to the engine as a partial fragment shader - (QGLCustomizedShader). The shader will implement a pre-defined method name - which Qt's fragment pipeline will call. There are two different hooks which - can be implemented as custom shader code: + The custom shader is passed to the shader manager as a partial fragment shader + by calling setCustomShader(). Qt's fragment pipeline will call the following + method name in the custom shader: mediump vec4 customShader(sampler2d src, vec2 srcCoords) - mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords) + + Transformations, clipping, opacity, and composition modes set using QPainter + will be respected when using the custom shader hook. */ @@ -227,6 +228,22 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) +class Q_OPENGL_EXPORT QGLCustomShader +{ +public: + QGLCustomShader(QGLShader *shader = 0); + virtual ~QGLCustomShader(); + + virtual void updateUniforms(QGLShaderProgram *program); + + void setShader(QGLShader *shader); + QGLShader *shader() const; + +private: + Q_DISABLE_COPY(QGLCustomShader) + + QGLShader *m_shader; +}; struct QGLEngineShaderProg { @@ -259,7 +276,7 @@ struct QGLEngineCachedShaderProg static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; -class QGLEngineShaderManager : public QObject +class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject { Q_OBJECT public: @@ -271,7 +288,8 @@ public: ImageSrc = Qt::TexturePattern+1, NonPremultipliedImageSrc = Qt::TexturePattern+2, PatternSrc = Qt::TexturePattern+3, - TextureSrcWithPattern = Qt::TexturePattern+4 + TextureSrcWithPattern = Qt::TexturePattern+4, + CustomSrc = Qt::TexturePattern + 5 }; // There are optimisations we can do, depending on the brush transform: @@ -285,6 +303,8 @@ public: void setMaskType(MaskType); void setCompositionMode(QPainter::CompositionMode); + void setCustomShader(QGLCustomShader *shader); + uint getUniformIdentifier(const char *uniformName); uint getUniformLocation(uint id); @@ -322,6 +342,7 @@ public: MainFragmentShader, ImageSrcFragmentShader, + CustomSrcFragmentShader, ImageSrcWithPatternFragmentShader, NonPremultipliedImageSrcFragmentShader, SolidBrushSrcFragmentShader, @@ -366,7 +387,6 @@ public: Q_ENUMS(ShaderName) #endif - private: QGLContext* ctx; bool shaderProgNeedsChanging; @@ -383,6 +403,9 @@ private: QGLShaderProgram* simpleShaderProg; QGLEngineShaderProg* currentShaderProg; + QGLEngineShaderProg customShaderProg; + QGLCustomShader* customShader; + // TODO: Possibly convert to a LUT QList<QGLEngineShaderProg> cachedPrograms; diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 4e32f91..e379aa3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -290,6 +290,14 @@ static const char* const qglslImageSrcFragmentShader = "\ return texture2D(imageTexture, textureCoords); \ }"; +static const char* const qglslCustomSrcFragmentShader = "\ + varying highp vec2 textureCoords; \ + uniform sampler2D imageTexture; \ + lowp vec4 customShader(sampler2D texture, vec2 coords); \ + lowp vec4 srcPixel() { \ + return customShader(imageTexture, textureCoords); \ + }"; + static const char* const qglslImageSrcWithPatternFragmentShader = "\ varying highp vec2 textureCoords; \ uniform lowp vec4 patternColor; \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 4bf5d4c..a679a62 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -130,10 +130,6 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph QGLTextureGlyphCache::~QGLTextureGlyphCache() { - glDeleteFramebuffers(1, &m_fbo); - - if (m_width || m_height) - glDeleteTextures(1, &m_texture); } void QGLTextureGlyphCache::createTextureData(int width, int height) @@ -251,7 +247,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != -1 && id == lastTexture) + if (id != GLuint(-1) && id == lastTexture) return; lastTexture = id; @@ -1605,4 +1601,10 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() { } +QGLEngineShaderManager *QGL2PaintEngineEx::shaderManager() const +{ + Q_D(const QGL2PaintEngineEx); + return d->shaderManager; +} + QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 0d28a49..f8d3b53 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -88,8 +88,7 @@ public: bool canRestoreClip; }; - -class QGL2PaintEngineEx : public QPaintEngineEx +class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx { Q_DECLARE_PRIVATE(QGL2PaintEngineEx) public: @@ -133,6 +132,8 @@ public: } virtual void sync(); + QGLEngineShaderManager *shaderManager() const; + private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; |