summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2010-12-04 10:11:16 +0100
committerGunnar Sletta <gunnar.sletta@nokia.com>2010-12-04 10:11:16 +0100
commitba9d5b8be115adedae5d321ccb40fa84120512ab (patch)
tree36359faff34612bf50c98c918d593af93efb72ea
parent5c7678f9b69d2c0275de37618bb03b9fd398b504 (diff)
Added a Mac Texture Manager which is just awesome!
-rw-r--r--TODO7
-rw-r--r--src/adaptationlayers/adaptationlayers.pri9
-rw-r--r--src/adaptationlayers/mactexturemanager.cpp47
-rw-r--r--src/adaptationlayers/mactexturemanager.h14
-rw-r--r--src/adaptationlayers/threadedtexturemanager.cpp2
-rw-r--r--src/graphicsitems/qximagebase.cpp4
-rw-r--r--src/scenegraph/coreapi/qsgcontext.cpp8
-rw-r--r--src/scenegraph/coreapi/renderer.cpp5
-rw-r--r--tests/image-asynchronous.qml2
9 files changed, 93 insertions, 5 deletions
diff --git a/TODO b/TODO
index ffad6cd..6aa4eb2 100644
--- a/TODO
+++ b/TODO
@@ -41,3 +41,10 @@
- Fix any reference to "// ### gunnar: port properly". Some of these will be pointless to port
as the upgrade to new QML items is pretty close, so we'll have to evaluate those individually..
+
+- Threaded texture uploads on Mac OS X seems pretty pointless. No matter what I try it seems
+ like I get a hit of 25 ms in the main thread even though shark tells me that a lot of effort
+ has been spent in the background thread too. From the shark traces it looks like the driver
+ 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
diff --git a/src/adaptationlayers/adaptationlayers.pri b/src/adaptationlayers/adaptationlayers.pri
index 514e32d..bbba835 100644
--- a/src/adaptationlayers/adaptationlayers.pri
+++ b/src/adaptationlayers/adaptationlayers.pri
@@ -6,7 +6,7 @@ HEADERS += \
$$PWD/default/default_rectanglenode.h \
$$PWD/default/default_glyphnode.h \
$$PWD/default/default_glyphnode_p.h \
- $$PWD/adaptationlayers/threadedtexturemanager.h
+ $$PWD/threadedtexturemanager.h \
SOURCES += \
$$PWD/adaptationlayer.cpp \
@@ -14,4 +14,9 @@ SOURCES += \
$$PWD/default/default_rectanglenode.cpp \
$$PWD/default/default_glyphnode.cpp \
$$PWD/default/default_glyphnode_p.cpp \
- $$PWD/threadedtexturemanager.cpp
+ $$PWD/threadedtexturemanager.cpp \
+
+macx:{
+ SOURCES += adaptationlayers/mactexturemanager.cpp
+ HEADERS += adaptationlayers/mactexturemanager.h
+}
diff --git a/src/adaptationlayers/mactexturemanager.cpp b/src/adaptationlayers/mactexturemanager.cpp
new file mode 100644
index 0000000..dec66c6
--- /dev/null
+++ b/src/adaptationlayers/mactexturemanager.cpp
@@ -0,0 +1,47 @@
+#include "mactexturemanager.h"
+
+/*!
+ Since we are using client storage which means asynchronous DMA
+ uploads, we need to keep the bits around for the duration
+ of the texture id. So we keep the image in along in the reference
+ */
+class QSGMacTextureReference : public TextureReference
+{
+public:
+ QImage image;
+};
+
+
+QSGMacTextureManager::QSGMacTextureManager()
+{
+}
+
+
+const TextureReference *QSGMacTextureManager::requestUploadedTexture(const QImage &image, UploadHints hints, QObject *listener, const char *slot)
+{
+ // Client storage will most likely fail when mipmapping is used..
+ if (hints & TextureManager::GenerateMipmapUploadHint)
+ return TextureManager::requestUploadedTexture(image, hints, listener, slot);
+
+ GLuint id;
+ glGenTextures(1, &id);
+ glBindTexture(GL_TEXTURE_2D, id);
+
+ glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV, image.constBits());
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ QSGMacTextureReference *texture = new QSGMacTextureReference;
+ texture->image = image;
+ texture->setTextureId(id);
+ texture->setTextureSize(image.size());
+ texture->setStatus(TextureReference::Uploaded);
+
+ return texture;
+}
diff --git a/src/adaptationlayers/mactexturemanager.h b/src/adaptationlayers/mactexturemanager.h
new file mode 100644
index 0000000..89cba85
--- /dev/null
+++ b/src/adaptationlayers/mactexturemanager.h
@@ -0,0 +1,14 @@
+#ifndef MACTEXTUREMANAGER_H
+#define MACTEXTUREMANAGER_H
+
+#include "adaptationlayer.h"
+
+class QT_SCENEGRAPH_EXPORT QSGMacTextureManager : public TextureManager
+{
+public:
+ QSGMacTextureManager();
+
+ const TextureReference *requestUploadedTexture(const QImage &image, UploadHints hints, QObject *listener, const char *slot);
+};
+
+#endif // MACTEXTUREMANAGER_H
diff --git a/src/adaptationlayers/threadedtexturemanager.cpp b/src/adaptationlayers/threadedtexturemanager.cpp
index 2522733..4df4d6c 100644
--- a/src/adaptationlayers/threadedtexturemanager.cpp
+++ b/src/adaptationlayers/threadedtexturemanager.cpp
@@ -8,6 +8,7 @@
#include <QPaintDevice>
#include <QGLWidget>
+#include <qdatetime.h>
struct TextureToUpload
{
@@ -114,6 +115,7 @@ const TextureReference *QSGThreadedTextureManager::requestUploadedTexture(const
QObject::connect(work.texture, SIGNAL(statusChanged(int)), listener, slot);
d->thread.mutex.lock();
+
d->thread.requests << work;
d->thread.condition.wakeOne();
d->thread.mutex.unlock();
diff --git a/src/graphicsitems/qximagebase.cpp b/src/graphicsitems/qximagebase.cpp
index 8bbae28..e826f5c 100644
--- a/src/graphicsitems/qximagebase.cpp
+++ b/src/graphicsitems/qximagebase.cpp
@@ -203,8 +203,10 @@ void QxImageBase::requestFinished()
0,
this,
SLOT(textureStatusChanged(int)));
- if (d->texture->status() == TextureReference::Uploaded)
+
+ if (d->texture->status() == TextureReference::Uploaded) {
pixmapChange();
+ }
} else {
d->texture = tm->requestUploadedTexture(d->pix.pixmap().toImage(), TextureManager::SynchronousUploadHint);
pixmapChange();
diff --git a/src/scenegraph/coreapi/qsgcontext.cpp b/src/scenegraph/coreapi/qsgcontext.cpp
index 68a65bb..05eb477 100644
--- a/src/scenegraph/coreapi/qsgcontext.cpp
+++ b/src/scenegraph/coreapi/qsgcontext.cpp
@@ -8,6 +8,10 @@
#include "default/default_glyphnode.h"
#include "threadedtexturemanager.h"
+#ifdef Q_WS_MAC
+#include "mactexturemanager.h"
+#endif
+
#include <private/qobject_p.h>
class QSGContextPrivate : public QObjectPrivate
@@ -159,7 +163,9 @@ Renderer *QSGContext::createRenderer()
*/
TextureManager *QSGContext::createTextureManager()
{
-#if defined (Q_WS_MAC) || defined (Q_WS_WIN)
+#if defined (Q_WS_MAC)
+ return new QSGMacTextureManager;
+#elif defined (Q_WS_WIN)
return new QSGThreadedTextureManager;
#else
return new TextureManager;
diff --git a/src/scenegraph/coreapi/renderer.cpp b/src/scenegraph/coreapi/renderer.cpp
index b666188..1178b5a 100644
--- a/src/scenegraph/coreapi/renderer.cpp
+++ b/src/scenegraph/coreapi/renderer.cpp
@@ -115,6 +115,9 @@ void Renderer::renderScene(const Bindable &bindable)
if (!m_root_node)
return;
+// QTime time;
+// time.start();
+
preprocess();
bindable.bind();
GeometryDataUploader::bind();
@@ -122,6 +125,8 @@ void Renderer::renderScene(const Bindable &bindable)
render();
GeometryDataUploader::release();
m_changed_emitted = false;
+
+// printf("rendering time: %d\n", time.elapsed());
}
void Renderer::setProjectMatrixToDeviceRect()
diff --git a/tests/image-asynchronous.qml b/tests/image-asynchronous.qml
index 9212d18..d3d58f3 100644
--- a/tests/image-asynchronous.qml
+++ b/tests/image-asynchronous.qml
@@ -18,7 +18,7 @@ Rectangle {
property int state: 0
Behavior on opacity {
- NumberAnimation { duration: 250 }
+ NumberAnimation { duration: 500 }
}