summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2010-12-16 08:27:57 +0100
committerGunnar Sletta <gunnar.sletta@nokia.com>2010-12-16 08:27:57 +0100
commit0c117eb94ebbc39fd6a8d6be25db86f349d05e20 (patch)
tree61c9ead27377f5ca1e634ebbd946d132ec20e71a
parent6bdfa1a7529a9f4dd379b3eca4dec1cb4ce7364d (diff)
some more autotests for texturemanager
-rw-r--r--TODO31
-rw-r--r--src/scenegraph/coreapi/qsgtexturemanager.cpp51
-rw-r--r--src/scenegraph/coreapi/qsgtexturemanager.h2
-rw-r--r--tests/auto/texturemanager/tst_texturemanagertest.cpp69
4 files changed, 150 insertions, 3 deletions
diff --git a/TODO b/TODO
index 6aa4eb2..4814e57 100644
--- a/TODO
+++ b/TODO
@@ -12,7 +12,6 @@
declarative/
canvas/
view
- animation driver
items/
all the qxitems
scenegraph/
@@ -34,6 +33,9 @@
adaptation interfaces
default implementations
qmlrenderer
+ animation driver
+
+
- Make QxImage push normalized source coords into TextureNode so we don't have to renormalize for
every geometry change. It also makes a lot more sense, now that TextureNode doesn't know the
@@ -48,3 +50,30 @@
does a texture memcpy for the first glDrawElements() that uses the texture in the UI thread.
I guess that only leaves PBO uploads, but that won't remedy the problem, I recon...
EDIT: CLIENT_STORAGE + TEXTURE_STORAGE as SHARED + seems to kill ALL performance problems
+
+
+- Scene Graph
+ - Product Finalization:
+ - API Review and proper d-ptr implementations where required
+ - Documentation for all public classes
+ - Autotests for all public classes
+ - NodeInterfaces, Scene Graph structure, QSGContext, Texture classes, Renderer
+ - Solve the texture problem. Convenient base class, asynchronous uploads (threading?), atlasses?
+ - Multimedia, through Qt Mobility or directly to native API's like gstreamer
+ - We have phonon, but it doesn't work for devices
+ - Gstreamer, would work on meego / linux
+ - Lacking solution on symbian
+ - Upgrade to proper QML Items
+ - Examples for most common usecases usecases
+ - Solve the text problem
+ - Investigate mipmapping
+ - Investigate distance field
+ - Investigate curve rendering on gpu
+ - Scalable unhinted text layout
+ - text as geometry over a physical size
+ - Optimal backends for SGX, CTS79 and Mali 400.
+ - Pluggable vsync animation
+ - Wayland based
+ - eglSwapBuffers based
+ - signal based?
+
diff --git a/src/scenegraph/coreapi/qsgtexturemanager.cpp b/src/scenegraph/coreapi/qsgtexturemanager.cpp
index d8c08f8..6b072cc 100644
--- a/src/scenegraph/coreapi/qsgtexturemanager.cpp
+++ b/src/scenegraph/coreapi/qsgtexturemanager.cpp
@@ -120,13 +120,29 @@ public:
int uploadTimer;
QTime lastUpload;
+
+ int maxTextureSize;
};
+/*!
+ The QSGTextureManager class is responsible for converting QImages into texture ids
+ inside the QML scene graph.
+ The QSGTextureManager is created by the QSGContext class after a GL context is
+ available, so the QSGTextureManager and subclasses can safely assume that a
+ GL context is bound and make GL calls.
+ */
QSGTextureManager::QSGTextureManager()
: d(new QSGTextureManagerPrivate)
{
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &d->maxTextureSize);
+}
+
+
+int QSGTextureManager::maxTextureSize() const
+{
+ return d->maxTextureSize;
}
@@ -186,6 +202,9 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
if (texture)
return QSGTextureRef(texture);
+ while (glGetError() != GL_NO_ERROR) {}
+
+
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
@@ -198,6 +217,16 @@ QSGTextureRef QSGTextureManager::upload(const QImage &image)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
#endif
+ // Gracefully fail in case of an error...
+ GLuint error = glGetError();
+ if (error != GL_NO_ERROR) {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &id);
+ if (error != GL_OUT_OF_MEMORY)
+ qWarning("QSGTextureManager::upload failed, OpenGL error code: %x", error);
+ return QSGTextureRef();
+ }
+
texture = new QSGTexture;
texture->setTextureId(id);
texture->setTextureSize(image.size());
@@ -220,7 +249,9 @@ QSGTextureRef QSGTextureManager::requestUpload(const QImage &image,
Q_ASSERT(!image.isNull());
QSGTexture *t = new QSGTexture();
- connect(t, SIGNAL(statusChanged(int)), listener, slot);
+ t->setStatus(QSGTexture::Loading);
+ if (listener && slot)
+ connect(t, SIGNAL(statusChanged(int)), listener, slot);
connect(t, SIGNAL(destroyed(QObject*)), this, SLOT(textureDestroyed(QObject*)));
QSGTextureAsyncUpload work;
@@ -282,14 +313,30 @@ void QSGTextureManager::processAsyncTextures()
// Create or bind the texture...
if (upload.texture->textureId() == 0) {
+ while (glGetError() != GL_NO_ERROR) {}
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ // Clean up
+ // Gracefully fail in case of an error...
+ GLuint error = glGetError();
+ if (error != GL_NO_ERROR) {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &id);
+ if (error != GL_OUT_OF_MEMORY) {
+ qWarning("QSGTextureManager::async upload failed, OpenGL error code: %x", error);
+ t->setStatus(QSGTexture::Error);
+ } else {
+ t->setStatus(QSGTexture::Null);
+ }
+ return;
+ }
+
t->setTextureId(id);
t->setTextureSize(QSize(w, h));
t->setAlphaChannel(upload.image.hasAlphaChannel());
- t->setStatus(QSGTexture::Loading);
// printf("ASYNC: created texture %p with id=%d\n", t, id);
} else {
glBindTexture(GL_TEXTURE_2D, t->textureId());
diff --git a/src/scenegraph/coreapi/qsgtexturemanager.h b/src/scenegraph/coreapi/qsgtexturemanager.h
index 6eb25ad..2b065f3 100644
--- a/src/scenegraph/coreapi/qsgtexturemanager.h
+++ b/src/scenegraph/coreapi/qsgtexturemanager.h
@@ -177,6 +177,8 @@ public:
static void swizzleBGRAToRGBA(QImage *image);
+ int maxTextureSize() const;
+
protected:
void timerEvent(QTimerEvent *);
diff --git a/tests/auto/texturemanager/tst_texturemanagertest.cpp b/tests/auto/texturemanager/tst_texturemanagertest.cpp
index 853d527..3ddda9e 100644
--- a/tests/auto/texturemanager/tst_texturemanagertest.cpp
+++ b/tests/auto/texturemanager/tst_texturemanagertest.cpp
@@ -19,6 +19,13 @@ private Q_SLOTS:
void upload();
void uploadSameImageTwice();
+ void requestUpload();
+
+ void gracefullyRunOutOfMemory();
+ void gracefullyFailOnTooLarge();
+
+ void maxTextureSize();
+
private:
QSGContext *context;
QGLWidget *glWidget;
@@ -80,10 +87,72 @@ void TextureManagerTest::uploadSameImageTwice()
QImage shallowCopy = image;
QSGTextureRef t2 = tm->upload(shallowCopy);
QCOMPARE(t.texture(), t2.texture());
+}
+
+
+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) {
+ QTest::qWait(50);
+ QApplication::processEvents();
+ }
+
+ QVERIFY(t->status() == QSGTexture::Ready);
+ QVERIFY(t->textureId() > 0);
+ QVERIFY(t->textureSize().width() >= image.width());
+ QVERIFY(t->textureSize().height() >= image.height());
}
+/*!
+ 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
+ */
+void TextureManagerTest::gracefullyRunOutOfMemory()
+{
+ QImage image(512, 512, QImage::Format_ARGB32_Premultiplied);
+ QList<QSGTextureRef> refs;
+
+ int i = 128;
+ while (--i) {
+ QSGTextureRef t = tm->upload(image);
+ refs << t;
+ if (t.isNull())
+ break;
+ }
+
+ QVERIFY(true);
+}
+
+
+void TextureManagerTest::gracefullyFailOnTooLarge()
+{
+ QImage image(32000, 2, QImage::Format_ARGB32_Premultiplied);
+ QSGTextureRef t = tm->upload(image);
+ QVERIFY(t.isNull());
+}
+
+
+void TextureManagerTest::maxTextureSize()
+{
+ int size = tm->maxTextureSize();
+
+ if (size < 1024) {
+ qWarning("Texture limit is only %d", size);
+ }
+
+ // 64 is the lowest allowed by the spec...
+ // Any lower number would indicate an error
+ QVERIFY(size >=64); }
+
+
QTEST_MAIN(TextureManagerTest);
#include "tst_texturemanagertest.moc"