| Index: src/core/SkScaledImageCache.cpp
|
| diff --git a/src/core/SkScaledImageCache.cpp b/src/core/SkScaledImageCache.cpp
|
| index eba20c4f906644ce16307a4e18d30963d5188e1e..25e29c2fb74aa3738e8b6f7a92ab0f07523dcc78 100644
|
| --- a/src/core/SkScaledImageCache.cpp
|
| +++ b/src/core/SkScaledImageCache.cpp
|
| @@ -11,6 +11,13 @@
|
| #include "SkPixelRef.h"
|
| #include "SkRect.h"
|
|
|
| +// This can be defined by the caller's build system
|
| +//#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
|
| +
|
| +#ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
|
| +# define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024
|
| +#endif
|
| +
|
| #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
|
| #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024)
|
| #endif
|
| @@ -164,7 +171,7 @@ static inline SkScaledImageCache::Rec* find_rec_in_list(
|
| }
|
| #endif
|
|
|
| -SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
|
| +void SkScaledImageCache::init() {
|
| fHead = NULL;
|
| fTail = NULL;
|
| #ifdef USE_HASH
|
| @@ -173,11 +180,133 @@ SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
|
| fHash = NULL;
|
| #endif
|
| fBytesUsed = 0;
|
| - fByteLimit = byteLimit;
|
| fCount = 0;
|
| + fAllocator = NULL;
|
| +
|
| + // One of these should be explicit set by the caller after we return.
|
| + fByteLimit = 0;
|
| + fDiscardableFactory = NULL;
|
| +}
|
| +
|
| +#include "SkDiscardableMemory.h"
|
| +
|
| +class SkOneShotDiscardablePixelRef : public SkPixelRef {
|
| +public:
|
| + // Ownership of the discardablememory is transfered to the pixelref
|
| + SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_t rowBytes);
|
| + ~SkOneShotDiscardablePixelRef();
|
| +
|
| + SK_DECLARE_UNFLATTENABLE_OBJECT()
|
| +
|
| +protected:
|
| + virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
|
| + virtual void onUnlockPixels() SK_OVERRIDE;
|
| + virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
|
| +
|
| +private:
|
| + SkImageInfo fInfo; // remove when SkPixelRef gets this in baseclass
|
| +
|
| + SkDiscardableMemory* fDM;
|
| + size_t fRB;
|
| + bool fFirstTime;
|
| +
|
| + typedef SkPixelRef INHERITED;
|
| +};
|
| +
|
| +SkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& info,
|
| + SkDiscardableMemory* dm,
|
| + size_t rowBytes)
|
| + : INHERITED(info)
|
| + , fDM(dm)
|
| + , fRB(rowBytes)
|
| +{
|
| + fInfo = info; // remove this redundant field when SkPixelRef has info
|
| +
|
| + SkASSERT(dm->data());
|
| + fFirstTime = true;
|
| +}
|
| +
|
| +SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
|
| + SkDELETE(fDM);
|
| +}
|
| +
|
| +void* SkOneShotDiscardablePixelRef::onLockPixels(SkColorTable** ctable) {
|
| + if (fFirstTime) {
|
| + // we're already locked
|
| + fFirstTime = false;
|
| + return fDM->data();
|
| + }
|
| + return fDM->lock() ? fDM->data() : NULL;
|
| +}
|
| +
|
| +void SkOneShotDiscardablePixelRef::onUnlockPixels() {
|
| + SkASSERT(!fFirstTime);
|
| + fDM->unlock();
|
| +}
|
| +
|
| +size_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const {
|
| + return fInfo.fHeight * fRB;
|
| +}
|
| +
|
| +class SkScaledImageCacheDiscardableAllocator : public SkBitmap::Allocator {
|
| +public:
|
| + SkScaledImageCacheDiscardableAllocator(
|
| + SkScaledImageCache::DiscardableFactory factory) {
|
| + SkASSERT(factory);
|
| + fFactory = factory;
|
| + }
|
| +
|
| + virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
|
| +
|
| +private:
|
| + SkScaledImageCache::DiscardableFactory fFactory;
|
| +};
|
| +
|
| +bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
|
| + SkColorTable* ctable) {
|
| + size_t size = bitmap->getSize();
|
| + if (0 == size) {
|
| + return false;
|
| + }
|
| +
|
| + SkDiscardableMemory* dm = fFactory(size);
|
| + if (NULL == dm) {
|
| + return false;
|
| + }
|
| +
|
| + // can relax when we have bitmap::asImageInfo
|
| + if (SkBitmap::kARGB_8888_Config != bitmap->config()) {
|
| + return false;
|
| + }
|
| +
|
| + SkImageInfo info = {
|
| + bitmap->width(),
|
| + bitmap->height(),
|
| + kPMColor_SkColorType,
|
| + bitmap->alphaType()
|
| + };
|
| +
|
| + bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef,
|
| + (info, dm, bitmap->rowBytes())))->unref();
|
| + bitmap->lockPixels();
|
| + return bitmap->readyToDraw();
|
| +}
|
| +
|
| +SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) {
|
| + this->init();
|
| + fDiscardableFactory = factory;
|
| +
|
| + fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory));
|
| +}
|
| +
|
| +SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
|
| + this->init();
|
| + fByteLimit = byteLimit;
|
| }
|
|
|
| SkScaledImageCache::~SkScaledImageCache() {
|
| + SkSafeUnref(fAllocator);
|
| +
|
| Rec* rec = fHead;
|
| while (rec) {
|
| Rec* next = rec->fNext;
|
| @@ -367,30 +496,45 @@ void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
|
| }
|
|
|
| void SkScaledImageCache::purgeAsNeeded() {
|
| - size_t byteLimit = fByteLimit;
|
| - size_t bytesUsed = fBytesUsed;
|
| + size_t byteLimit;
|
| + int countLimit;
|
| +
|
| + if (fDiscardableFactory) {
|
| + countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT;
|
| + byteLimit = SK_MaxU32; // no limit based on bytes
|
| + } else {
|
| + countLimit = SK_MaxS32; // no limit based on count
|
| + byteLimit = fByteLimit;
|
| + }
|
|
|
| + size_t bytesUsed = fBytesUsed;
|
| + int countUsed = fCount;
|
| +
|
| Rec* rec = fTail;
|
| while (rec) {
|
| - if (bytesUsed < byteLimit) {
|
| + if (bytesUsed < byteLimit && countUsed < countLimit) {
|
| break;
|
| }
|
| +
|
| Rec* prev = rec->fPrev;
|
| if (0 == rec->fLockCount) {
|
| size_t used = rec->bytesUsed();
|
| SkASSERT(used <= bytesUsed);
|
| - bytesUsed -= used;
|
| this->detach(rec);
|
| #ifdef USE_HASH
|
| fHash->remove(rec->fKey);
|
| #endif
|
|
|
| SkDELETE(rec);
|
| - fCount -= 1;
|
| +
|
| + bytesUsed -= used;
|
| + countUsed -= 1;
|
| }
|
| rec = prev;
|
| }
|
| +
|
| fBytesUsed = bytesUsed;
|
| + fCount = countUsed;
|
| }
|
|
|
| size_t SkScaledImageCache::setByteLimit(size_t newLimit) {
|
| @@ -513,7 +657,11 @@ void SkScaledImageCache::validate() const {
|
| SK_DECLARE_STATIC_MUTEX(gMutex);
|
|
|
| static void create_cache(SkScaledImageCache** cache) {
|
| +#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
|
| + *cache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
|
| +#else
|
| *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
|
| +#endif
|
| }
|
|
|
| static SkScaledImageCache* get_cache() {
|
| @@ -592,6 +740,11 @@ size_t SkScaledImageCache::SetByteLimit(size_t newLimit) {
|
| return get_cache()->setByteLimit(newLimit);
|
| }
|
|
|
| +SkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
|
| + SkAutoMutexAcquire am(gMutex);
|
| + return get_cache()->allocator();
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| #include "SkGraphics.h"
|
|
|