aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2012-01-09 08:43:34 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-13 09:27:22 +0100
commitc3b4d679684434d318c75474f426d5c61a4b239c (patch)
tree4f512ff74a2ab1fa957db2a123c447156a83df69
parentc194b012182c3ae495bb7a740f02a5a9f5b3c3b3 (diff)
Reintroduce plugin support for asynchronous hardware specific textures
Change-Id: Iad36542d2137e7a6470009c308ece3de389907c1 Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp41
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h7
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp109
-rw-r--r--src/quick/scenegraph/qsgcontextplugin_p.h6
-rw-r--r--src/quick/util/qdeclarativepixmapcache.cpp27
5 files changed, 110 insertions, 80 deletions
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 5af7c76b16..cad2cb09c8 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -300,47 +300,6 @@ QSGRenderer *QSGContext::createRenderer()
-/*!
- Return true if the image provider supports direct decoding of images,
- straight into textures without going through a QImage first.
-
- If the implementation returns true from this function, the decodeImageToTexture() function
- will be called to read data from a QIODevice, rather than QML decoding
- the image using QImageReader and passing the result to setImage().
-
- \warning This function will be called from outside the GUI and rendering threads
- and must not make use of OpenGL.
- */
-
-bool QSGContext::canDecodeImageToTexture() const
-{
- return false;
-}
-
-
-
-/*!
- Decode the data in \a dev directly to a texture provider of \a requestSize size.
- The size of the decoded data should be written to \a impsize.
-
- If the implementation fails to decode the image data, it should return 0. The
- image data will then be decoded normally.
-
- \warning This function will be called from outside the GUI and renderer threads
- and must not make use of GL calls.
- */
-
-QSGTexture *QSGContext::decodeImageToTexture(QIODevice *dev,
- QSize *size,
- const QSize &requestSize)
-{
- Q_UNUSED(dev);
- Q_UNUSED(size);
- Q_UNUSED(requestSize);
- return 0;
-}
-
-
QSurfaceFormat QSGContext::defaultSurfaceFormat() const
{
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 0d69a4fb47..5e9aadec35 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -102,11 +102,6 @@ public:
virtual QSGGlyphNode *createGlyphNode();
virtual QSGRenderer *createRenderer();
- virtual bool canDecodeImageToTexture() const;
- virtual QSGTexture *decodeImageToTexture(QIODevice *dev,
- QSize *size,
- const QSize &requestSize);
-
virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
virtual QSize minimumFBOSize() const;
@@ -127,6 +122,8 @@ public:
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
+ static QDeclarativeTextureFactory *createTextureFactoryFromImage(const QImage &image);
+
public slots:
void textureFactoryDestroyed(QObject *o);
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
index a07793f44f..6bf6ac90e7 100644
--- a/src/quick/scenegraph/qsgcontextplugin.cpp
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -61,44 +61,97 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
(QSGContextFactoryInterface_iid, QLatin1String("/scenegraph")))
#endif
-/*!
- \fn QSGContext *QSGContext::createDefaultContext()
+struct QSGAdaptionPluginData
+{
+ QSGAdaptionPluginData()
+ : tried(false)
+ , factory(0)
+ {
+ }
- Creates a default scene graph context for the current hardware.
- This may load a device-specific plugin.
-*/
-QSGContext *QSGContext::createDefaultContext()
+ ~QSGAdaptionPluginData()
+ {
+ delete factory;
+ }
+
+ bool tried;
+ QSGContextFactoryInterface *factory;
+ QString deviceName;
+};
+
+QThreadStorage<QSGAdaptionPluginData> qsg_plugin_data;
+
+
+QSGAdaptionPluginData *contextFactory()
{
- const QStringList args = QGuiApplication::arguments();
- QString device;
- for (int index = 0; index < args.count(); ++index) {
- if (args.at(index).startsWith(QLatin1String("--device="))) {
- device = args.at(index).mid(9);
- break;
+ QSGAdaptionPluginData &plugin = qsg_plugin_data.localData();
+ if (!plugin.tried) {
+ plugin.tried = true;
+ const QStringList args = QGuiApplication::arguments();
+ QString device;
+ for (int index = 0; index < args.count(); ++index) {
+ if (args.at(index).startsWith(QLatin1String("--device="))) {
+ device = args.at(index).mid(9);
+ break;
+ }
}
- }
- if (device.isEmpty())
- device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
- if (device.isEmpty())
- return new QSGContext();
+ if (device.isEmpty())
+ device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
- if (QSGContextFactoryInterface *factory
- = qobject_cast<QSGContextFactoryInterface*>
- (loader()->instance(device))) {
- QSGContext *context = factory->create(device);
- if (context)
- return context;
- }
+ if (!device.isEmpty()) {
+ plugin.factory = qobject_cast<QSGContextFactoryInterface*>(loader()->instance(device));
+ plugin.deviceName = device;
+ }
#ifndef QT_NO_DEBUG
- qWarning("Could not create scene graph context for device '%s'"
- " - check that plugins are installed correctly in %s",
- qPrintable(device),
- qPrintable(QLibraryInfo::location(QLibraryInfo::PluginsPath)));
+ if (!device.isEmpty()) {
+ qWarning("Could not create scene graph context for device '%s'"
+ " - check that plugins are installed correctly in %s",
+ qPrintable(device),
+ qPrintable(QLibraryInfo::location(QLibraryInfo::PluginsPath)));
+ }
#endif
+
#endif // QT_NO_LIBRARY || QT_NO_SETTINGS
+ }
+ return &plugin;
+}
+
+
+/*!
+ \fn QSGContext *QSGContext::createDefaultContext()
+
+ Creates a default scene graph context for the current hardware.
+ This may load a device-specific plugin.
+*/
+QSGContext *QSGContext::createDefaultContext()
+{
+ QSGAdaptionPluginData *plugin = contextFactory();
+ if (plugin->factory)
+ return plugin->factory->create(plugin->deviceName);
return new QSGContext();
}
+
+
+/*!
+ \fn QDeclarativeTextureFactory *createTextureFactoryFromImage(const QImage &image)
+
+ Calls into the scene graph adaptation if available and creates a texture
+ factory. The primary purpose of this function is to reimplement hardware
+ specific asynchronous texture frameskip-less uploads that can happen on
+ the image providers thread.
+ */
+
+QDeclarativeTextureFactory *QSGContext::createTextureFactoryFromImage(const QImage &image)
+{
+ QSGAdaptionPluginData *plugin = contextFactory();
+ if (plugin->factory)
+ return plugin->factory->createTextureFactoryFromImage(image);
+ return 0;
+}
+
+
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontextplugin_p.h b/src/quick/scenegraph/qsgcontextplugin_p.h
index a480ee51eb..21924c90ac 100644
--- a/src/quick/scenegraph/qsgcontextplugin_p.h
+++ b/src/quick/scenegraph/qsgcontextplugin_p.h
@@ -46,6 +46,8 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
+#include <QDeclarativeImageProvider>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -55,6 +57,8 @@ class QSGContext;
struct Q_QUICK_EXPORT QSGContextFactoryInterface : public QFactoryInterface
{
virtual QSGContext *create(const QString &key) const = 0;
+
+ virtual QDeclarativeTextureFactory *createTextureFactoryFromImage(const QImage &image) = 0;
};
#define QSGContextFactoryInterface_iid \
@@ -71,6 +75,8 @@ public:
virtual QStringList keys() const = 0;
virtual QSGContext *create(const QString &key) const = 0;
+
+ virtual QDeclarativeTextureFactory *createTextureFactoryFromImage(const QImage &image) { return 0; }
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qdeclarativepixmapcache.cpp b/src/quick/util/qdeclarativepixmapcache.cpp
index 006d720a6e..cb29ec649b 100644
--- a/src/quick/util/qdeclarativepixmapcache.cpp
+++ b/src/quick/util/qdeclarativepixmapcache.cpp
@@ -48,6 +48,7 @@
#include <private/qdeclarativeengine_p.h>
#include <QtQuick/private/qsgtexture_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
#include <QCoreApplication>
#include <QImageReader>
@@ -64,7 +65,6 @@
#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
#include <QSslError>
-#include <QOpenGLContext>
#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
@@ -430,7 +430,11 @@ void QDeclarativePixmapReader::networkRequestDone(QNetworkReply *reply)
// send completion event to the QDeclarativePixmapReply
mutex.lock();
if (!cancelled.contains(job)) {
- job->postReply(error, errorString, readSize, image);
+ QDeclarativeTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
+ if (factory)
+ job->postReply(error, errorString, readSize, factory, image);
+ else
+ job->postReply(error, errorString, readSize, image);
}
mutex.unlock();
}
@@ -529,8 +533,14 @@ void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, c
errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString());
}
mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, image);
+ if (!cancelled.contains(runningJob)) {
+ QDeclarativeTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
+ if (factory)
+ runningJob->postReply(errorCode, errorStr, readSize, factory, image);
+ else
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ }
+
mutex.unlock();
} else {
QDeclarativeTextureFactory *t = ep->getTextureFromProvider(url, &readSize, requestSize);
@@ -564,8 +574,13 @@ void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, c
errorCode = QDeclarativePixmapReply::Loading;
}
mutex.lock();
- if (!cancelled.contains(runningJob))
- runningJob->postReply(errorCode, errorStr, readSize, image);
+ if (!cancelled.contains(runningJob)) {
+ QDeclarativeTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
+ if (factory)
+ runningJob->postReply(errorCode, errorStr, readSize, factory, image);
+ else
+ runningJob->postReply(errorCode, errorStr, readSize, image);
+ }
mutex.unlock();
} else {
// Network resource