summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex
diff options
context:
space:
mode:
authorTrond Kjernåsen <trond.kjernasen@nokia.com>2010-06-22 10:51:00 (GMT)
committerTrond Kjernåsen <trond.kjernasen@nokia.com>2010-07-02 10:24:47 (GMT)
commit38922774119817f4bf1595b9651f914e5c3d9f02 (patch)
tree55870e86a85c95d22b2115c89d49343dd0767fbc /src/opengl/gl2paintengineex
parent9f72c297843459ab22eeb3af048baa9037aa9634 (diff)
downloadQt-38922774119817f4bf1595b9651f914e5c3d9f02.zip
Qt-38922774119817f4bf1595b9651f914e5c3d9f02.tar.gz
Qt-38922774119817f4bf1595b9651f914e5c3d9f02.tar.bz2
More work on GL threading.
Removed QObject inheritance from QGLEngineSharedShaders and made it thread-local, so that paintengines in different threads can use programs without clashing. Lifted some restrictions on QPixmap so that they may be used in threads when the GL2 engine is active. Made the QGLContextGroup a part of the pixmap and image cache keys.
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp94
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h13
2 files changed, 82 insertions, 25 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 40b3641..5330706 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -51,19 +51,61 @@ QT_BEGIN_NAMESPACE
static void qt_shared_shaders_free(void *data)
{
+ qDebug() << "qt_shared_shaders_free() for thread:" << hex << QThread::currentThread();
delete reinterpret_cast<QGLEngineSharedShaders *>(data);
}
-Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_shaders, (qt_shared_shaders_free))
+
+class QGLThreadLocalShaders {
+public:
+ QGLThreadLocalShaders(QGLContextResource *resource) : m_resource(resource), m_shaders(0) {}
+ ~QGLThreadLocalShaders() {
+ if (m_shaders) {
+ qDebug() << "~QGLThreadLocalShaders() for thread:" << hex << QThread::currentThread();
+ m_shaders->cleanupBeforeDestruction();
+ }
+ }
+ QGLContextResource *m_resource;
+ QGLEngineSharedShaders *m_shaders;
+};
+
+class QGLThreadShaders
+{
+public:
+ QGLContextResource *shadersForThread() {
+ QGLThreadLocalShaders *shaders = m_storage.localData();
+ if (!shaders) {
+ // The QGLContextResource is needed because the shaders need to be cleaned up
+ // when the context is destroyed, not just when a thread exits
+ QGLContextResource *resource = new QGLContextResource(qt_shared_shaders_free);
+ qDebug() << "new local resource for thread:" << hex << QThread::currentThread() << resource;
+ shaders = new QGLThreadLocalShaders(resource);
+ m_storage.setLocalData(shaders);
+ }
+ return shaders->m_resource;
+ }
+
+ void setShadersForThread(const QGLContext *context, QGLEngineSharedShaders *sharedShaders) {
+ shadersForThread()->insert(context, sharedShaders);
+ m_storage.localData()->m_shaders = sharedShaders;
+ qDebug() << " -> context:" << context;
+ }
+
+private:
+ QThreadStorage<QGLThreadLocalShaders *> m_storage;
+};
+
+Q_GLOBAL_STATIC(QGLThreadShaders, qt_shared_shaders);
QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context)
{
- QGLEngineSharedShaders *p = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->value(context));
- if (!p) {
+ QGLEngineSharedShaders *shaders = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->shadersForThread()->value(context));
+ if (!shaders) {
QGLShareContextScope scope(context);
- qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context));
+ shaders = new QGLEngineSharedShaders(context);
+ qt_shared_shaders()->setShadersForThread(context, shaders);
}
- return p;
+ return shaders;
}
const char* QGLEngineSharedShaders::qShaderSnippets[] = {
@@ -170,18 +212,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
source.clear();
source.append(qShaderSnippets[MainVertexShader]);
source.append(qShaderSnippets[PositionOnlyVertexShader]);
- vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+ vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
+ shaders.append(vertexShader);
if (!vertexShader->compileSourceCode(source))
qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
source.clear();
source.append(qShaderSnippets[MainFragmentShader]);
source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
- fragShader = new QGLShader(QGLShader::Fragment, context, this);
+ fragShader = new QGLShader(QGLShader::Fragment, context, 0);
+ shaders.append(fragShader);
if (!fragShader->compileSourceCode(source))
qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
- simpleShaderProg = new QGLShaderProgram(context, this);
+ simpleShaderProg = new QGLShaderProgram(context, 0);
simpleShaderProg->addShader(vertexShader);
simpleShaderProg->addShader(fragShader);
simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
@@ -198,18 +242,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
source.clear();
source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
source.append(qShaderSnippets[UntransformedPositionVertexShader]);
- vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+ vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
+ shaders.append(vertexShader);
if (!vertexShader->compileSourceCode(source))
qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
source.clear();
source.append(qShaderSnippets[MainFragmentShader]);
source.append(qShaderSnippets[ImageSrcFragmentShader]);
- fragShader = new QGLShader(QGLShader::Fragment, context, this);
+ fragShader = new QGLShader(QGLShader::Fragment, context, 0);
+ shaders.append(fragShader);
if (!fragShader->compileSourceCode(source))
qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
- blitShaderProg = new QGLShaderProgram(context, this);
+ blitShaderProg = new QGLShaderProgram(context, 0);
blitShaderProg->addShader(vertexShader);
blitShaderProg->addShader(fragShader);
blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
@@ -224,9 +270,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
QGLEngineSharedShaders::~QGLEngineSharedShaders()
{
- QList<QGLEngineShaderProg*>::iterator itr;
- for (itr = cachedPrograms.begin(); itr != cachedPrograms.end(); ++itr)
- delete *itr;
+ cleanupBeforeDestruction();
+}
+
+
+// This might be called both when a thread exits, or when the a
+// context is destroyed
+
+void QGLEngineSharedShaders::cleanupBeforeDestruction()
+{
+ qDeleteAll(shaders);
+ shaders.clear();
+
+ qDeleteAll(cachedPrograms);
+ cachedPrograms.clear();
if (blitShaderProg) {
delete blitShaderProg;
@@ -276,7 +333,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
source.append(qShaderSnippets[prog.compositionFragShader]);
if (prog.maskFragShader)
source.append(qShaderSnippets[prog.maskFragShader]);
- fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
+ fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0);
+ shaders.append(fragShader);
QByteArray description;
#if defined(QT_DEBUG)
// Name the shader for easier debugging
@@ -302,7 +360,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
source.clear();
source.append(qShaderSnippets[prog.mainVertexShader]);
source.append(qShaderSnippets[prog.positionVertexShader]);
- vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
+ vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0);
+ shaders.append(vertexShader);
#if defined(QT_DEBUG)
// Name the shader for easier debugging
description.clear();
@@ -320,7 +379,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
newProg = new QGLEngineShaderProg(prog);
// If the shader program's not found in the cache, create it now.
- newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
+ newProg->program = new QGLShaderProgram(ctxGuard.context(), 0);
newProg->program->addShader(vertexShader);
newProg->program->addShader(fragShader);
@@ -413,7 +472,6 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
currentShaderProg(0)
{
sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
- connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot()));
}
QGLEngineShaderManager::~QGLEngineShaderManager()
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 06b96ae..8d3697b 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -259,9 +259,9 @@ static const GLuint QT_PMV_MATRIX_3_ATTR = 5;
class QGLEngineShaderProg;
-class QGLEngineSharedShaders : public QObject
+class QGLEngineSharedShaders
{
- Q_OBJECT
+ Q_GADGET
public:
enum SnippetName {
@@ -364,14 +364,16 @@ public:
// full.
void cleanupCustomStage(QGLCustomShaderStage* stage);
-signals:
- void shaderProgNeedsChanging();
+ // 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;
QGLShaderProgram *simpleShaderProg;
QList<QGLEngineShaderProg*> cachedPrograms;
+ QList<QGLShader *> shaders;
static const char* qShaderSnippets[TotalSnippetCount];
};
@@ -492,9 +494,6 @@ public:
QGLEngineSharedShaders* sharedShaders;
-private slots:
- void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; }
-
private:
QGLContext* ctx;
bool shaderProgNeedsChanging;