QPixmapCache: make sure to not overflow cache limit

The cost for the pixmap cache was calculated in bytes but
setCacheLimit() takes the size in kilobytes. This lead to the
situation that all values above 2097152 overflowed and disabled
the caching completely. Fix it by calculating the cost in
kilobytes as it is done in QGLContext.

Task-number: QTBUG-45293
Change-Id: Ib8dc2360c8f3201ce0b615a04c38b5ccaa8fc6cf
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
This commit is contained in:
Christian Ehrlicher 2018-04-05 21:12:52 +02:00
parent 4840ec7c68
commit c7cbf21699
2 changed files with 20 additions and 8 deletions

View File

@ -86,7 +86,17 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap \sa QCache, QPixmap
*/ */
static int cache_limit = 10240; // 10 MB cache limit static const int cache_limit_default = 10240; // 10 MB cache limit
static inline int cost(const QPixmap &pixmap)
{
// make sure to do a 64bit calculation
const qint64 costKb = static_cast<qint64>(pixmap.width()) *
pixmap.height() * pixmap.depth() / (8 * 1024);
const qint64 costMax = std::numeric_limits<int>::max();
// a small pixmap should have at least a cost of 1(kb)
return static_cast<int>(qBound(1LL, costKb, costMax));
}
/*! /*!
\class QPixmapCache::Key \class QPixmapCache::Key
@ -237,7 +247,7 @@ uint qHash(const QPixmapCache::Key &k)
QPMCache::QPMCache() QPMCache::QPMCache()
: QObject(0), : QObject(0),
QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit * 1024), QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit_default),
keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false) keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false)
{ {
} }
@ -553,7 +563,7 @@ bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
{ {
return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); return pm_cache()->insert(key, pixmap, cost(pixmap));
} }
/*! /*!
@ -573,7 +583,7 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
*/ */
QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap) QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
{ {
return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); return pm_cache()->insert(pixmap, cost(pixmap));
} }
/*! /*!
@ -590,7 +600,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
//The key is not valid anymore, a flush happened before probably //The key is not valid anymore, a flush happened before probably
if (!key.d || !key.d->isValid) if (!key.d || !key.d->isValid)
return false; return false;
return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); return pm_cache()->replace(key, pixmap, cost(pixmap));
} }
/*! /*!
@ -603,7 +613,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
int QPixmapCache::cacheLimit() int QPixmapCache::cacheLimit()
{ {
return cache_limit; return pm_cache()->maxCost();
} }
/*! /*!
@ -616,8 +626,7 @@ int QPixmapCache::cacheLimit()
void QPixmapCache::setCacheLimit(int n) void QPixmapCache::setCacheLimit(int n)
{ {
cache_limit = n; pm_cache()->setMaxCost(n);
pm_cache()->setMaxCost(1024 * cache_limit);
} }
/*! /*!

View File

@ -92,6 +92,9 @@ void tst_QPixmapCache::cacheLimit()
// it was between 2048 and 10240 last time I looked at it // it was between 2048 and 10240 last time I looked at it
QVERIFY(originalCacheLimit >= 1024 && originalCacheLimit <= 20480); QVERIFY(originalCacheLimit >= 1024 && originalCacheLimit <= 20480);
QPixmapCache::setCacheLimit(std::numeric_limits<int>::max());
QCOMPARE(QPixmapCache::cacheLimit(), std::numeric_limits<int>::max());
QPixmapCache::setCacheLimit(100); QPixmapCache::setCacheLimit(100);
QCOMPARE(QPixmapCache::cacheLimit(), 100); QCOMPARE(QPixmapCache::cacheLimit(), 100);