diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2023-08-30 22:05:23 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2023-09-01 15:57:36 +0200 |
commit | 3df72c56e732341aa55fa8e4aff48dbaebc15018 (patch) | |
tree | db71674bc5394c632d1659c7d2bc83d07e288605 /src | |
parent | e1382f6ad7983a1adf082ba5852379a6bf154a83 (diff) |
Export QQuickPixmapKey and (renamed) QQuickPixmapCache for autotests
We need to be able to do a leak check in tst_qquickpixmapcache.
So we also need to use the singleton pattern rather than
Q_GLOBAL_STATIC. Since it gets more exposed this way, make
the badly-encapsulated parts of API available only to friends.
It's always been bothersome that various other places in the code are
including qquickpixmapcache_p.h to get QQuickPixmap, and
qquickpixmapcache_p.h also does not include any class called
QQuickPixmapCache as you'd expect; while arguably, QQuickPixmapStore is
the cache. Often in comments I've needed to refer to "the code in
qquickpixmapcache.cpp" because it's a very private, inbred family of
related classes that don't match the header name. So now we split the
headers: qquickpixmapcache_p.h is for the cache, which is now called
QQuickPixmapCache; and qquickpixmap_p.h is the header most often needed
in other places. Most classes in qquickpixmap_p.h are exported, but
QQuickPixmapCache itself is not (except for autotests). It cannot be
defined in the header that gets included in Particles for example: then
it wouldn't link, because the implementation is not (and shouldn't be)
exported, and that's not what Particles needs anyway.
Task-number: QTBUG-81266
Task-number: QTBUG-114953
Change-Id: Ifd7f253b8bbaa130eb52d5546f342754f99f47bb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
25 files changed, 296 insertions, 252 deletions
diff --git a/src/labs/platform/qquicklabsplatformiconloader_p.h b/src/labs/platform/qquicklabsplatformiconloader_p.h index 20914afe85..0fb406df4f 100644 --- a/src/labs/platform/qquicklabsplatformiconloader_p.h +++ b/src/labs/platform/qquicklabsplatformiconloader_p.h @@ -18,7 +18,7 @@ #include <QtCore/qurl.h> #include <QtCore/qstring.h> #include <QtGui/qicon.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include "qquicklabsplatformicon_p.h" diff --git a/src/labs/sharedimage/qsharedimageprovider.cpp b/src/labs/sharedimage/qsharedimageprovider.cpp index 69f0013b06..33f72447e3 100644 --- a/src/labs/sharedimage/qsharedimageprovider.cpp +++ b/src/labs/sharedimage/qsharedimageprovider.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qsharedimageprovider_p.h> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qimage_p.h> #include <QImageReader> #include <QFileInfo> diff --git a/src/labs/sharedimage/qsharedimageprovider_p.h b/src/labs/sharedimage/qsharedimageprovider_p.h index ee81866072..67d978afa8 100644 --- a/src/labs/sharedimage/qsharedimageprovider_p.h +++ b/src/labs/sharedimage/qsharedimageprovider_p.h @@ -18,7 +18,7 @@ #include "qtlabssharedimageglobal_p.h" #include <QQuickImageProvider> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <QScopedPointer> #include "qsharedimageloader_p.h" diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h index 66cb4c6e53..29d39ea6ac 100644 --- a/src/particles/qquickimageparticle_p.h +++ b/src/particles/qquickimageparticle_p.h @@ -17,7 +17,7 @@ #include "qquickparticlepainter_p.h" #include "qquickdirection_p.h" -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <QQmlListProperty> #include <QtGui/qcolor.h> #include <QtQuick/qsgmaterial.h> diff --git a/src/particles/qquickmaskextruder_p.h b/src/particles/qquickmaskextruder_p.h index 457a768c28..d35f5057a6 100644 --- a/src/particles/qquickmaskextruder_p.h +++ b/src/particles/qquickmaskextruder_p.h @@ -15,7 +15,7 @@ // We mean it. // #include "qquickparticleextruder_p.h" -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <QUrl> #include <QImage> diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp index 84019826e4..f32954ed34 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp @@ -13,7 +13,7 @@ #include <QtQuick/qquickitem.h> #include <QtQml/qqmlcomponent.h> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qquickview_p.h> #include <private/qhighdpiscaling_p.h> diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp index e1e98537da..336395b131 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp @@ -10,7 +10,7 @@ #include <QtQuick/qquickitem.h> #include <QtGui/qguiapplication.h> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qqmldebugconnector_p.h> #include <private/qversionedpacket_p.h> diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index aea9223b7c..c859008fa0 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -187,6 +187,7 @@ qt_internal_add_qml_module(Quick util/qquickforeignutils.cpp util/qquickforeignutils_p.h util/qquickglobal.cpp util/qquickimageprovider.cpp util/qquickimageprovider.h util/qquickimageprovider_p.h + util/qquickpixmap_p.h util/qquickpixmapcache.cpp util/qquickpixmapcache_p.h util/qquickprofiler_p.h util/qquickpropertychanges.cpp util/qquickpropertychanges_p.h diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 6a03cdb5f7..bdc6bf0fb3 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -9,7 +9,7 @@ #include <private/qquickcontext2dtexture_p.h> #include <private/qsgadaptationlayer_p.h> #include <qsgtextureprovider.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include <QtGui/QGuiApplication> #include <qsgtextureprovider.h> diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index dee7616222..f331607e97 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -9,7 +9,7 @@ #include <private/qquickitem_p.h> #include <QtQuick/private/qquickevents_p_p.h> #include <private/qquickitemchangelistener_p.h> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qv4scopedvalue_p.h> #include <QtCore/qbuffer.h> #include <QtCore/qmimedata.h> diff --git a/src/quick/items/qquickdrag_p_p.h b/src/quick/items/qquickdrag_p_p.h index 3cb122dbcc..65d007572d 100644 --- a/src/quick/items/qquickdrag_p_p.h +++ b/src/quick/items/qquickdrag_p_p.h @@ -25,7 +25,7 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/private/qquickitemchangelistener_p.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index a27f1713b3..10a3db787d 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -18,7 +18,7 @@ #include "qquickimplicitsizeitem_p_p.h" #include "qquickimagebase_p.h" -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index bcd1afc19d..adc36e0b93 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -14,7 +14,7 @@ #include <QtQml/QQmlEngine> #include <QtQml/QQmlInfo> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qquickitem_p.h> #include <private/qsgcontext_p.h> #include <private/qsgadaptationlayer_p.h> diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h index 3ef8940edc..f7d6d84c98 100644 --- a/src/quick/items/qquickscalegrid_p_p.h +++ b/src/quick/items/qquickscalegrid_p_p.h @@ -20,7 +20,7 @@ #include <QtQml/qqml.h> #include <QtCore/qobject.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include <private/qtquickglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 015b2e1e4d..d7e32e1b35 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -23,7 +23,7 @@ QT_REQUIRE_CONFIG(quick_sprite); #include <QUrl> #include <QVariantMap> #include <QQmlListProperty> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include "qquickspriteengine_p.h" #include <QDebug> diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index b83a1804db..c7b01f81a5 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -28,7 +28,7 @@ QT_REQUIRE_CONFIG(quick_sprite); #include <QImage> #include <QPair> #include <QRandomGenerator> -#include <private/qquickpixmapcache_p.h> +#include <private/qquickpixmap_p.h> #include <private/qtquickglobal_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 4e9cadc115..e69d878409 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -29,7 +29,7 @@ #include <private/qtextengine_p.h> #include <private/qquickstyledtext_p.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include <qmath.h> #include <limits.h> diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp index ff28abe600..a24ee163d8 100644 --- a/src/quick/items/qquicktextdocument.cpp +++ b/src/quick/items/qquicktextdocument.cpp @@ -10,7 +10,7 @@ #include <QtQml/qqmlinfo.h> #include <QtQml/qqmlcontext.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 324ddd0b56..8a27671035 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -36,7 +36,7 @@ #include <QtQml/qqmlinfo.h> #include <QtQml/private/qqmlmetatype_p.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmldebugconnector_p.h> diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 17a685aee1..4271c079ce 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -4,7 +4,7 @@ #include <QtQuick/private/qsgcontext_p.h> #include <QtQuick/private/qsgtexture_p.h> #include <QtQuick/private/qsgrenderer_p.h> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> #include <QtQuick/private/qsgadaptationlayer_p.h> #include <QtQuick/private/qsginternaltextnode_p.h> diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index e3b96ddad4..38f6a4bc27 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -4,7 +4,7 @@ #include "qquickimageprovider.h" #include "qquickimageprovider_p.h" -#include "qquickpixmapcache_p.h" +#include "qquickpixmap_p.h" #include <QtQuick/private/qsgcontext_p.h> #include <private/qqmlglobal_p.h> #include <QtGui/qcolorspace.h> diff --git a/src/quick/util/qquickpixmap_p.h b/src/quick/util/qquickpixmap_p.h new file mode 100644 index 0000000000..86b3323b87 --- /dev/null +++ b/src/quick/util/qquickpixmap_p.h @@ -0,0 +1,203 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKPIXMAP_H +#define QQUICKPIXMAP_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qstring.h> +#include <QtGui/qpixmap.h> +#include <QtCore/qmutex.h> +#include <QtCore/qurl.h> +#include <private/qtquickglobal_p.h> +#include <QtQuick/qquickimageprovider.h> + +#include <private/qintrusivelist_p.h> + +QT_BEGIN_NAMESPACE + +class QQmlEngine; +class QQuickPixmapData; +class QQuickTextureFactory; +class QQuickImageProviderOptionsPrivate; + +class QQuickDefaultTextureFactory : public QQuickTextureFactory +{ + Q_OBJECT +public: + QQuickDefaultTextureFactory(const QImage &i); + QSGTexture *createTexture(QQuickWindow *window) const override; + QSize textureSize() const override { return size; } + int textureByteCount() const override { return size.width() * size.height() * 4; } + QImage image() const override { return im; } + +private: + QImage im; + QSize size; +}; + +class QQuickImageProviderPrivate +{ +public: + QQuickImageProvider::ImageType type; + QQuickImageProvider::Flags flags; + bool isProviderWithOptions; +}; + +// ### Qt 6: Make public moving to qquickimageprovider.h +class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderOptions +{ +public: + enum AutoTransform { + UsePluginDefaultTransform = -1, + ApplyTransform = 0, + DoNotApplyTransform = 1 + }; + + QQuickImageProviderOptions(); + ~QQuickImageProviderOptions(); + + QQuickImageProviderOptions(const QQuickImageProviderOptions&); + QQuickImageProviderOptions& operator=(const QQuickImageProviderOptions&); + + bool operator==(const QQuickImageProviderOptions&) const; + + AutoTransform autoTransform() const; + void setAutoTransform(AutoTransform autoTransform); + + bool preserveAspectRatioCrop() const; + void setPreserveAspectRatioCrop(bool preserveAspectRatioCrop); + + bool preserveAspectRatioFit() const; + void setPreserveAspectRatioFit(bool preserveAspectRatioFit); + + QColorSpace targetColorSpace() const; + void setTargetColorSpace(const QColorSpace &colorSpace); + +private: + QSharedDataPointer<QQuickImageProviderOptionsPrivate> d; +}; + +/*! \internal + A class that encapsulates the action of fetching a pixmap, as well as the + pixmap itself (indirectly via QQuickPixmapData::textureFactory) and the + responsibility of canceling outstanding requests. Rather than relying on + QPixmapCache which doesn't cache all the information Qt Quick needs, + QQuickPixmap implements its own cache, that correctly degrades over time. + (QQuickPixmapData::release() marks it as being not-currently-used, and + QQuickPixmapCache::shrinkCache() sweeps away the least-recently-released + instances until the remaining bytes are less than cache_limit.) +*/ +class Q_QUICK_PRIVATE_EXPORT QQuickPixmap +{ + Q_DECLARE_TR_FUNCTIONS(QQuickPixmap) +public: + QQuickPixmap(); + QQuickPixmap(QQmlEngine *, const QUrl &); + QQuickPixmap(QQmlEngine *, const QUrl &, const QRect ®ion, const QSize &); + QQuickPixmap(const QUrl &, const QImage &image); + ~QQuickPixmap(); + + enum Status { Null, Ready, Error, Loading }; + + enum Option { + Asynchronous = 0x00000001, + Cache = 0x00000002 + }; + Q_DECLARE_FLAGS(Options, Option) + + bool isNull() const; + bool isReady() const; + bool isError() const; + bool isLoading() const; + + Status status() const; + QString error() const; + const QUrl &url() const; + const QSize &implicitSize() const; + const QRect &requestRegion() const; + const QSize &requestSize() const; + QQuickImageProviderOptions::AutoTransform autoTransform() const; + int frameCount() const; + QImage image() const; + void setImage(const QImage &); + void setPixmap(const QQuickPixmap &other); + + QColorSpace colorSpace() const; + + QQuickTextureFactory *textureFactory() const; + + QRect rect() const; + int width() const; + int height() const; + + void load(QQmlEngine *, const QUrl &); + void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, QQuickPixmap::Options options); + void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, + QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1, + qreal devicePixelRatio = 1.0); + void loadImageFromDevice(QQmlEngine *engine, QIODevice *device, const QUrl &url, + const QRect &requestRegion, const QSize &requestSize, + const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1); + + void clear(); + void clear(QObject *); + + bool connectFinished(QObject *, const char *); + bool connectFinished(QObject *, int); + bool connectDownloadProgress(QObject *, const char *); + bool connectDownloadProgress(QObject *, int); + + static void purgeCache(); + static bool isCached(const QUrl &url, const QRect &requestRegion, const QSize &requestSize, + const int frame, const QQuickImageProviderOptions &options); + + static const QLatin1String itemGrabberScheme; + +private: + Q_DISABLE_COPY(QQuickPixmap) + QQuickPixmapData *d; + QIntrusiveListNode dataListNode; + friend class QQuickPixmapData; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPixmap::Options) + +// ### Qt 6: This should be made public in Qt 6. It's functionality can't be merged into +// QQuickImageProvider without breaking source compatibility. +class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderWithOptions : public QQuickAsyncImageProvider +{ +public: + QQuickImageProviderWithOptions(ImageType type, Flags flags = Flags()); + + QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override; + QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) override; + QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize) override; + QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; + + virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options); + virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options); + + static QSize loadSize(const QSize &originalSize, const QSize &requestedSize, const QByteArray &format, const QQuickImageProviderOptions &options, + qreal devicePixelRatio = 1.0); + static QQuickImageProviderWithOptions *checkedCast(QQuickImageProvider *provider); +}; + +QT_END_NAMESPACE + +#endif // QQUICKPIXMAP_H diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 7f37643920..a17a9aebc3 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -40,10 +40,10 @@ #define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8 -// After QQuickPixmapStore::unreferencePixmap() it may get deleted via a timer in 30 seconds +// After QQuickPixmapCache::unreferencePixmap() it may get deleted via a timer in 30 seconds #define CACHE_EXPIRE_TIME 30 -// How many (1/4) of the unreferenced pixmaps to delete in QQuickPixmapStore::timerEvent() +// How many (1/4) of the unreferenced pixmaps to delete in QQuickPixmapCache::timerEvent() #define CACHE_REMOVAL_FRACTION 4 #define PIXMAP_PROFILE(Code) Q_QUICK_PROFILE(QQuickProfiler::ProfilePixmapCache, Code) @@ -100,7 +100,7 @@ Q_LOGGING_CATEGORY(lcImg, "qt.quick.image") /*! \internal The maximum currently-unused image data that can be stored for potential - later reuse, in bytes. See QQuickPixmapStore::shrinkCache() + later reuse, in bytes. See QQuickPixmapCache::shrinkCache() */ static int cache_limit = 2048 * 1024; @@ -293,7 +293,7 @@ public: # define PIXMAP_READER_LOCK() #endif -class QQuickPixmapStore; +class QQuickPixmapCache; /*! \internal The private storage for QQuickPixmap. @@ -370,9 +370,9 @@ public: int cost() const; void addref(); - void release(QQuickPixmapStore *store = nullptr); + void release(QQuickPixmapCache *store = nullptr); void addToCache(); - void removeFromCache(QQuickPixmapStore *store = nullptr); + void removeFromCache(QQuickPixmapCache *store = nullptr); uint refCount; int frameCount; @@ -401,7 +401,7 @@ public: QQuickPixmapReply *reply; // prev/next pointers to form a linked list for dereferencing pixmaps that are currently unused - // (those get lazily deleted in QQuickPixmapStore::shrinkCache()) + // (those get lazily deleted in QQuickPixmapCache::shrinkCache()) QQuickPixmapData *prevUnreferenced; QQuickPixmapData**prevUnreferencedPtr; QQuickPixmapData *nextUnreferenced; @@ -1178,15 +1178,6 @@ void QQuickPixmapReader::run() #endif } -struct QQuickPixmapKey -{ - const QUrl *url; - const QRect *region; - const QSize *size; - int frame; - QQuickImageProviderOptions options; -}; - inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs) { return *lhs.url == *rhs.url && @@ -1225,45 +1216,13 @@ inline QDebug operator<<(QDebug debug, const QQuickPixmapKey &key) } #endif -class QQuickPixmapStore : public QObject -{ - Q_OBJECT -public: - QQuickPixmapStore(); - ~QQuickPixmapStore(); - - void unreferencePixmap(QQuickPixmapData *); - void referencePixmap(QQuickPixmapData *); - - void purgeCache(); - -protected: - void timerEvent(QTimerEvent *) override; - -public: - QHash<QQuickPixmapKey, QQuickPixmapData *> m_cache; - QMutex m_cacheMutex; // avoid simultaneous iteration and modification - -private: - Q_DISABLE_COPY(QQuickPixmapStore) - void shrinkCache(int remove); - - QQuickPixmapData *m_unreferencedPixmaps; - QQuickPixmapData *m_lastUnreferencedPixmap; - - int m_unreferencedCost; - int m_timerId; - bool m_destroying; -}; -Q_GLOBAL_STATIC(QQuickPixmapStore, pixmapStore); - - -QQuickPixmapStore::QQuickPixmapStore() - : m_unreferencedPixmaps(nullptr), m_lastUnreferencedPixmap(nullptr), m_unreferencedCost(0), m_timerId(-1), m_destroying(false) +QQuickPixmapCache *QQuickPixmapCache::instance() { + static QQuickPixmapCache self; + return &self; } -QQuickPixmapStore::~QQuickPixmapStore() +QQuickPixmapCache::~QQuickPixmapCache() { m_destroying = true; @@ -1306,7 +1265,7 @@ QQuickPixmapStore::~QQuickPixmapStore() Declare that \a data is currently unused so that shrinkCache() can lazily delete it later. */ -void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data) +void QQuickPixmapCache::unreferencePixmap(QQuickPixmapData *data) { Q_ASSERT(data->prevUnreferenced == nullptr); Q_ASSERT(data->prevUnreferencedPtr == nullptr); @@ -1340,7 +1299,7 @@ void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data) Declare that \a data is being used (by a QQuickPixmap) so that shrinkCache() won't delete it. (This is not reference counting though.) */ -void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data) +void QQuickPixmapCache::referencePixmap(QQuickPixmapData *data) { Q_ASSERT(data->prevUnreferencedPtr); @@ -1364,7 +1323,7 @@ void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data) Delete the least-recently-released QQuickPixmapData instances until the remaining bytes are less than cache_limit. */ -void QQuickPixmapStore::shrinkCache(int remove) +void QQuickPixmapCache::shrinkCache(int remove) { qCDebug(lcImg) << "reduce unreferenced cost" << m_unreferencedCost << "to less than limit" << cache_limit; while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) { @@ -1385,7 +1344,7 @@ void QQuickPixmapStore::shrinkCache(int remove) } } -void QQuickPixmapStore::timerEvent(QTimerEvent *) +void QQuickPixmapCache::timerEvent(QTimerEvent *) { int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION; @@ -1397,14 +1356,14 @@ void QQuickPixmapStore::timerEvent(QTimerEvent *) } } -void QQuickPixmapStore::purgeCache() +void QQuickPixmapCache::purgeCache() { shrinkCache(m_unreferencedCost); } void QQuickPixmap::purgeCache() { - pixmapStore()->purgeCache(); + QQuickPixmapCache::instance()->purgeCache(); } QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d) @@ -1470,10 +1429,10 @@ void QQuickPixmapData::addref() ++refCount; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount)); if (prevUnreferencedPtr) - pixmapStore()->referencePixmap(this); + QQuickPixmapCache::instance()->referencePixmap(this); } -void QQuickPixmapData::release(QQuickPixmapStore *store) +void QQuickPixmapData::release(QQuickPixmapCache *store) { Q_ASSERT(refCount > 0); --refCount; @@ -1490,7 +1449,7 @@ void QQuickPixmapData::release(QQuickPixmapStore *store) QQuickPixmapReader::readerMutex.unlock(); } - store = store ? store : pixmapStore(); + store = store ? store : QQuickPixmapCache::instance(); if (pixmapStatus == QQuickPixmap::Ready #ifdef Q_OS_WEBOS && storeToCache @@ -1508,7 +1467,7 @@ void QQuickPixmapData::release(QQuickPixmapStore *store) } /*! \internal - Add this to the global static QQuickPixmapStore. + Add this to the QQuickPixmapCache singleton. \note The actual image will end up in QQuickPixmapData::textureFactory. At the time addToCache() is called, it's generally not yet loaded; so the @@ -1522,30 +1481,30 @@ void QQuickPixmapData::addToCache() { if (!inCache) { QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; - QMutexLocker locker(&pixmapStore()->m_cacheMutex); + QMutexLocker locker(&QQuickPixmapCache::instance()->m_cacheMutex); if (lcImg().isDebugEnabled()) { - qCDebug(lcImg) << "adding" << key << "to total" << pixmapStore()->m_cache.size(); - for (auto it = pixmapStore()->m_cache.keyBegin(); it != pixmapStore()->m_cache.keyEnd(); ++it) { + qCDebug(lcImg) << "adding" << key << "to total" << QQuickPixmapCache::instance()->m_cache.size(); + for (auto it = QQuickPixmapCache::instance()->m_cache.keyBegin(); it != QQuickPixmapCache::instance()->m_cache.keyEnd(); ++it) { if (*(it->url) == url && it->frame == frame) qDebug(lcImg) << " similar pre-existing:" << *it; } } - pixmapStore()->m_cache.insert(key, this); + QQuickPixmapCache::instance()->m_cache.insert(key, this); inCache = true; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( - url, pixmapStore()->m_cache.size())); + url, QQuickPixmapCache::instance()->m_cache.size())); } } -void QQuickPixmapData::removeFromCache(QQuickPixmapStore *store) +void QQuickPixmapData::removeFromCache(QQuickPixmapCache *store) { if (inCache) { if (!store) - store = pixmapStore(); + store = QQuickPixmapCache::instance(); QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; - QMutexLocker locker(&pixmapStore()->m_cacheMutex); + QMutexLocker locker(&QQuickPixmapCache::instance()->m_cacheMutex); store->m_cache.remove(key); - qCDebug(lcImg) << "removed" << key << implicitSize << "; total remaining" << pixmapStore()->m_cache.size(); + qCDebug(lcImg) << "removed" << key << implicitSize << "; total remaining" << QQuickPixmapCache::instance()->m_cache.size(); inCache = false; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( url, store->m_cache.size())); @@ -1880,9 +1839,9 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QRect &reques } QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; - QQuickPixmapStore *store = pixmapStore(); + QQuickPixmapCache *store = QQuickPixmapCache::instance(); - QMutexLocker locker(&pixmapStore()->m_cacheMutex); + QMutexLocker locker(&QQuickPixmapCache::instance()->m_cacheMutex); QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.end(); #ifdef Q_OS_WEBOS @@ -1977,7 +1936,7 @@ void QQuickPixmap::loadImageFromDevice(QQmlEngine *engine, QIODevice *device, co { auto oldD = d; QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, providerOptions }; - QQuickPixmapStore *store = pixmapStore(); + QQuickPixmapCache *store = QQuickPixmapCache::instance(); QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.end(); QMutexLocker locker(&store->m_cacheMutex); iter = store->m_cache.find(key); @@ -2036,7 +1995,7 @@ bool QQuickPixmap::isCached(const QUrl &url, const QRect &requestRegion, const Q const int frame, const QQuickImageProviderOptions &options) { QQuickPixmapKey key = { &url, &requestRegion, &requestSize, frame, options }; - QQuickPixmapStore *store = pixmapStore(); + QQuickPixmapCache *store = QQuickPixmapCache::instance(); return store->m_cache.contains(key); } diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index 77e1bb4189..de942aa019 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -15,186 +15,67 @@ // We mean it. // -#include <QtCore/qcoreapplication.h> -#include <QtCore/qstring.h> -#include <QtGui/qpixmap.h> +#include <QtCore/qmutex.h> #include <QtCore/qurl.h> -#include <private/qtquickglobal_p.h> #include <QtQuick/qquickimageprovider.h> - -#include <private/qintrusivelist_p.h> +#include <private/qquickpixmap_p.h> QT_BEGIN_NAMESPACE -class QQmlEngine; class QQuickPixmapData; -class QQuickTextureFactory; -class QQuickImageProviderOptionsPrivate; -class QQuickDefaultTextureFactory : public QQuickTextureFactory +/*! \internal + A composite key to identify a QQuickPixmapData instance in a QHash. +*/ +struct Q_AUTOTEST_EXPORT QQuickPixmapKey { - Q_OBJECT -public: - QQuickDefaultTextureFactory(const QImage &i); - QSGTexture *createTexture(QQuickWindow *window) const override; - QSize textureSize() const override { return size; } - int textureByteCount() const override { return size.width() * size.height() * 4; } - QImage image() const override { return im; } - -private: - QImage im; - QSize size; + const QUrl *url; + const QRect *region; + const QSize *size; + int frame; + QQuickImageProviderOptions options; }; -class QQuickImageProviderPrivate +/*! \internal + A singleton managing the storage and garbage collection of QQuickPixmapData + instances. It's exported only for the sake of autotests, and should not be + manipulated outside qquickpixmap.cpp and qquickpixmapcache.cpp. +*/ +class Q_AUTOTEST_EXPORT QQuickPixmapCache : public QObject { -public: - QQuickImageProvider::ImageType type; - QQuickImageProvider::Flags flags; - bool isProviderWithOptions; -}; + Q_OBJECT -// ### Qt 6: Make public moving to qquickimageprovider.h -class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderOptions -{ public: - enum AutoTransform { - UsePluginDefaultTransform = -1, - ApplyTransform = 0, - DoNotApplyTransform = 1 - }; - - QQuickImageProviderOptions(); - ~QQuickImageProviderOptions(); - - QQuickImageProviderOptions(const QQuickImageProviderOptions&); - QQuickImageProviderOptions& operator=(const QQuickImageProviderOptions&); + static QQuickPixmapCache *instance(); + ~QQuickPixmapCache() override; - bool operator==(const QQuickImageProviderOptions&) const; + void unreferencePixmap(QQuickPixmapData *); + void referencePixmap(QQuickPixmapData *); - AutoTransform autoTransform() const; - void setAutoTransform(AutoTransform autoTransform); + void purgeCache(); - bool preserveAspectRatioCrop() const; - void setPreserveAspectRatioCrop(bool preserveAspectRatioCrop); - - bool preserveAspectRatioFit() const; - void setPreserveAspectRatioFit(bool preserveAspectRatioFit); - - QColorSpace targetColorSpace() const; - void setTargetColorSpace(const QColorSpace &colorSpace); +protected: + void timerEvent(QTimerEvent *) override; private: - QSharedDataPointer<QQuickImageProviderOptionsPrivate> d; -}; + QQuickPixmapCache() = default; + Q_DISABLE_COPY(QQuickPixmapCache) -/*! \internal - A class that encapsulates the action of fetching a pixmap, as well as the - pixmap itself (indirectly via QQuickPixmapData::textureFactory) and the - responsibility of canceling outstanding requests. Rather than relying on - QPixmapCache which doesn't cache all the information Qt Quick needs, - QQuickPixmap implements its own cache, that correctly degrades over time. - (QQuickPixmapData::release() marks it as being not-currently-used, and - QQuickPixmapStore::shrinkCache() sweeps away the least-recently-released - instances until the remaining bytes are less than cache_limit.) -*/ -class Q_QUICK_PRIVATE_EXPORT QQuickPixmap -{ - Q_DECLARE_TR_FUNCTIONS(QQuickPixmap) -public: - QQuickPixmap(); - QQuickPixmap(QQmlEngine *, const QUrl &); - QQuickPixmap(QQmlEngine *, const QUrl &, const QRect ®ion, const QSize &); - QQuickPixmap(const QUrl &, const QImage &image); - ~QQuickPixmap(); - - enum Status { Null, Ready, Error, Loading }; - - enum Option { - Asynchronous = 0x00000001, - Cache = 0x00000002 - }; - Q_DECLARE_FLAGS(Options, Option) - - bool isNull() const; - bool isReady() const; - bool isError() const; - bool isLoading() const; - - Status status() const; - QString error() const; - const QUrl &url() const; - const QSize &implicitSize() const; - const QRect &requestRegion() const; - const QSize &requestSize() const; - QQuickImageProviderOptions::AutoTransform autoTransform() const; - int frameCount() const; - QImage image() const; - void setImage(const QImage &); - void setPixmap(const QQuickPixmap &other); - - QColorSpace colorSpace() const; - - QQuickTextureFactory *textureFactory() const; - - QRect rect() const; - int width() const; - int height() const; - - void load(QQmlEngine *, const QUrl &); - void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options); - void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize); - void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, QQuickPixmap::Options options); - void load(QQmlEngine *, const QUrl &, const QRect &requestRegion, const QSize &requestSize, - QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1, - qreal devicePixelRatio = 1.0); - void loadImageFromDevice(QQmlEngine *engine, QIODevice *device, const QUrl &url, - const QRect &requestRegion, const QSize &requestSize, - const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1); - - void clear(); - void clear(QObject *); - - bool connectFinished(QObject *, const char *); - bool connectFinished(QObject *, int); - bool connectDownloadProgress(QObject *, const char *); - bool connectDownloadProgress(QObject *, int); - - static void purgeCache(); - static bool isCached(const QUrl &url, const QRect &requestRegion, const QSize &requestSize, - const int frame, const QQuickImageProviderOptions &options); - - static const QLatin1String itemGrabberScheme; + void shrinkCache(int remove); private: - Q_DISABLE_COPY(QQuickPixmap) - QQuickPixmapData *d; - QIntrusiveListNode dataListNode; - friend class QQuickPixmapData; -}; + QHash<QQuickPixmapKey, QQuickPixmapData *> m_cache; + QMutex m_cacheMutex; // avoid simultaneous iteration and modification -Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPixmap::Options) + QQuickPixmapData *m_unreferencedPixmaps = nullptr; + QQuickPixmapData *m_lastUnreferencedPixmap = nullptr; -// ### Qt 6: This should be made public in Qt 6. It's functionality can't be merged into -// QQuickImageProvider without breaking source compatibility. -class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderWithOptions : public QQuickAsyncImageProvider -{ -public: - QQuickImageProviderWithOptions(ImageType type, Flags flags = Flags()); + int m_unreferencedCost = 0; + int m_timerId = -1; + bool m_destroying = false; - QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override; - QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) override; - QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize) override; - QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; - - virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); - virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); - virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options); - virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options); - - static QSize loadSize(const QSize &originalSize, const QSize &requestedSize, const QByteArray &format, const QQuickImageProviderOptions &options, - qreal devicePixelRatio = 1.0); - static QQuickImageProviderWithOptions *checkedCast(QQuickImageProvider *provider); + friend class QQuickPixmap; + friend class QQuickPixmapData; }; QT_END_NAMESPACE diff --git a/src/quick/util/qquickstyledtext_p.h b/src/quick/util/qquickstyledtext_p.h index b7d51871a3..af4b980c44 100644 --- a/src/quick/util/qquickstyledtext_p.h +++ b/src/quick/util/qquickstyledtext_p.h @@ -19,7 +19,7 @@ #include <QPointF> #include <QList> #include <QUrl> -#include <QtQuick/private/qquickpixmapcache_p.h> +#include <QtQuick/private/qquickpixmap_p.h> QT_BEGIN_NAMESPACE |