summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2010-12-16 11:08:36 +0100
committerGunnar Sletta <gunnar.sletta@nokia.com>2010-12-16 11:08:36 +0100
commit650821207ae31b7e9a2cc6533a9ec81b9b747046 (patch)
tree5270e47d9480b7f8fcd0da082f6aba7251b2fddc
parent8e41a4285870fc03bcd2df4f9f67f3467482e59d (diff)
Fixed the last issue with caching issue...
-rw-r--r--src/scenegraph/coreapi/qsgtexturemanager.cpp35
-rw-r--r--tests/auto/texturemanager/tst_texturemanagertest.cpp67
2 files changed, 91 insertions, 11 deletions
diff --git a/src/scenegraph/coreapi/qsgtexturemanager.cpp b/src/scenegraph/coreapi/qsgtexturemanager.cpp
index a26d353..11228e5 100644
--- a/src/scenegraph/coreapi/qsgtexturemanager.cpp
+++ b/src/scenegraph/coreapi/qsgtexturemanager.cpp
@@ -197,13 +197,27 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
{
Q_ASSERT(!image.isNull());
+ // Check if the image is already uploaded and cached
QSGTextureCacheKey key = { image.cacheKey() };
QSGTexture *texture = d->cache.value(key);
if (texture)
return QSGTextureRef(texture);
- while (glGetError() != GL_NO_ERROR) {}
+ // Check if the image is already scheduled for asynchronous upload...
+ // If so, kill the partial texture and upload in one go below using a new texture..
+ for (int i=0; i<d->asyncUploads.size(); ++i) {
+ const QSGTextureAsyncUpload &work = d->asyncUploads.at(i);
+ if (work.image.cacheKey() == image.cacheKey()) {
+ texture = work.texture;
+ GLuint tid = texture->textureId();
+ if (tid)
+ glDeleteTextures(1, &tid);
+ d->asyncUploads.removeAt(i);
+ }
+ }
+ // image not already scheduled, upload normally...
+ while (glGetError() != GL_NO_ERROR) {}
GLuint id;
glGenTextures(1, &id);
@@ -227,7 +241,8 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
return QSGTextureRef();
}
- texture = new QSGTexture;
+ if (!texture)
+ texture = new QSGTexture;
texture->setTextureId(id);
texture->setTextureSize(image.size());
texture->setAlphaChannel(image.hasAlphaChannel());
@@ -242,6 +257,12 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
}
+/*!
+ Schedules \a image to be uploaded.
+
+ The function returns a texture reference which is
+
+ */
QSGTextureRef QSGTextureManager::requestUpload(const QImage &image,
const QObject *listener,
const char *slot)
@@ -249,14 +270,12 @@ QSGTextureRef QSGTextureManager::requestUpload(const QImage &image,
Q_ASSERT(!image.isNull());
QSGTexture *t = 0;
-
// Check if the image is already uploaded and thus part of the cache..
QSGTextureCacheKey key = { image.cacheKey() };
t = d->cache.value(key);
if (t)
return QSGTextureRef(t);
-
// Check if the image is already scheduled for asynchronous upload...
for (int i=0; i<d->asyncUploads.size(); ++i) {
const QSGTextureAsyncUpload &work = d->asyncUploads.at(i);
@@ -265,7 +284,7 @@ QSGTextureRef QSGTextureManager::requestUpload(const QImage &image,
}
}
-
+ // Not present in any caches, upload normally...
t = new QSGTexture();
t->setStatus(QSGTexture::Loading);
if (listener && slot)
@@ -310,7 +329,6 @@ void QSGTextureManager::processAsyncTextures()
time.start();
d->lastUpload.restart();
-
while (!d->asyncUploads.isEmpty()) {
QSGTextureAsyncUpload &upload = d->asyncUploads.first();
@@ -343,6 +361,7 @@ void QSGTextureManager::processAsyncTextures()
if (error != GL_NO_ERROR) {
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &id);
+ d->asyncUploads.dequeue();
if (error != GL_OUT_OF_MEMORY) {
qWarning("QSGTextureManager::async upload failed, OpenGL error code: %x", error);
t->setStatus(QSGTexture::Error);
@@ -368,7 +387,6 @@ void QSGTextureManager::processAsyncTextures()
int y = (upload.progress / hChunkCount) * 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,
@@ -382,7 +400,8 @@ void QSGTextureManager::processAsyncTextures()
if (upload.progress == chunkCount) {
t->setStatus(QSGTexture::Ready);
- disconnect(t, SIGNAL(destroyed(QObject*)), this, SLOT(textureDestroyed(QObject*)));
+ QSGTextureCacheKey key = { upload.image.cacheKey() };
+ d->cache.insert(key, t);
d->asyncUploads.dequeue();
if (d->asyncUploads.size() == 0) {
killTimer(d->uploadTimer);
diff --git a/tests/auto/texturemanager/tst_texturemanagertest.cpp b/tests/auto/texturemanager/tst_texturemanagertest.cpp
index 886dfa0..f69a76a 100644
--- a/tests/auto/texturemanager/tst_texturemanagertest.cpp
+++ b/tests/auto/texturemanager/tst_texturemanagertest.cpp
@@ -62,18 +62,27 @@ private Q_SLOTS:
void requestUpload();
void requestUploadSameImageTwice();
+ void requestUploadSameImageTwiceWithDelay();
void requestUploadAfterSyncUpload();
+ void uploadAfterRequestUpload();
void gracefullyRunOutOfMemory();
void gracefullyFailOnTooLarge();
void maxTextureSize();
+public slots:
+ void textureStatusChanged(int newStatus) {
+ status = newStatus;
+ }
+
private:
QSGContext *context;
QGLWidget *glWidget;
QSGTextureManager *tm;
+
+ int status;
};
@@ -134,15 +143,18 @@ void TextureManagerTest::uploadSameImageTwice()
}
+/*!
+ Requests an image to be uploaded and verifies that it actually works
+ */
void TextureManagerTest::requestUpload()
{
QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
QSGTextureRef t = tm->requestUpload(image, 0, 0);
QVERIFY(t->status() == QSGTexture::Ready || t->status() == QSGTexture::Loading);
-
- int maxWait = 1000;
- while (t->status() == QSGTexture::Loading) {
+ QTime time;
+ time.start();
+ while (t->status() == QSGTexture::Loading && time.elapsed() < 1000) {
QTest::qWait(50);
QApplication::processEvents();
}
@@ -155,6 +167,30 @@ void TextureManagerTest::requestUpload()
/*!
+ Requests the same image to be uploaded twice. The second time,
+ the image should be directly available. This is to verify that
+ we are actually caching the uploaded requested images.
+ */
+void TextureManagerTest::requestUploadSameImageTwiceWithDelay()
+{
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ QSGTextureRef t = tm->requestUpload(image, 0, 0);
+ QTime time;
+ time.start();
+ while (t->status() == QSGTexture::Loading && time.elapsed() < 1000) {
+ QTest::qWait(50);
+ QApplication::processEvents();
+ }
+ QVERIFY(t.isReady());
+
+ QSGTextureRef t2 = tm->requestUpload(image, 0, 0);
+ QVERIFY(t.texture() == t2.texture());
+ QVERIFY(t2.isReady());
+}
+
+
+
+/*!
Test that we don't fail horribly when allocating large amounts of
texture memory. Since some drivers page graphics memory out to disk
and thus never run out, cap the test at 128Mb to not run forever
@@ -234,6 +270,31 @@ void TextureManagerTest::requestUploadAfterSyncUpload()
+/*!
+ Verify that a sync upload after an async upload returns
+ a ready texture and that the async texture then also is
+ ready...
+ */
+void TextureManagerTest::uploadAfterRequestUpload()
+{
+ status = QSGTexture::Null;
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+
+ QSGTextureRef async = tm->requestUpload(image, this, SLOT(textureStatusChanged(int)));
+ QSGTextureRef sync = tm->upload(image);
+
+ QVERIFY(sync.isReady());
+ QVERIFY(async.isReady());
+ QCOMPARE(status, int(QSGTexture::Ready));
+
+ QVERIFY(async.texture() == sync.texture());
+}
+
+
+
+
+
QTEST_MAIN(TextureManagerTest);
#include "tst_texturemanagertest.moc"