summaryrefslogtreecommitdiffstats
path: root/src/adaptationlayers/threadedtexturemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/adaptationlayers/threadedtexturemanager.cpp')
-rw-r--r--src/adaptationlayers/threadedtexturemanager.cpp124
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;
+}
+
+
+
+