summaryrefslogtreecommitdiffstats
path: root/src/gui/platform
diff options
context:
space:
mode:
authorVolker Hilsheimer <[email protected]>2024-08-01 09:34:24 +0200
committerVolker Hilsheimer <[email protected]>2024-08-03 03:09:53 +0200
commitc8a2794c441dfc6aa0ceec3ae847a8b1e353a89f (patch)
tree25b7662af5904ef7eb1d22db5bc0846e1f14dd0f /src/gui/platform
parentd897e6a5f37a8ddd99d6d1cfe2b91e14a3dfdeed (diff)
Apple: cache all pixmaps from the icon engine
So far we have only cached the most recently requested pixmap, under the assumption that this is the one usually requested several times in a row. However, our menu integration requests the pixmaps for all available sizes when populating the native menu item with an NSImage. Not caching the pixmaps for all sizes results in repeated rendering of the image, which significantly slows down the opening of native menus e.g. using Qt Quick's labs.platform Menu. Use a per-icon-engine cache for the pixmaps, with a cache key that is a struct holding the mode, state, size, and scale factor. Pick-to: 6.8 6.7 Fixes: QTBUG-127614 Change-Id: Ie13cae8c69a8ee979907d4b9ea01bcdd89dd585b Reviewed-by: Tor Arne Vestbø <[email protected]>
Diffstat (limited to 'src/gui/platform')
-rw-r--r--src/gui/platform/darwin/qappleiconengine.mm22
-rw-r--r--src/gui/platform/darwin/qappleiconengine_p.h28
2 files changed, 32 insertions, 18 deletions
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
index 4dd8e42124e..d99da6da841 100644
--- a/src/gui/platform/darwin/qappleiconengine.mm
+++ b/src/gui/platform/darwin/qappleiconengine.mm
@@ -397,26 +397,26 @@ auto *configuredImage(const UIImage *image, const QColor &color)
QPixmap QAppleIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
{
- const quint64 cacheKey = calculateCacheKey(mode, state);
- if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
+ const CacheKey key(mode, state, size, scale);
+ QPixmap pixmap = m_cache.value(key);
+ if (pixmap.isNull()) {
const QSize paintSize = actualSize(size, mode, state);
const QSize paintOffset = paintSize != size
? (QSizeF(size - paintSize) * 0.5).toSize()
: QSize();
- m_pixmap = QPixmap(size * scale);
- m_pixmap.setDevicePixelRatio(scale);
- m_pixmap.fill(Qt::transparent);
+ pixmap = QPixmap(size * scale);
+ pixmap.setDevicePixelRatio(scale);
+ pixmap.fill(Qt::transparent);
- if (!m_pixmap.isNull()) {
- QPainter painter(&m_pixmap);
+ if (!pixmap.isNull()) {
+ QPainter painter(&pixmap);
paint(&painter, QRect(paintOffset.width(), paintOffset.height(),
- paintSize.width(), paintSize.height()), mode, state);
+ paintSize.width(), paintSize.height()), mode, state);
+ m_cache.insert(key, pixmap);
}
-
- m_cacheKey = cacheKey;
}
- return m_pixmap;
+ return pixmap;
}
void QAppleIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
diff --git a/src/gui/platform/darwin/qappleiconengine_p.h b/src/gui/platform/darwin/qappleiconengine_p.h
index 2a4ff7fc649..d99c60ffc54 100644
--- a/src/gui/platform/darwin/qappleiconengine_p.h
+++ b/src/gui/platform/darwin/qappleiconengine_p.h
@@ -17,6 +17,8 @@
#include <QtGui/qiconengine.h>
+#include <QtCore/qhash.h>
+
#include <QtCore/private/qcore_mac_p.h>
Q_FORWARD_DECLARE_OBJC_CLASS(UIImage);
@@ -43,19 +45,31 @@ public:
static QList<QSize> availableIconSizes(double aspectRatio = 1.0);
private:
- static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
- {
- return (quint64(mode) << 32) | state;
- }
-
const QString m_iconName;
#if defined(Q_OS_MACOS)
const NSImage *m_image;
#elif defined(QT_PLATFORM_UIKIT)
const UIImage *m_image;
#endif
- mutable QPixmap m_pixmap;
- mutable quint64 m_cacheKey = {};
+ struct CacheKey {
+ constexpr CacheKey(QIcon::Mode mode, QIcon::State state, QSize size, qreal scale) noexcept
+ : modeAndState((quint64(mode) << 32) | state), size(size), scale(scale)
+ {}
+
+ quint64 modeAndState;
+ QSize size;
+ qreal scale;
+
+ friend constexpr bool operator==(const CacheKey &lhs, const CacheKey &rhs) noexcept
+ {
+ return lhs.modeAndState == rhs.modeAndState
+ && lhs.size == rhs.size
+ && lhs.scale == rhs.scale;
+ }
+ friend constexpr size_t qHash(const CacheKey &key, size_t seed) noexcept
+ { return qHashMulti(seed, key.modeAndState, key.size, key.scale); }
+ };
+ mutable QHash<CacheKey, QPixmap> m_cache;
};