summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Kjernåsen <trond.kjernasen@nokia.com>2010-04-16 09:38:20 (GMT)
committerTrond Kjernåsen <trond.kjernasen@nokia.com>2010-07-02 10:24:59 (GMT)
commit4c3ac765b26e56fbf08c9f70cf43aa00a6565cae (patch)
tree20d12784bb7ef1e402b0d57f59d7820ca45672c0
parent7e464e38009f2492a41e9972a75f868cf88d353a (diff)
downloadQt-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.cpp49
-rw-r--r--src/opengl/qgl.cpp9
-rw-r--r--src/opengl/qgl_p.h2
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;