diff options
Diffstat (limited to 'src/opengl/gl2paintengineex')
6 files changed, 56 insertions, 119 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 0ba324d..888bac9 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -48,65 +48,54 @@ QT_BEGIN_NAMESPACE +class QGLSharedShaderResource : public QGLContextResource +{ +public: + ~QGLSharedShaderResource() { + qDebug() << "~QGLSharedShaderResource cleaned up" << hex << this; + } -// Handling the cleanup and creation of the thread-local shader cache -// differes from other QGLContextResources. The cache needs to be -// cleaned up when the thread exits, or when its group context is -// destroyed. - -static void qt_gl_free_shared_shaders(void *value); + void freeResource(void *value) + { + qDebug() << "Context destroyed:"; + qDebug() << " -> deleting shader cache" << hex << value; + delete reinterpret_cast<QGLEngineSharedShaders *>(value); + } +}; class QGLThreadLocalShaders { public: - QGLThreadLocalShaders(const QGLContext *context, QGLEngineSharedShaders *shaders) - : m_context(context), m_shaders(shaders) - { - m_resource = new QGLContextResource(qt_gl_free_shared_shaders); - m_resource->insert(context, this); + QGLEngineSharedShaders *shadersForContext(const QGLContext *context) { + QGLEngineSharedShaders *shaders = reinterpret_cast<QGLEngineSharedShaders *>(m_resource.value(context)); + if (!shaders) { + QGLShareContextScope scope(context); + shaders = new QGLEngineSharedShaders(context); + qDebug() << " -> new shader cache for context:" << hex << context << "cache:" << shaders; + m_resource.insert(context, shaders); + } + return shaders; } + ~QGLThreadLocalShaders() { qDebug() << "Thread exit:"; qDebug() << "~QGLThreadLocalShaders() for thread:" << hex << QThread::currentThread(); - qDebug() << " -> deleting shader cache:" << hex << m_shaders; - delete m_shaders; - // remove the resource from the group's resource list, so that - // the cleanup function is not called when the context is destroyed - m_resource->remove(m_context); - delete m_resource; } - const QGLContext *m_context; - QGLEngineSharedShaders *m_shaders; - QGLContextResource *m_resource; -}; -static void qt_gl_free_shared_shaders(void *value) -{ - QGLThreadLocalShaders *local = reinterpret_cast<QGLThreadLocalShaders *>(value); - qDebug() << "Context destroyed:"; - qDebug() << " -> deleting shader cache" << hex << local->m_shaders; - delete local->m_shaders; - local->m_shaders = 0; - - // this function is called when the context group for the context - // we have ref'ed is deleted - that means our context ptr is no - // longer valid - local->m_context = 0; -} +private: + QGLSharedShaderResource m_resource; +}; class QGLShaderStorage { public: QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { - QGLThreadLocalShaders *shaders = m_storage.localData(); + QGLThreadLocalShaders *&shaders = m_storage.localData(); if (!shaders) { - qDebug() << "New shader cache for thread:" << hex << QThread::currentThread(); - QGLShareContextScope scope(context); - shaders = new QGLThreadLocalShaders(context, new QGLEngineSharedShaders(context)); - qDebug() << " -> context:" << context; - m_storage.setLocalData(shaders); + qDebug() << "New thread storage for:" << hex << QThread::currentThread(); + shaders = new QGLThreadLocalShaders; } - return shaders->m_shaders; + return shaders->shadersForContext(context); } private: @@ -282,15 +271,6 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) QGLEngineSharedShaders::~QGLEngineSharedShaders() { - cleanupBeforeDestruction(); -} - - -// This might be called both when a thread exits, or when the a -// context is destroyed - -void QGLEngineSharedShaders::cleanupBeforeDestruction() -{ qDeleteAll(shaders); shaders.clear(); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 8d3697b..e5ababf 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -364,10 +364,6 @@ public: // full. void cleanupCustomStage(QGLCustomShaderStage* stage); - // this is needed so that threads can get a foot in and have a chance to - // clean up the shaders they've created before the thread exits - void cleanupBeforeDestruction(); - private: QGLSharedResourceGuard ctxGuard; QGLShaderProgram *blitShaderProg; diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index a1495dd..a0a3f8f 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -46,12 +46,16 @@ QT_BEGIN_NAMESPACE -static void QGL2GradientCache_free(void *ptr) +class QGLGradientCacheResource : public QGLContextResource { - delete reinterpret_cast<QGL2GradientCache *>(ptr); -} +public: + void freeResource(void *value) + { + delete reinterpret_cast<QGL2GradientCache *>(value); + } +}; -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) +Q_GLOBAL_STATIC(QGLGradientCacheResource, qt_gradient_caches) QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) { diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 634b315..260e797 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1457,6 +1457,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform()); if (!cache || cache->cacheType() != glyphType) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); + cache->insert(ctx, cache); staticTextItem->fontEngine->setGlyphCache(ctx, cache); } diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index faf4563..001a09e 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -54,45 +54,10 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled; QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) - , ctx(0) - , pex(0) + , ctx(context) , m_width(0) , m_height(0) { - if (context != 0) - setContext(context); -} - -QGLTextureGlyphCache::~QGLTextureGlyphCache() -{ - cleanUpContext(); -} - -void QGLTextureGlyphCache::cleanUpContext() -{ - if (ctx) { - QGLShareContextScope scope(ctx); - - if (!ctx->d_ptr->workaround_brokenFBOReadBack && pex != 0) - glDeleteFramebuffers(1, &m_fbo); - - if (m_width || m_height) { - glDeleteTextures(1, &m_texture); - m_width = 0; - m_height = 0; - m_h = 0; - } - - ctx = 0; - } -} - -void QGLTextureGlyphCache::setContext(const QGLContext *context) -{ - cleanUpContext(); - - ctx = context; - // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The // workaround is to use a system-memory copy of the glyph cache for this device. @@ -101,8 +66,12 @@ void QGLTextureGlyphCache::setContext(const QGLContext *context) if (!ctx->d_ptr->workaround_brokenFBOReadBack && pex != 0) glGenFramebuffers(1, &m_fbo); - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(contextDestroyed(const QGLContext*))); + fprintf(stderr, "## QGLTextureGlyphCache(): ctx: %p - this: %p\n", ctx, this); +} + +QGLTextureGlyphCache::~QGLTextureGlyphCache() +{ + fprintf(stderr, "## ~QGLTextureGlyphCache(): context: %p - this: %p\n", ctx, this); } void QGLTextureGlyphCache::createTextureData(int width, int height) @@ -161,7 +130,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) GLuint oldTexture = m_texture; createTextureData(width, height); - + if (pex == 0 || ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index d291ac3..710a12d 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -62,9 +62,8 @@ QT_BEGIN_NAMESPACE class QGL2PaintEngineExPrivate; -class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache +class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QGLContextResource, public QImageTextureGlyphCache { - Q_OBJECT public: QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); @@ -82,33 +81,21 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } - void setContext(const QGLContext *context); inline const QGLContext *context() const { return ctx; } + void freeResource(void *) { + qDebug() << "QGLTextureGlyphCache::freeResource():" << this << "ctx:" << ctx; + // At this point, the context group is made current, so it's safe to + // release resources without a makeCurrent() call + if (!ctx->d_ptr->workaround_brokenFBOReadBack) + glDeleteFramebuffers(1, &m_fbo); -public Q_SLOTS: - void contextDestroyed(const QGLContext *context) { - if (context == ctx) { - const QGLContext *nextCtx = qt_gl_transfer_context(ctx); - if (!nextCtx) { - // the context may not be current, so we cannot directly - // destroy the fbo and texture here, but since the context - // is about to be destroyed, the GL server will do the - // clean up for us anyway - m_fbo = 0; - m_texture = 0; - 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 *>(nextCtx); - } - } + if (m_width || m_height) + glDeleteTextures(1, &m_texture); } private: |