summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/scenegraph/coreapi/qsgtexturemanager.cpp59
-rw-r--r--src/scenegraph/coreapi/qsgtexturemanager.h4
2 files changed, 58 insertions, 5 deletions
diff --git a/src/scenegraph/coreapi/qsgtexturemanager.cpp b/src/scenegraph/coreapi/qsgtexturemanager.cpp
index 5e468a0..218c1ea 100644
--- a/src/scenegraph/coreapi/qsgtexturemanager.cpp
+++ b/src/scenegraph/coreapi/qsgtexturemanager.cpp
@@ -103,6 +103,7 @@ public:
: context(0)
, maxUploadTime(5)
, uploadChunkSize(64)
+ , uploadTimer(0)
{
}
@@ -112,6 +113,9 @@ public:
QQueue<QSGTextureAsyncUpload> asyncUploads;
int maxUploadTime;
int uploadChunkSize;
+
+ int uploadTimer;
+ QTime lastUpload;
};
@@ -136,6 +140,17 @@ QSGContext *QSGTextureManager::context() const
}
+void QSGTextureManager::textureDestroyed(QObject *destroyed)
+{
+ for (int i=0; i<d->asyncUploads.size(); ++i) {
+ if (destroyed == d->asyncUploads[i].texture) {
+ d->asyncUploads.removeAt(i);
+ break;
+ }
+ }
+}
+
+
void QSGTextureManager::swizzleBGRAToRGBA(QImage *image)
{
const int width = image->width();
@@ -174,6 +189,8 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
texture->setAlphaChannel(image.hasAlphaChannel());
texture->setStatus(QSGTexture::Ready);
+ connect(texture, SIGNAL(destroyed(QObject*)), this, SLOT(textureDestroyed(QObject*)));
+
d->cache.insert(key, texture);
QSGTextureRef ref(texture);
@@ -195,14 +212,38 @@ QSGTextureRef QSGTextureManager::requestUpload(const QImage &image,
d->asyncUploads << work;
+ if (d->uploadTimer == 0) {
+ d->uploadTimer = startTimer(30);
+ }
+
return QSGTextureRef(t);
}
+
+void QSGTextureManager::timerEvent(QTimerEvent *)
+{
+ // ### gunnar:
+ // In the future, I forsee us starting / stopping this timer based
+ // on wether the vsync animation driver is running or not.
+ // Then we can also skip the "time since last upload" logic which
+ // is currently kinda messy and unpredictable.
+ if (d->lastUpload.elapsed() > 50) {
+ // Its been a while since the last frame tick, so we are pausing...
+ // Upload a "big" chunk...
+ int old = d->maxUploadTime;
+ d->maxUploadTime = 50;
+ processAsyncTextures();
+ d->maxUploadTime = old;
+ }
+}
+
void QSGTextureManager::processAsyncTextures()
{
QTime time;
time.start();
+ d->lastUpload.restart();
+
while (!d->asyncUploads.isEmpty()) {
QSGTextureAsyncUpload &upload = d->asyncUploads.first();
@@ -215,11 +256,11 @@ void QSGTextureManager::processAsyncTextures()
int chunkCount = hChunkCount * vChunkCount;
QSGTexture *t = upload.texture;
-// printf("ASYNC: texture: %p, id=%d, size=(%dx%d), progress: %d / %d\n",
+// printf("\nASYNC: texture: %p, id=%d, size=(%dx%d), progress: %d / %d (%dx%d)\n",
// t,
// t->textureId(),
// w, h,
-// upload.progress, chunkCount);
+// upload.progress, chunkCount, hChunkCount, vChunkCount);
// Create or bind the texture...
if (upload.texture->textureId() == 0) {
@@ -239,25 +280,33 @@ void QSGTextureManager::processAsyncTextures()
if (time.elapsed() > d->maxUploadTime)
return;
+ int steps = 0;
+
while (upload.progress < chunkCount && time.elapsed() < d->maxUploadTime) {
int x = (upload.progress % hChunkCount) * d->uploadChunkSize;
int y = (upload.progress / hChunkCount) * d->uploadChunkSize;
- QImage subImage = upload.image.copy(x, y, d->uploadChunkSize, d->uploadChunkSize);
+ QRect area = QRect(x, y, d->uploadChunkSize, d->uploadChunkSize) & upload.image.rect();
+
+ QImage subImage = upload.image.copy(area);
// printf("ASYNC: - doing another batch: %d (x=%d, y=%d, w=%d, h=%d\n",
// upload.progress,
// x, y, subImage.width(), subImage.height());
swizzleBGRAToRGBA(&subImage);
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, d->uploadChunkSize, d->uploadChunkSize, GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, subImage.width(), subImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
++upload.progress;
}
if (upload.progress == chunkCount) {
t->setStatus(QSGTexture::Ready);
+ disconnect(t, SIGNAL(destroyed(QObject*)), this, SLOT(textureDestroyed(QObject*)));
d->asyncUploads.dequeue();
+ if (d->asyncUploads.size() == 0) {
+ killTimer(d->uploadTimer);
+ d->uploadTimer = 0;
+ }
}
}
diff --git a/src/scenegraph/coreapi/qsgtexturemanager.h b/src/scenegraph/coreapi/qsgtexturemanager.h
index 46979a2..0bc08aa 100644
--- a/src/scenegraph/coreapi/qsgtexturemanager.h
+++ b/src/scenegraph/coreapi/qsgtexturemanager.h
@@ -175,8 +175,12 @@ public:
static void swizzleBGRAToRGBA(QImage *image);
+protected:
+ void timerEvent(QTimerEvent *);
+
private slots:
void processAsyncTextures();
+ void textureDestroyed(QObject *texture);
private:
QSGTextureManagerPrivate *d;