summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2010-12-08 10:57:28 +0100
committerGunnar Sletta <gunnar.sletta@nokia.com>2010-12-08 10:57:28 +0100
commit39d7613a229600e74604e429fa5c607930f6790c (patch)
tree0094e8565fbe6e441e8eb03707eb01a69028e1c5
parent56bf92c816687942670cfd599b76f00705392d2e (diff)
More work on async uploads
If textures are deleted while pending upload, remove them from the queue. If no timers are running, upload regularily using a timer
-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;