diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2010-12-16 11:08:36 +0100 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@nokia.com> | 2010-12-16 11:08:36 +0100 |
commit | 650821207ae31b7e9a2cc6533a9ec81b9b747046 (patch) | |
tree | 5270e47d9480b7f8fcd0da082f6aba7251b2fddc | |
parent | 8e41a4285870fc03bcd2df4f9f67f3467482e59d (diff) |
Fixed the last issue with caching issue...
-rw-r--r-- | src/scenegraph/coreapi/qsgtexturemanager.cpp | 35 | ||||
-rw-r--r-- | tests/auto/texturemanager/tst_texturemanagertest.cpp | 67 |
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" |