diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2012-01-09 08:43:34 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-01-13 09:27:22 +0100 |
commit | c3b4d679684434d318c75474f426d5c61a4b239c (patch) | |
tree | 4f512ff74a2ab1fa957db2a123c447156a83df69 /src | |
parent | c194b012182c3ae495bb7a740f02a5a9f5b3c3b3 (diff) |
Reintroduce plugin support for asynchronous hardware specific textures
Change-Id: Iad36542d2137e7a6470009c308ece3de389907c1
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 41 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 7 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontextplugin.cpp | 109 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontextplugin_p.h | 6 | ||||
-rw-r--r-- | src/quick/util/qdeclarativepixmapcache.cpp | 27 |
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 |