diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-07-24 09:45:33 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-07-27 13:04:30 (GMT) |
commit | 3643028959f0b38350e57e60ba4000435b75e592 (patch) | |
tree | c129e4dee11487abd437ab8ebd993ba261e06fa6 /src/opengl/gl2paintengineex | |
parent | cf66c667a97c0079141eb3f2d9e997b7378ae792 (diff) | |
parent | c36139c665e61866aff4bf8572890a735167a7d0 (diff) | |
download | Qt-3643028959f0b38350e57e60ba4000435b75e592.zip Qt-3643028959f0b38350e57e60ba4000435b75e592.tar.gz Qt-3643028959f0b38350e57e60ba4000435b75e592.tar.bz2 |
Merge commit 'qt/master-stable'
Conflicts:
configure.exe
qmake/Makefile.unix
qmake/generators/makefile.cpp
src/corelib/global/qglobal.h
src/corelib/kernel/kernel.pri
src/corelib/kernel/qcoreevent.cpp
src/corelib/kernel/qsharedmemory_unix.cpp
src/gui/graphicsview/qgraphicsscene.cpp
src/gui/kernel/qaction.cpp
src/gui/kernel/qaction.h
src/gui/kernel/qaction_p.h
src/gui/kernel/qapplication.cpp
src/gui/kernel/qapplication.h
src/gui/kernel/qwidget.cpp
src/gui/kernel/qwidget.h
src/gui/kernel/qwidget_mac.mm
src/gui/painting/qgraphicssystemfactory.cpp
src/gui/styles/qwindowsstyle.cpp
src/gui/text/qfontengine_qpf.cpp
src/gui/widgets/qabstractscrollarea_p.h
src/network/access/qnetworkaccessdebugpipebackend.cpp
src/network/socket/qlocalsocket_unix.cpp
src/network/socket/qnativesocketengine_p.h
src/network/socket/qnativesocketengine_unix.cpp
src/openvg/qpaintengine_vg.cpp
tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp
tests/auto/qcssparser/qcssparser.pro
tests/auto/qdir/tst_qdir.cpp
tests/auto/qfile/tst_qfile.cpp
tests/auto/qobject/tst_qobject.cpp
tests/auto/qpathclipper/qpathclipper.pro
tests/auto/qprocess/tst_qprocess.cpp
tests/auto/qsettings/tst_qsettings.cpp
tests/auto/qsharedpointer/qsharedpointer.pro
tests/auto/qsqlquerymodel/qsqlquerymodel.pro
tests/auto/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro
tests/auto/qsqltablemodel/qsqltablemodel.pro
tests/auto/qsqlthread/qsqlthread.pro
tests/auto/qwidget/tst_qwidget.cpp
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 62 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager_p.h | 29 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qglgradientcache.cpp | 29 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qglgradientcache_p.h | 27 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 163 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 25 |
6 files changed, 197 insertions, 138 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 4b73ca9..d7c91b8 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -49,6 +49,28 @@ QT_BEGIN_NAMESPACE +static void QGLEngineShaderManager_free(void *ptr) +{ + delete reinterpret_cast<QGLEngineShaderManager *>(ptr); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shader_managers, (QGLEngineShaderManager_free)) + +QGLEngineShaderManager *QGLEngineShaderManager::managerForContext(const QGLContext *context) +{ + QGLEngineShaderManager *p = reinterpret_cast<QGLEngineShaderManager *>(qt_shader_managers()->value(context)); + if (!p) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != context) + const_cast<QGLContext *>(context)->makeCurrent(); + p = new QGLEngineShaderManager(const_cast<QGLContext *>(context)); + qt_shader_managers()->insert(context, p); + if (oldContext && oldContext != context) + oldContext->makeCurrent(); + } + return p; +} + const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, @@ -190,27 +212,33 @@ QGLEngineShaderManager::~QGLEngineShaderManager() //### } - -uint QGLEngineShaderManager::getUniformIdentifier(const char *uniformName) -{ - uniformIdentifiers << uniformName; - return uniformIdentifiers.size() - 1; -} - -uint QGLEngineShaderManager::getUniformLocation(uint id) +uint QGLEngineShaderManager::getUniformLocation(Uniform id) { QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; - uint oldSize = uniformLocations.size(); - if (oldSize <= id) { - uint newSize = id + 1; - uniformLocations.resize(newSize); - - for (uint i = oldSize; i < newSize; ++i) - uniformLocations[i] = GLuint(-1); - } + if (uniformLocations.isEmpty()) + uniformLocations.fill(GLuint(-1), NumUniforms); + + static const char *uniformNames[] = { + "imageTexture", + "patternColor", + "globalOpacity", + "depth", + "pmvMatrix", + "maskTexture", + "fragmentColor", + "linearData", + "angle", + "halfViewportSize", + "fmp", + "fmp2_m_radius2", + "inverse_2_fmp2_m_radius2", + "invertedTextureSize", + "brushTransform", + "brushTexture" + }; if (uniformLocations.at(id) == GLuint(-1)) - uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformIdentifiers.at(id)); + uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]); return uniformLocations.at(id); } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 34f0768..99711bd40 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -220,6 +220,7 @@ #include <QGLShader> #include <QGLShaderProgram> #include <QPainter> +#include <private/qgl_p.h> QT_BEGIN_HEADER @@ -274,6 +275,26 @@ public: TextureSrcWithPattern = Qt::TexturePattern+4 }; + enum Uniform { + ImageTexture, + PatternColor, + GlobalOpacity, + Depth, + PmvMatrix, + MaskTexture, + FragmentColor, + LinearData, + Angle, + HalfViewportSize, + Fmp, + Fmp2MRadius2, + Inverse2Fmp2MRadius2, + InvertedTextureSize, + BrushTransform, + BrushTexture, + NumUniforms + }; + // There are optimisations we can do, depending on the brush transform: // 1) May not have to apply perspective-correction // 2) Can use lower precision for matrix @@ -285,8 +306,7 @@ public: void setMaskType(MaskType); void setCompositionMode(QPainter::CompositionMode); - uint getUniformIdentifier(const char *uniformName); - uint getUniformLocation(uint id); + uint getUniformLocation(Uniform id); void setDirty(); // someone has manually changed the current shader program bool useCorrectShaderProg(); // returns true if the shader program needed to be changed @@ -295,6 +315,8 @@ public: QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer + static QGLEngineShaderManager *managerForContext(const QGLContext *context); + enum ShaderName { MainVertexShader, MainWithTexCoordsVertexShader, @@ -352,6 +374,7 @@ public: TotalShaderCount, InvalidShaderName }; + /* // These allow the ShaderName enum to be used as a cache key const int mainVertexOffset = 0; @@ -391,8 +414,6 @@ private: void compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type); static const char* qglEngineShaderSourceCode[TotalShaderCount]; - - QVector<const char *> uniformIdentifiers; }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index 8c6b4f0..7c54bb9 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -46,6 +46,28 @@ QT_BEGIN_NAMESPACE +static void QGL2GradientCache_free(void *ptr) +{ + delete reinterpret_cast<QGL2GradientCache *>(ptr); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) + +QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) +{ + QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context)); + if (!p) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != context) + const_cast<QGLContext *>(context)->makeCurrent(); + p = new QGL2GradientCache; + qt_gradient_caches()->insert(context, p); + if (oldContext && oldContext != context) + oldContext->makeCurrent(); + } + return p; +} + void QGL2GradientCache::cleanCache() { QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { @@ -55,13 +77,8 @@ void QGL2GradientCache::cleanCache() { cache.clear(); } -GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx) +GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { - if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx)) - cleanCache(); - - buffer_ctx = ctx; - quint64 hash_val = 0; QGradientStops stops = gradient.stops(); diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 55c7b65..ba698bc 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -53,12 +53,12 @@ #include <QMultiHash> #include <QObject> #include <QtOpenGL/QtOpenGL> +#include <private/qgl_p.h> QT_BEGIN_NAMESPACE -class QGL2GradientCache : public QObject +class QGL2GradientCache { - Q_OBJECT struct CacheInfo { inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) : @@ -73,16 +73,12 @@ class QGL2GradientCache : public QObject typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash; public: - QGL2GradientCache() : QObject(), buffer_ctx(0) - { -/* - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext *)), - SLOT(cleanupGLContextRefs(const QGLContext *))); -*/ - } + static QGL2GradientCache *cacheForContext(const QGLContext *context); + + QGL2GradientCache() { } + ~QGL2GradientCache() {cleanCache();} - GLuint getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx); + GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } protected: @@ -95,15 +91,6 @@ protected: void cleanCache(); QGLGradientColorTableHash cache; - const QGLContext *buffer_ctx; - -public slots: - void cleanupGLContextRefs(const QGLContext *context) { - if (context == buffer_ctx) { - cleanCache(); - buffer_ctx = 0; - } - } }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index c4f5891..5c85b40 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -74,6 +74,7 @@ #include <private/qpainter_p.h> #include <private/qfontengine_p.h> #include <private/qtextureglyphcache_p.h> +#include <private/qpixmapdata_gl_p.h> #include "qglgradientcache_p.h" #include "qglengineshadermanager_p.h" @@ -88,8 +89,9 @@ static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush static const GLuint QT_MASK_TEXTURE_UNIT = 1; static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2; -class QGLTextureGlyphCache : public QTextureGlyphCache +class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache { + Q_OBJECT public: QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); @@ -105,6 +107,25 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + +public Q_SLOTS: + void contextDestroyed(const QGLContext *context) { + if (context == ctx) { + QList<const QGLContext *> shares = qgl_share_reg()->shares(ctx); + if (shares.isEmpty()) { + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + ctx = 0; + } else { + // since the context holding the texture is shared, and + // about to be destroyed, we have to transfer ownership + // of the texture to one of the share contexts + ctx = const_cast<QGLContext *>(shares.at(0)); + } + } + } + private: QGLContext *ctx; @@ -126,14 +147,23 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph , m_height(0) { glGenFramebuffers(1, &m_fbo); + connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext *)), + SLOT(contextDestroyed(const QGLContext *))); } QGLTextureGlyphCache::~QGLTextureGlyphCache() { - glDeleteFramebuffers(1, &m_fbo); - - if (m_width || m_height) - glDeleteTextures(1, &m_texture); + if (ctx) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != ctx) + ctx->makeCurrent(); + glDeleteFramebuffers(1, &m_fbo); + + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + if (oldContext && oldContext != ctx) + oldContext->makeCurrent(); + } } void QGLTextureGlyphCache::createTextureData(int width, int height) @@ -231,8 +261,11 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, m_height - c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { - mask = mask.convertToFormat(QImage::Format_Indexed8); - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits()); + // If the width of the uploaded data is not a multiple of four bytes, we get some garbage + // in the glyph cache, probably because of a driver bug. + // Convert to ARGB32 to get a multiple of 4 bytes per line. + mask = mask.convertToFormat(QImage::Format_ARGB32); + glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } } @@ -242,16 +275,12 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert); QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() { - if (shaderManager) { - delete shaderManager; - shaderManager = 0; - } } 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; @@ -271,6 +300,7 @@ void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMod QColor QGL2PaintEngineExPrivate::premultiplyColor(QColor c, GLfloat opacity) { qreal alpha = c.alphaF() * opacity; + c.setAlphaF(alpha); c.setRedF(c.redF() * alpha); c.setGreenF(c.greenF() * alpha); c.setBlueF(c.blueF() * alpha); @@ -314,9 +344,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader() } } - -Q_GLOBAL_STATIC(QGL2GradientCache, qt_opengl_gradient_cache) - void QGL2PaintEngineExPrivate::updateBrushTexture() { // qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()"); @@ -337,7 +364,10 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() // We apply global opacity in the fragment shaders, so we always pass 1.0 // for opacity to the cache. - GLuint texId = qt_opengl_gradient_cache()->getBuffer(*g, 1.0, ctx); + GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0); + + glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, texId); if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient) updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); @@ -345,9 +375,6 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, true); else updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true); - - glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); - glBindTexture(GL_TEXTURE_2D, texId); } else if (style == Qt::TexturePattern) { const QPixmap& texPixmap = currentBrush->texture(); @@ -372,7 +399,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() if (style == Qt::SolidPattern) { QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(FragmentColor), col); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col); } else { // All other brushes have a transform and thus need the translation point: @@ -383,10 +410,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(PatternColor), col); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::LinearGradientPattern) { const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient()); @@ -403,10 +430,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() 1.0f / (l.x() * l.x() + l.y() * l.y()) ); - shaderManager->currentProgram()->setUniformValue(location(LinearData), linearData); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::LinearData), linearData); QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::ConicalGradientPattern) { const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient()); @@ -414,10 +441,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0; - shaderManager->currentProgram()->setUniformValue(location(Angle), angle); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Angle), angle); QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::RadialGradientPattern) { const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient()); @@ -427,15 +454,15 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() translationPoint = realFocal; QPointF fmp = realCenter - realFocal; - shaderManager->currentProgram()->setUniformValue(location(Fmp), fmp); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp), fmp); GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius; - shaderManager->currentProgram()->setUniformValue(location(Fmp2MRadius2), fmp2_m_radius2); - shaderManager->currentProgram()->setUniformValue(location(Inverse2Fmp2MRadius2), + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2), GLfloat(1.0 / (2.0*fmp2_m_radius2))); QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else if (style == Qt::TexturePattern) { translationPoint = q->state()->brushOrigin; @@ -444,14 +471,14 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) { QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(PatternColor), col); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } QSizeF invertedTextureSize( 1.0 / texPixmap.width(), 1.0 / texPixmap.height() ); - shaderManager->currentProgram()->setUniformValue(location(InvertedTextureSize), invertedTextureSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::InvertedTextureSize), invertedTextureSize); QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(HalfViewportSize), halfViewportSize); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize); } else qWarning("QGL2PaintEngineEx: Unimplemented fill style"); @@ -460,8 +487,8 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() QTransform gl_to_qt(1, 0, 0, -1, 0, height); QTransform inv_matrix = gl_to_qt * (brushQTransform * q->state()->matrix).inverted() * translate; - shaderManager->currentProgram()->setUniformValue(location(BrushTransform), inv_matrix); - shaderManager->currentProgram()->setUniformValue(location(BrushTexture), QT_BRUSH_TEXTURE_UNIT); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTransform), inv_matrix); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT); } brushUniformsDirty = false; } @@ -599,11 +626,11 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); shaderManager->setTextureCoordsEnabled(true); if (prepareForDraw(opaque)) - shaderManager->currentProgram()->setUniformValue(location(ImageTexture), QT_IMAGE_TEXTURE_UNIT); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); if (pattern) { QColor col = premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(PatternColor), col); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } GLfloat dx = 1.0 / textureSize.width(); @@ -655,6 +682,11 @@ void QGL2PaintEngineEx::sync() glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(true); + glClearDepth(1); + d->needsSync = true; } @@ -847,17 +879,17 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) updateBrushUniforms(); if (shaderMatrixUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(PmvMatrix), pmvMatrix); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PmvMatrix), pmvMatrix); shaderMatrixUniformDirty = false; } if (depthUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(Depth), (GLfloat)q->state()->currentDepth); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), (GLfloat)q->state()->currentDepth); depthUniformDirty = false; } if (useGlobalOpacityUniform && opacityUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(GlobalOpacity), (GLfloat)q->state()->opacity); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); opacityUniformDirty = false; } @@ -1023,14 +1055,18 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - GLuint id = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true); + QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true, true); + + GLfloat top = texture->yInverted ? (pixmap.height() - src.top()) : src.top(); + GLfloat bottom = texture->yInverted ? (pixmap.height() - src.bottom()) : src.bottom(); + QGLRect srcRect(src.left(), top, src.right(), bottom); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel(); d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, - state()->renderHints & QPainter::SmoothPixmapTransform, id); - d->drawTexture(dest, src, pixmap.size(), isOpaque, isBitmap); + state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); + d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); } void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src, @@ -1042,7 +1078,8 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - GLuint id = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + GLuint id = texture->id; d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, state()->renderHints & QPainter::SmoothPixmapTransform, id); @@ -1140,7 +1177,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte prepareForDraw(false); // Text always causes src pixels to be transparent - shaderManager->currentProgram()->setUniformValue(location(MaskTexture), QT_MASK_TEXTURE_UNIT); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr) glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data()); @@ -1180,28 +1217,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) qt_resolve_version_2_0_functions(d->ctx); #endif - if (d->shaderManager) { - d->shaderManager->setDirty(); - } else { - d->shaderManager = new QGLEngineShaderManager(d->ctx); - - d->uniformIdentifiers[QGL2PaintEngineExPrivate::ImageTexture] = d->shaderManager->getUniformIdentifier("imageTexture"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::PatternColor] = d->shaderManager->getUniformIdentifier("patternColor"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::GlobalOpacity] = d->shaderManager->getUniformIdentifier("globalOpacity"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::Depth] = d->shaderManager->getUniformIdentifier("depth"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::PmvMatrix] = d->shaderManager->getUniformIdentifier("pmvMatrix"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::MaskTexture] = d->shaderManager->getUniformIdentifier("maskTexture"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::FragmentColor] = d->shaderManager->getUniformIdentifier("fragmentColor"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::LinearData] = d->shaderManager->getUniformIdentifier("linearData"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::Angle] = d->shaderManager->getUniformIdentifier("angle"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::HalfViewportSize] = d->shaderManager->getUniformIdentifier("halfViewportSize"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::Fmp] = d->shaderManager->getUniformIdentifier("fmp"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::Fmp2MRadius2] = d->shaderManager->getUniformIdentifier("fmp2_m_radius2"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::Inverse2Fmp2MRadius2] = d->shaderManager->getUniformIdentifier("inverse_2_fmp2_m_radius2"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::InvertedTextureSize] = d->shaderManager->getUniformIdentifier("invertedTextureSize"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::BrushTransform] = d->shaderManager->getUniformIdentifier("brushTransform"); - d->uniformIdentifiers[QGL2PaintEngineExPrivate::BrushTexture] = d->shaderManager->getUniformIdentifier("brushTexture"); - } + d->shaderManager = QGLEngineShaderManager::managerForContext(d->ctx); + d->shaderManager->setDirty(); glViewport(0, 0, d->width, d->height); @@ -1276,6 +1293,14 @@ bool QGL2PaintEngineEx::end() glUseProgram(0); d->transferMode(BrushDrawingMode); d->drawable.swapBuffers(); +#if defined(Q_WS_X11) + // On some (probably all) drivers, deleting an X pixmap which has been bound to a texture + // before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes + // the pixmap behind the driver's back before it's had a chance to use it. To fix this, we + // reference all QPixmaps which have been bound to stop them being deleted and only deref + // them here, after swapBuffers, where they can be safely deleted. + ctx->d_func()->boundPixmaps.clear(); +#endif d->drawable.doneCurrent(); d->ctx->d_ptr->active_engine = 0; @@ -1408,7 +1433,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) if (state()->matrix.type() <= QTransform::TxScale) { rect = state()->matrix.mapRect(rect); - if (d->use_system_clip && rect.contains(d->systemClip.boundingRect()) + if ((d->use_system_clip && rect.contains(d->systemClip.boundingRect())) || rect.contains(QRect(0, 0, d->width, d->height))) return; } @@ -1606,3 +1631,5 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() } QT_END_NAMESPACE + +#include "qpaintengineex_opengl2.moc" diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 0d28a49..ec447a3 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -221,32 +221,11 @@ public: void systemStateChanged(); uint use_system_clip : 1; - enum Uniform { - ImageTexture, - PatternColor, - GlobalOpacity, - Depth, - PmvMatrix, - MaskTexture, - FragmentColor, - LinearData, - Angle, - HalfViewportSize, - Fmp, - Fmp2MRadius2, - Inverse2Fmp2MRadius2, - InvertedTextureSize, - BrushTransform, - BrushTexture, - NumUniforms - }; - - uint location(Uniform uniform) + uint location(QGLEngineShaderManager::Uniform uniform) { - return shaderManager->getUniformLocation(uniformIdentifiers[uniform]); + return shaderManager->getUniformLocation(uniform); } - uint uniformIdentifiers[NumUniforms]; GLuint lastTexture; bool needsSync; |