1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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;
}
|