aboutsummaryrefslogtreecommitdiffstats
path: root/src/imports
diff options
context:
space:
mode:
authorEirik Aavitsland <eirik.aavitsland@qt.io>2017-01-19 15:11:40 +0100
committerEirik Aavitsland <eirik.aavitsland@qt.io>2017-01-30 12:43:37 +0000
commitf952b68fb1f8553b394791a8315468ae673650bc (patch)
tree02eb42e0dce3173c75868caa3ae3d0c316202906 /src/imports
parent7900e74edd42bdd7ee3ecf78be656dd8d3211607 (diff)
Add shared memory image provider
Adds functionality to save CPU memory when several processes use the same local image files. Example and autotest will be added during stabilization. Task-number: QTBUG-56279 Change-Id: Iabe1e42620c79adca4f61f3901da41d9d5a723df Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/imports')
-rw-r--r--src/imports/imports.pro1
-rw-r--r--src/imports/sharedimage/plugin.cpp134
-rw-r--r--src/imports/sharedimage/qmldir3
-rw-r--r--src/imports/sharedimage/qsharedimageloader.cpp265
-rw-r--r--src/imports/sharedimage/qsharedimageloader_p.h81
-rw-r--r--src/imports/sharedimage/sharedimage.pro17
-rw-r--r--src/imports/sharedimage/sharedimageprovider.cpp156
-rw-r--r--src/imports/sharedimage/sharedimageprovider.h58
8 files changed, 715 insertions, 0 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index c49c05956d..20ade45fc8 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -15,6 +15,7 @@ qtHaveModule(quick) {
layouts \
qtquick2 \
window \
+ sharedimage \
testlib
qtConfig(opengl(es1|es2)?): \
diff --git a/src/imports/sharedimage/plugin.cpp b/src/imports/sharedimage/plugin.cpp
new file mode 100644
index 0000000000..f20edc641c
--- /dev/null
+++ b/src/imports/sharedimage/plugin.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qqmlextensionplugin.h>
+#include <qqmlengine.h>
+#include <sharedimageprovider.h>
+
+
+/*!
+ \qmlmodule QtQuick.SharedImage 1
+ \title Qt Quick Shared Image Provider
+ \ingroup qmlmodules
+ \brief Adds an image provider which utilizes shared CPU memory
+
+ \section2 Summary
+
+ This module provides functionality to save memory in use cases where
+ several Qt Quick applications use the same local image files. It does this
+ by placing the decoded QImage data in shared system memory, making it
+ accessible to all the processes (see QSharedMemory).
+
+ This module only shares CPU memory. It does not provide sharing of GPU
+ memory or textures.
+
+ \section2 Usage
+
+ To use this module, import it like this:
+ \code
+ import QtQuick.SharedImage 1.0
+ \endcode
+
+ The sharing functionality is provided through a QQuickImageProvider. Use
+ the "image:" scheme for the URL source of the image, followed by the
+ identifier \e shared, followed by the image file path. For example:
+
+ \code
+ Image { source: "image://shared/usr/share/wallpapers/mybackground.jpg" }
+ \endcode
+
+ This will look for the file \e /usr/share/wallpapers/mybackground.jpg.
+ The first process that does this will read the image file
+ using normal Qt image loading. The decoded image data will then be placed
+ in shared memory, using the full file path as key. Later processes
+ requesting the same image will discover that the data is already available
+ in shared memory. They will then use that instead of loading the image file
+ again.
+
+ The shared image data will be kept available until the last process has deleted
+ its last reference to the shared image, at which point it is automatically released.
+
+ If system memory sharing is not available, the shared image provider falls
+ back to normal, unshared image loading.
+
+ The file path must be absolute. To use a relative path, make it absolute
+ using \e Qt.resolvedUrl() and replace the URL scheme. For example:
+
+ \code
+ ...
+ property string imagePrefix: Qt.resolvedUrl("../myimages/").replace("file://", "image://shared/")
+ Image { source: imagePrefix + "myimage.png" }
+ \endcode
+
+ The shared image module does not provide any directly usable QML types.
+*/
+
+static void initResources()
+{
+#ifdef QT_STATIC
+ Q_INIT_RESOURCE(qmake_QtQuick_SharedImage);
+#endif
+}
+
+QT_BEGIN_NAMESPACE
+
+class QtQuickSharedImagePlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QtQuickSharedImagePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+
+ void registerTypes(const char *uri) Q_DECL_OVERRIDE
+ {
+ Q_ASSERT(uri == QStringLiteral("QtQuick.SharedImage"));
+ // Need to register *something* to let our version number be known:
+ qmlRegisterTypeNotAvailable(uri, 1, 0, "nosuchtype", QStringLiteral("Just a dummy type, do not use"));
+ }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri) override
+ {
+ Q_UNUSED(uri);
+ engine->addImageProvider("shared", new SharedImageProvider);
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/sharedimage/qmldir b/src/imports/sharedimage/qmldir
new file mode 100644
index 0000000000..64a5aa8ac1
--- /dev/null
+++ b/src/imports/sharedimage/qmldir
@@ -0,0 +1,3 @@
+module QtQuick.SharedImage
+plugin sharedimageplugin
+classname QtQuickSharedImagePlugin
diff --git a/src/imports/sharedimage/qsharedimageloader.cpp b/src/imports/sharedimage/qsharedimageloader.cpp
new file mode 100644
index 0000000000..65cbd92bb4
--- /dev/null
+++ b/src/imports/sharedimage/qsharedimageloader.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedimageloader_p.h"
+#include <private/qobject_p.h>
+#include <private/qimage_p.h>
+#include <QSharedMemory>
+
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcSharedImage, "qt.quick.sharedimage");
+
+struct SharedImageHeader {
+ quint8 magic;
+ quint8 version;
+ quint16 offset;
+ qint32 width;
+ qint32 height;
+ qint32 bpl;
+ QImage::Format format;
+};
+Q_STATIC_ASSERT(sizeof(SharedImageHeader) % 4 == 0);
+
+#ifndef QT_NO_SHAREDMEMORY
+struct SharedImageInfo {
+ QString path;
+ QPointer<QSharedMemory> shmp;
+};
+
+void cleanupSharedImage(void *cleanupInfo)
+{
+ if (!cleanupInfo)
+ return;
+ SharedImageInfo *sii = static_cast<SharedImageInfo *>(cleanupInfo);
+ qCDebug(lcSharedImage) << "Cleanup called for" << sii->path;
+ if (sii->shmp.isNull()) {
+ qCDebug(lcSharedImage) << "shm is 0 for" << sii->path;
+ return;
+ }
+ QSharedMemory *shm = sii->shmp.data();
+ sii->shmp.clear();
+ delete shm; // destructor detaches
+ delete sii;
+}
+#else
+void cleanupSharedImage(void *) {}
+#endif
+
+class QSharedImageLoaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSharedImageLoader)
+
+public:
+ QSharedImageLoaderPrivate()
+ : QObjectPrivate()
+ {}
+
+ QImage load(const QString &path, QSharedImageLoader::ImageParameters *params);
+
+ void storeImageToMem(void *data, const QImage &img);
+
+ bool verifyMem(const void *data, int size);
+
+ QImage createImageFromMem(const void *data, void *cleanupInfo);
+
+};
+
+
+void QSharedImageLoaderPrivate::storeImageToMem(void *data, const QImage &img)
+{
+ Q_ASSERT(data && !img.isNull());
+
+ SharedImageHeader *h = static_cast<SharedImageHeader *>(data);
+ h->magic = 'Q';
+ h->version = 1;
+ h->offset = sizeof(SharedImageHeader);
+ h->width = img.width();
+ h->height = img.height();
+ h->bpl = img.bytesPerLine();
+ h->format = img.format();
+
+ uchar *p = static_cast<uchar *>(data) + sizeof(SharedImageHeader);
+ memcpy(p, img.constBits(), img.byteCount());
+}
+
+
+bool QSharedImageLoaderPrivate::verifyMem(const void *data, int size)
+{
+ if (!data || size < int(sizeof(SharedImageHeader)))
+ return false;
+
+ const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
+ if ((h->magic != 'Q')
+ || (h->version < 1)
+ || (h->offset < sizeof(SharedImageHeader))
+ || (h->width <= 0)
+ || (h->height <= 0)
+ || (h->bpl <= 0)
+ || (h->format <= QImage::Format_Invalid)
+ || (h->format >= QImage::NImageFormats)) {
+ return false;
+ }
+
+ int availSize = size - h->offset;
+ if (h->height * h->bpl > availSize)
+ return false;
+ if ((qt_depthForFormat(h->format) * h->width * h->height) > (8 * availSize))
+ return false;
+
+ return true;
+}
+
+
+QImage QSharedImageLoaderPrivate::createImageFromMem(const void *data, void *cleanupInfo)
+{
+ const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
+ const uchar *p = static_cast<const uchar *>(data) + h->offset;
+
+ QImage img(p, h->width, h->height, h->bpl, h->format, cleanupSharedImage, cleanupInfo);
+ return img;
+}
+
+
+QImage QSharedImageLoaderPrivate::load(const QString &path, QSharedImageLoader::ImageParameters *params)
+{
+#ifndef QT_NO_SHAREDMEMORY
+ Q_Q(QSharedImageLoader);
+
+ QImage nil;
+ if (path.isEmpty())
+ return nil;
+
+ QScopedPointer<QSharedMemory> shm(new QSharedMemory(q->key(path, params)));
+ bool locked = false;
+
+ if (!shm->attach(QSharedMemory::ReadOnly)) {
+ QImage img = q->loadFile(path, params);
+ if (img.isNull())
+ return nil;
+ int size = sizeof(SharedImageHeader) + img.byteCount();
+ if (shm->create(size)) {
+ qCDebug(lcSharedImage) << "Created new shm segment of size" << size << "for image" << path;
+ if (!shm->lock()) {
+ qCDebug(lcSharedImage) << "Lock1 failed!?" << shm->errorString();
+ return nil;
+ }
+ locked = true;
+ storeImageToMem(shm->data(), img);
+ } else if (shm->error() == QSharedMemory::AlreadyExists) {
+ // race handling: other process may have created the share while
+ // we loaded the image, so try again to just attach
+ if (!shm->attach(QSharedMemory::ReadOnly)) {
+ qCDebug(lcSharedImage) << "Attach to existing failed?" << shm->errorString();
+ return nil;
+ }
+ } else {
+ qCDebug(lcSharedImage) << "Create failed?" << shm->errorString();
+ return nil;
+ }
+ }
+
+ Q_ASSERT(shm->isAttached());
+
+ if (!locked) {
+ if (!shm->lock()) {
+ qCDebug(lcSharedImage) << "Lock2 failed!?" << shm->errorString();
+ return nil;
+ }
+ locked = true;
+ }
+
+ if (!verifyMem(shm->constData(), shm->size())) {
+ qCDebug(lcSharedImage) << "Verifymem failed!?";
+ shm->unlock();
+ return nil;
+ }
+
+ QSharedMemory *shmp = shm.take();
+ SharedImageInfo *sii = new SharedImageInfo;
+ sii->path = path;
+ sii->shmp = shmp;
+ QImage shImg = createImageFromMem(shmp->constData(), sii);
+
+ if (!shmp->unlock()) {
+ qCDebug(lcSharedImage) << "UnLock failed!?";
+ }
+
+ return shImg;
+#else
+ Q_UNUSED(path);
+ Q_UNUSED(params);
+ return QImage();
+#endif
+}
+
+
+QSharedImageLoader::QSharedImageLoader(QObject *parent)
+ : QObject(*new QSharedImageLoaderPrivate, parent)
+{
+}
+
+QSharedImageLoader::~QSharedImageLoader()
+{
+}
+
+QImage QSharedImageLoader::load(const QString &path, ImageParameters *params)
+{
+ Q_D(QSharedImageLoader);
+
+ return d->load(path, params);
+}
+
+QImage QSharedImageLoader::loadFile(const QString &path, ImageParameters *params)
+{
+ Q_UNUSED(params);
+
+ return QImage(path);
+}
+
+QString QSharedImageLoader::key(const QString &path, ImageParameters *params)
+{
+ Q_UNUSED(params);
+
+ return path;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/imports/sharedimage/qsharedimageloader_p.h b/src/imports/sharedimage/qsharedimageloader_p.h
new file mode 100644
index 0000000000..afb50e5088
--- /dev/null
+++ b/src/imports/sharedimage/qsharedimageloader_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHAREDIMAGELOADER_H
+#define QSHAREDIMAGELOADER_H
+
+#include <QImage>
+#include <QVariant>
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcSharedImage);
+
+class QSharedImageLoaderPrivate;
+
+class QSharedImageLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSharedImageLoader)
+
+public:
+ enum ImageParameter {
+ OriginalSize = 0,
+ RequestedSize,
+ NumImageParameters
+ };
+ typedef QVector<QVariant> ImageParameters;
+
+ QSharedImageLoader(QObject *parent = Q_NULLPTR);
+ ~QSharedImageLoader();
+
+ QImage load(const QString &path, ImageParameters *params = Q_NULLPTR);
+
+protected:
+ virtual QImage loadFile(const QString &path, ImageParameters *params);
+ virtual QString key(const QString &path, ImageParameters *params);
+
+private:
+ Q_DISABLE_COPY(QSharedImageLoader)
+};
+
+QT_END_NAMESPACE
+
+#endif // QSHAREDIMAGELOADER_H
diff --git a/src/imports/sharedimage/sharedimage.pro b/src/imports/sharedimage/sharedimage.pro
new file mode 100644
index 0000000000..523de66ac1
--- /dev/null
+++ b/src/imports/sharedimage/sharedimage.pro
@@ -0,0 +1,17 @@
+CXX_MODULE = qml
+TARGET = sharedimageplugin
+TARGETPATH = QtQuick/SharedImage
+IMPORT_VERSION = 1.0
+
+QT *= quick qml gui-private core-private
+
+SOURCES += \
+ plugin.cpp \
+ sharedimageprovider.cpp \
+ qsharedimageloader.cpp
+
+HEADERS += \
+ sharedimageprovider.h \
+ qsharedimageloader_p.h
+
+load(qml_plugin)
diff --git a/src/imports/sharedimage/sharedimageprovider.cpp b/src/imports/sharedimage/sharedimageprovider.cpp
new file mode 100644
index 0000000000..2dd3a130e9
--- /dev/null
+++ b/src/imports/sharedimage/sharedimageprovider.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <sharedimageprovider.h>
+#include <qsharedimageloader_p.h>
+#include <qquickimageprovider.h>
+#include <private/qimage_p.h>
+#include <QImageReader>
+#include <QFileInfo>
+#include <QDir>
+
+class QuickSharedImageLoader : public QSharedImageLoader
+{
+ Q_OBJECT
+ friend class SharedImageProvider;
+
+public:
+ QuickSharedImageLoader(QObject *parent = Q_NULLPTR)
+ : QSharedImageLoader(parent)
+ {
+ }
+
+protected:
+ QImage loadFile(const QString &path, ImageParameters *params) override
+ {
+ QImageReader imgio(path);
+ QSize realSize = imgio.size();
+ QSize requestSize = params ? params->value(RequestedSize).toSize() : QSize();
+
+ // Following qquickpixmapcache's readImage, from here...
+ const bool force_scale = imgio.format() == "svg" || imgio.format() == "svgz";
+
+ if (requestSize.width() > 0 || requestSize.height() > 0) {
+ QSize s = realSize;
+ qreal ratio = 0.0;
+ if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
+ ratio = qreal(requestSize.width())/s.width();
+ }
+ if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
+ qreal hr = qreal(requestSize.height())/s.height();
+ if (ratio == 0.0 || hr < ratio)
+ ratio = hr;
+ }
+ if (ratio > 0.0) {
+ s.setHeight(qRound(s.height() * ratio));
+ s.setWidth(qRound(s.width() * ratio));
+ imgio.setScaledSize(s);
+ }
+ }
+ // ... to here
+
+ QImage image;
+ if (imgio.read(&image)) {
+ if (realSize.isEmpty())
+ realSize = image.size();
+ // Make sure we have acceptable format for texture uploader, or it will convert & lose sharing
+ // This mimics the testing & conversion normally done by the quick pixmapcache & texturefactory
+ if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied) {
+ QImage::Format newFmt = QImage::Format_RGB32;
+ if (image.hasAlphaChannel() && image.data_ptr()->checkForAlphaPixels())
+ newFmt = QImage::Format_ARGB32_Premultiplied;
+ qCDebug(lcSharedImage) << "Convert on load from format" << image.format() << "to" << newFmt;
+ image = image.convertToFormat(newFmt);
+ }
+ }
+
+ if (params && params->count() > OriginalSize)
+ params->replace(OriginalSize, realSize);
+
+ return image;
+ }
+
+ QString key(const QString &path, ImageParameters *params) override
+ {
+ QSize reqSz = params->value(RequestedSize).toSize();
+ if (!reqSz.isValid())
+ return path;
+
+ QString key = path + QStringLiteral("_%1x%2").arg(reqSz.width()).arg(reqSz.height());
+ qCDebug(lcSharedImage) << "KEY:" << key;
+ return key;
+ }
+};
+
+
+SharedImageProvider::SharedImageProvider()
+ : QQuickImageProvider(QQuickImageProvider::Image), loader(new QuickSharedImageLoader)
+{
+}
+
+QImage SharedImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
+{
+ QFileInfo fi(QDir::root(), id);
+ QString path = fi.canonicalFilePath();
+ if (path.isEmpty())
+ return QImage();
+
+ QSharedImageLoader::ImageParameters params(QSharedImageLoader::NumImageParameters);
+ params[QSharedImageLoader::RequestedSize].setValue(requestedSize);
+
+ QImage img = loader->load(path, &params);
+ if (img.isNull()) {
+ // May be sharing problem, fall back to normal local load
+ img = loader->loadFile(path, &params);
+ if (!img.isNull())
+ qCWarning(lcSharedImage) << "Sharing problem; loading" << id << "unshared";
+ }
+
+ //... QSize realSize = params.value(QSharedImageLoader::OriginalSize).toSize();
+ // quickpixmapcache's readImage() reports back the original size, prior to requestedSize scaling, in the *size
+ // parameter. That value is currently ignored by quick however, which only cares about the present size of the
+ // returned image. So handling and sharing of info on pre-scaled size is currently not implemented.
+ if (size) {
+ *size = img.size();
+ }
+
+ return img;
+}
+
+#include "sharedimageprovider.moc"
diff --git a/src/imports/sharedimage/sharedimageprovider.h b/src/imports/sharedimage/sharedimageprovider.h
new file mode 100644
index 0000000000..a2f6b6ef2f
--- /dev/null
+++ b/src/imports/sharedimage/sharedimageprovider.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHAREDIMAGEPROVIDER_H
+#define SHAREDIMAGEPROVIDER_H
+
+#include <QQuickImageProvider>
+#include <QScopedPointer>
+
+class QuickSharedImageLoader;
+
+class SharedImageProvider : public QQuickImageProvider
+{
+public:
+ SharedImageProvider();
+
+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
+
+protected:
+ QScopedPointer<QuickSharedImageLoader> loader;
+};
+#endif // SHAREDIMAGEPROVIDER_H