diff options
Diffstat (limited to 'src/adaptationlayers/threadedtexturemanager.cpp')
-rw-r--r-- | src/adaptationlayers/threadedtexturemanager.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/adaptationlayers/threadedtexturemanager.cpp b/src/adaptationlayers/threadedtexturemanager.cpp new file mode 100644 index 0000000..a1af9cf --- /dev/null +++ b/src/adaptationlayers/threadedtexturemanager.cpp @@ -0,0 +1,124 @@ +#include "threadedtexturemanager.h" + +#include <QWaitCondition> +#include <QMutex> +#include <QThread> + +#include <QQueue> +#include <QPaintDevice> +#include <QGLWidget> + + +struct TextureToUpload +{ + QImage image; + TextureReference *texture; + TextureManager::UploadHints hints; +}; + +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(); + + start(); + } + + void run() { + + context->makeCurrent(); + + while (true) { + + mutex.lock(); + if (requests.isEmpty()) { + condition.wait(&mutex); + } + + if (requests.isEmpty()) { + mutex.unlock(); + continue; + } + + TextureToUpload work = requests.dequeue(); + mutex.unlock(); + + if (work.image.isNull()) + continue; + + 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); + + work.texture->setTextureId(id); + work.texture->setTextureSize(work.image.size()); + work.texture->setMipmaps(work.hints & TextureManager::GenerateMipmapUploadHint); + work.texture->setStatus(TextureReference::Uploaded); + } + } + + QGLWidget *widget; + QGLContext *context; + + QWaitCondition condition; + QMutex mutex; + + QQueue<TextureToUpload> requests; +}; + +class QSGThreadedTextureManagerPrivate +{ +public: + QSGTTMUploadThread thread; +}; + +QSGThreadedTextureManager::QSGThreadedTextureManager() +{ + d = new QSGThreadedTextureManagerPrivate; +} + +const TextureReference *QSGThreadedTextureManager::requestUploadedTexture(const QImage &image, UploadHints hints, QObject *listener, const char *slot) +{ + Q_ASSERT(!image.isNull()); + + if (hints & SynchronousUploadHint) { + return TextureManager::requestUploadedTexture(image, hints, listener, slot); + } + + TextureToUpload work; + work.texture = new TextureReference; + work.image = image; + work.hints = hints; + + QObject::connect(work.texture, SIGNAL(statusChanged(int)), listener, slot); + + d->thread.mutex.lock(); + d->thread.requests << work; + d->thread.condition.wakeOne(); + d->thread.mutex.unlock(); + + return work.texture; +} + + + + |