Support requestPixmap if platform has ThreadedPixmaps feature
authorAlbert Astals Cid <albert.astals@canonical.com>
Fri, 23 Nov 2012 11:44:16 +0000 (12:44 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 23 Nov 2012 16:13:33 +0000 (17:13 +0100)
As discussed with Samuel enable the use of requestPixmap in a thread
for async requests if the platform support ThreadedPixmaps

Task-number: 28138
Change-Id: I106cf0123430115464b0a75071c7e6129a98d22b
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
src/quick/util/qquickimageprovider.cpp
src/quick/util/qquickpixmapcache.cpp

index 94a753f..3c5610f 100644 (file)
@@ -136,7 +136,7 @@ QImage QQuickTextureFactory::image() const
 
     \list
     \li Loaded using QPixmaps rather than actual image files
-    \li Loaded asynchronously in a separate thread, if imageType() is \l{QQuickImageProvider::ImageType}{ImageType::Image}
+    \li Loaded asynchronously in a separate thread
     \endlist
 
     To specify that an image should be loaded by an image provider, use the
@@ -211,7 +211,7 @@ QImage QQuickTextureFactory::image() const
 
     \section2 Asynchronous image loading
 
-    Image providers that support QImage loading automatically include support
+    Image providers that support QImage or Texture loading automatically include support
     for asychronous loading of images. To enable asynchronous loading for an
     image source, set the \c asynchronous property to \c true for the relevant
     \l Image, \l BorderImage or \l AnimatedImage object. When this is enabled, 
@@ -225,11 +225,11 @@ QImage QQuickTextureFactory::image() const
     provider constructor. This ensures that all image requests for the
     provider are handled in a separate thread.
 
-    Asynchronous loading is not supported for image providers that provide
-    QPixmap rather than QImage values, as pixmaps can only be created in the
-    main thread. In this case, if \l {Image::}{asynchronous} is set to 
-    \c true, the value is ignored and the image is loaded
-    synchronously.
+    Asynchronous loading for image providers that provide QPixmap is only supported
+    in platforms that have the ThreadedPixmaps feature, in platforms where
+    pixmaps can only be created in the main thread (i.e. ThreadedPixmaps is not supported)
+    if \l {Image::}{asynchronous} is set to \c true, the value is ignored
+    and the image is loaded synchronously.
 
 
     \section2 Image caching
@@ -328,6 +328,9 @@ QImage QQuickImageProvider::requestImage(const QString &id, QSize *size, const Q
     In all cases, \a size must be set to the original size of the image. This
     is used to set the \l {Item::}{width} and \l {Item::}{height} of the
     relevant \l Image if these values have not been set explicitly.
+
+    \note this method may be called by multiple threads, so ensure the
+    implementation of this method is reentrant.
 */
 QPixmap QQuickImageProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
 {
index 1649e33..3d6a8d0 100644 (file)
@@ -47,6 +47,9 @@
 #include <private/qqmlglobal_p.h>
 #include <private/qqmlengine_p.h>
 
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
 #include <QtQuick/private/qsgtexture_p.h>
 #include <QtQuick/private/qsgcontext_p.h>
 
@@ -539,6 +542,18 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
             if (!cancelled.contains(runningJob))
                 runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image));
             mutex.unlock();
+        } else if (imageType == QQuickImageProvider::Pixmap) {
+            const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
+            QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
+            QString errorStr;
+            if (pixmap.isNull()) {
+                errorCode = QQuickPixmapReply::Loading;
+                errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+            }
+            mutex.lock();
+            if (!cancelled.contains(runningJob))
+                runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(pixmap.toImage()));
+            mutex.unlock();
         } else {
             QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, requestSize);
             QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
@@ -1176,7 +1191,8 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
     if (iter == store->m_cache.end()) {
         if (url.scheme() == QLatin1String("image")) {
             if (QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)))) {
-                if (provider->imageType() == QQuickImageProvider::Pixmap) {
+                const bool threadedPixmaps = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps);
+                if (!threadedPixmaps && provider->imageType() == QQuickImageProvider::Pixmap) {
                     // pixmaps can only be loaded synchronously
                     options &= ~QQuickPixmap::Asynchronous;
                 } else if (provider->flags() & QQuickImageProvider::ForceAsynchronousImageLoading) {