diff options
Diffstat (limited to 'src/adaptationlayers/threadedtexturemanager.cpp')
-rw-r--r-- | src/adaptationlayers/threadedtexturemanager.cpp | 136 |
1 files changed, 92 insertions, 44 deletions
diff --git a/src/adaptationlayers/threadedtexturemanager.cpp b/src/adaptationlayers/threadedtexturemanager.cpp index 616f0ec..665dbd9 100644 --- a/src/adaptationlayers/threadedtexturemanager.cpp +++ b/src/adaptationlayers/threadedtexturemanager.cpp @@ -24,29 +24,15 @@ struct TextureToUpload class QSGTTMUploadThread : public QThread { public: - QSGTTMUploadThread() { - QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); - // Getting the share widget from the current context is rather nasty and - // will not work for lighthouse based - Q_ASSERT(ctx->device() && ctx->device()->devType() == QInternal::Widget); - - QGLWidget *share = static_cast<QGLWidget *>(ctx->device()); - - widget = new QGLWidget(0, share); - widget->resize(8, 8); - - context = const_cast<QGLContext *>(widget->context()); - - widget->doneCurrent(); - - ctx->makeCurrent(); - + QSGTTMUploadThread(QSGThreadedTextureManager *m) + : manager(m) + { start(); } void run() { - context->makeCurrent(); + manager->makeThreadContextCurrent(); while (true) { @@ -66,49 +52,42 @@ public: if (work.image.isNull()) continue; -#ifdef QT_OPENGL_ES - qWarning("ThreadedTextureManager: Chances are that BGRA does not work on GLES"); -#endif - - GLuint id; - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, work.image.width(), work.image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, work.image.constBits()); - - if (work.hints & TextureManager::GenerateMipmapUploadHint) - glGenerateMipmap(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - - work.texture->setTextureId(id); - work.texture->setTextureSize(work.image.size()); - work.texture->setMipmaps(work.hints & TextureManager::GenerateMipmapUploadHint); - work.texture->setStatus(TextureReference::Uploaded); + manager->uploadInThread(work.texture, work.image, work.hints); } } - QGLWidget *widget; - QGLContext *context; + QSGThreadedTextureManager *manager; QWaitCondition condition; QMutex mutex; - QQueue<TextureToUpload> requests; + + }; class QSGThreadedTextureManagerPrivate { public: - QSGTTMUploadThread thread; + QSGTTMUploadThread *thread; + QGLContext *context; + QGLWidget *widget; }; QSGThreadedTextureManager::QSGThreadedTextureManager() { d = new QSGThreadedTextureManagerPrivate; + d->thread = 0; + d->context = 0; + d->widget = 0; } const TextureReference *QSGThreadedTextureManager::requestUploadedTexture(const QImage &image, UploadHints hints, QObject *listener, const char *slot) { + if (!d->thread) { + d->thread = new QSGTTMUploadThread(this); + initializeThreadContext(); + } + Q_ASSERT(!image.isNull()); if (hints & SynchronousUploadHint) { @@ -122,15 +101,84 @@ const TextureReference *QSGThreadedTextureManager::requestUploadedTexture(const QObject::connect(work.texture, SIGNAL(statusChanged(int)), listener, slot); - d->thread.mutex.lock(); + d->thread->mutex.lock(); - d->thread.requests << work; - d->thread.condition.wakeOne(); - d->thread.mutex.unlock(); + d->thread->requests << work; + d->thread->condition.wakeOne(); + d->thread->mutex.unlock(); return work.texture; } +/*! + Reimplement this function to initialize a non-standard threaded context. + + This function is called from the same thread as the scene graph is running + in. The default implementation will construct a QGLWidget, extract its + context and use this context in the background thread. + */ +void QSGThreadedTextureManager::initializeThreadContext() +{ + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); + // Getting the share widget from the current context is rather nasty and + // will not work for lighthouse based + Q_ASSERT(ctx->device() && ctx->device()->devType() == QInternal::Widget); + + QGLWidget *share = static_cast<QGLWidget *>(ctx->device()); + + d->widget = new QGLWidget(0, share); + d->widget->resize(8, 8); + + d->context = const_cast<QGLContext *>(d->widget->context()); + + d->widget->doneCurrent(); + + ctx->makeCurrent(); +} + + + +/*! + Reimplement this function to make the threaded context current. + + This function is called from the background thread. The default + implementation makes the context created in initializeThreadContext + current. + */ +void QSGThreadedTextureManager::makeThreadContextCurrent() +{ + d->context->makeCurrent(); +} + +/*! + Reimplement this function to upload images in the background thread. + + This function is called from the background thread. The default + implementation does this using a single glTexImage2D call. + */ + +void QSGThreadedTextureManager::uploadInThread(TextureReference *texture, const QImage &image, UploadHints hints) +{ +#ifdef QT_OPENGL_ES + qWarning("ThreadedTextureManager: Chances are that BGRA does not work on GLES"); +#endif + + GLuint id; + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D, id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); + + if (hints & TextureManager::GenerateMipmapUploadHint) + glGenerateMipmap(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, 0); + + texture->setOwnsTexture(true); + texture->setTextureId(id); + texture->setTextureSize(image.size()); + texture->setMipmaps(hints & TextureManager::GenerateMipmapUploadHint); + texture->setStatus(TextureReference::Uploaded); +} |