diff options
author | Trond Kjernåsen <trond.kjernasen@nokia.com> | 2010-04-16 09:38:20 (GMT) |
---|---|---|
committer | Trond Kjernåsen <trond.kjernasen@nokia.com> | 2010-07-02 10:24:59 (GMT) |
commit | 4c3ac765b26e56fbf08c9f70cf43aa00a6565cae (patch) | |
tree | 20d12784bb7ef1e402b0d57f59d7820ca45672c0 | |
parent | 7e464e38009f2492a41e9972a75f868cf88d353a (diff) | |
download | Qt-4c3ac765b26e56fbf08c9f70cf43aa00a6565cae.zip Qt-4c3ac765b26e56fbf08c9f70cf43aa00a6565cae.tar.gz Qt-4c3ac765b26e56fbf08c9f70cf43aa00a6565cae.tar.bz2 |
Don't use the QGLSignalProxy to clean up the thread-local shaders.
After much back and forth I think we can use this approach for cleaning
up thread-local, shared resources. Main problem has been dealing with
dangling pointers and references, but they should be solved now.
-rw-r--r-- | src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 49 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 9 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 2 |
3 files changed, 43 insertions, 17 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 7d6d8a6..0ba324d 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -48,42 +48,59 @@ QT_BEGIN_NAMESPACE -class QGLThreadLocalShaders : public QObject + +// 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); + +class QGLThreadLocalShaders { - Q_OBJECT public: QGLThreadLocalShaders(const QGLContext *context, QGLEngineSharedShaders *shaders) : m_context(context), m_shaders(shaders) { - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(contextDestroyed(const QGLContext*))); + m_resource = new QGLContextResource(qt_gl_free_shared_shaders); + m_resource->insert(context, this); } ~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; - -private slots: - void contextDestroyed(const QGLContext * context) { - if (context == m_context) { - qDebug() << "QGLThreadLocalShaders::contextDestroyed():"; - qDebug() << " -> cleaning up shader cache for thread:" << hex << QThread::currentThread(); - qDebug() << " -> shaders:" << hex << m_shaders; - m_shaders->cleanupBeforeDestruction(); - } - } + 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; +} + class QGLShaderStorage { public: QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { QGLThreadLocalShaders *shaders = m_storage.localData(); if (!shaders) { - qDebug() << "new shader cache for thread:" << hex << QThread::currentThread(); + qDebug() << "New shader cache for thread:" << hex << QThread::currentThread(); QGLShareContextScope scope(context); shaders = new QGLThreadLocalShaders(context, new QGLEngineSharedShaders(context)); qDebug() << " -> context:" << context; @@ -840,5 +857,3 @@ bool QGLEngineShaderManager::useCorrectShaderProg() } QT_END_NAMESPACE - -#include "qglengineshadermanager.moc" diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 995e753..1223552 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -5377,6 +5377,15 @@ void QGLContextResource::cleanup(const QGLContext *ctx, void *value) active.deref(); } +void QGLContextResource::remove(const QGLContext *ctx) +{ + if (ctx) { + QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); + group->m_resources.remove(this); + active.deref(); + } +} + void QGLContextGroup::cleanupResources(const QGLContext *ctx) { // If there are still shares, then no cleanup to be done yet. diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 9b862eb..d5083e9 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -624,6 +624,8 @@ public: void *value(const QGLContext *key); // Cleanup 'value' in response to a context group being destroyed. void cleanup(const QGLContext *ctx, void *value); + // Remove this resource from the group's resource list. + void remove(const QGLContext *ctx); private: FreeFunc free; QAtomicInt active; |