Notify resource caches when pixelref genID goes stale
patch from issue 954443002 at patchset 40001 (http://crrev.com/954443002#ps40001) BUG=skia: Review URL: https://codereview.chromium.org/950363002
This commit is contained in:
parent
4b583ac54b
commit
7eeba25877
@ -15,7 +15,7 @@ public:
|
||||
intptr_t fValue;
|
||||
|
||||
TestKey(intptr_t value) : fValue(value) {
|
||||
this->init(&gGlobalAddress, sizeof(fValue));
|
||||
this->init(&gGlobalAddress, 0, sizeof(fValue));
|
||||
}
|
||||
};
|
||||
struct TestRec : public SkResourceCache::Rec {
|
||||
|
@ -10,6 +10,20 @@
|
||||
#include "SkMipMap.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
/**
|
||||
* Use this for bitmapcache and mipmapcache entries.
|
||||
*/
|
||||
uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID) {
|
||||
uint64_t sharedID = SkSetFourByteTag('b', 'm', 'a', 'p');
|
||||
return (sharedID << 32) | bitmapGenID;
|
||||
}
|
||||
|
||||
void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID) {
|
||||
SkResourceCache::PostPurgeSharedID(SkMakeResourceCacheSharedIDForBitmap(bitmapGenID));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkBitmap::Allocator* SkBitmapCache::GetAllocator() {
|
||||
return SkResourceCache::GetAllocator();
|
||||
}
|
||||
@ -33,13 +47,13 @@ static unsigned gBitmapKeyNamespaceLabel;
|
||||
|
||||
struct BitmapKey : public SkResourceCache::Key {
|
||||
public:
|
||||
BitmapKey(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds)
|
||||
: fGenID(genID)
|
||||
, fScaleX(scaleX)
|
||||
, fScaleY(scaleY)
|
||||
, fBounds(bounds)
|
||||
BitmapKey(uint32_t genID, SkScalar sx, SkScalar sy, const SkIRect& bounds)
|
||||
: fGenID(genID)
|
||||
, fScaleX(sx)
|
||||
, fScaleY(sy)
|
||||
, fBounds(bounds)
|
||||
{
|
||||
this->init(&gBitmapKeyNamespaceLabel,
|
||||
this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
|
||||
sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(fBounds));
|
||||
}
|
||||
|
||||
@ -49,8 +63,6 @@ public:
|
||||
SkIRect fBounds;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct BitmapRec : public SkResourceCache::Rec {
|
||||
BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds,
|
||||
const SkBitmap& result)
|
||||
@ -58,13 +70,10 @@ struct BitmapRec : public SkResourceCache::Rec {
|
||||
, fBitmap(result)
|
||||
{}
|
||||
|
||||
BitmapKey fKey;
|
||||
SkBitmap fBitmap;
|
||||
|
||||
const Key& getKey() const SK_OVERRIDE { return fKey; }
|
||||
size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
|
||||
|
||||
static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
|
||||
static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
|
||||
const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
|
||||
SkBitmap* result = (SkBitmap*)contextBitmap;
|
||||
|
||||
@ -72,6 +81,10 @@ struct BitmapRec : public SkResourceCache::Rec {
|
||||
result->lockPixels();
|
||||
return SkToBool(result->getPixels());
|
||||
}
|
||||
|
||||
private:
|
||||
BitmapKey fKey;
|
||||
SkBitmap fBitmap;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -86,7 +99,7 @@ bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invSc
|
||||
}
|
||||
BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
|
||||
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
|
||||
}
|
||||
|
||||
void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
|
||||
@ -105,7 +118,7 @@ bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result
|
||||
SkResourceCache* localCache) {
|
||||
BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
|
||||
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
|
||||
}
|
||||
|
||||
bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result,
|
||||
@ -125,11 +138,27 @@ bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& r
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
static unsigned gMipMapKeyNamespaceLabel;
|
||||
|
||||
struct MipMapKey : public SkResourceCache::Key {
|
||||
public:
|
||||
MipMapKey(uint32_t genID, const SkIRect& bounds) : fGenID(genID), fBounds(bounds) {
|
||||
this->init(&gMipMapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
|
||||
sizeof(fGenID) + sizeof(fBounds));
|
||||
}
|
||||
|
||||
uint32_t fGenID;
|
||||
SkIRect fBounds;
|
||||
};
|
||||
|
||||
struct MipMapRec : public SkResourceCache::Rec {
|
||||
MipMapRec(const SkBitmap& src, const SkMipMap* result)
|
||||
: fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src))
|
||||
: fKey(src.getGenerationID(), get_bounds_from_bitmap(src))
|
||||
, fMipMap(result)
|
||||
{
|
||||
fMipMap->attachToCacheAndRef();
|
||||
@ -142,7 +171,7 @@ struct MipMapRec : public SkResourceCache::Rec {
|
||||
const Key& getKey() const SK_OVERRIDE { return fKey; }
|
||||
size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->size(); }
|
||||
|
||||
static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) {
|
||||
static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
|
||||
const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
|
||||
const SkMipMap* mm = SkRef(rec.fMipMap);
|
||||
// the call to ref() above triggers a "lock" in the case of discardable memory,
|
||||
@ -157,15 +186,16 @@ struct MipMapRec : public SkResourceCache::Rec {
|
||||
}
|
||||
|
||||
private:
|
||||
BitmapKey fKey;
|
||||
MipMapKey fKey;
|
||||
const SkMipMap* fMipMap;
|
||||
};
|
||||
}
|
||||
|
||||
const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) {
|
||||
BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src));
|
||||
MipMapKey key(src.getGenerationID(), get_bounds_from_bitmap(src));
|
||||
const SkMipMap* result;
|
||||
|
||||
if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Visitor, &result)) {
|
||||
if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
|
||||
result = NULL;
|
||||
}
|
||||
return result;
|
||||
@ -184,4 +214,3 @@ const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* l
|
||||
}
|
||||
return mipmap;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,10 @@
|
||||
class SkResourceCache;
|
||||
class SkMipMap;
|
||||
|
||||
uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID);
|
||||
|
||||
void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID);
|
||||
|
||||
class SkBitmapCache {
|
||||
public:
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
, fQuality(quality)
|
||||
, fRRect(rrect)
|
||||
{
|
||||
this->init(&gRRectBlurKeyNamespaceLabel,
|
||||
this->init(&gRRectBlurKeyNamespaceLabel, 0,
|
||||
sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fRRect));
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ public:
|
||||
fSizes[2] = SkSize::Make(rects[0].x() - rects[1].x(), rects[0].y() - rects[1].y());
|
||||
}
|
||||
|
||||
this->init(&gRectsBlurKeyNamespaceLabel,
|
||||
this->init(&gRectsBlurKeyNamespaceLabel, 0,
|
||||
sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fSizes));
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
sizeof(fLocalMatrixStorage);
|
||||
// This better be packed.
|
||||
SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - &fPictureID) == keySize);
|
||||
this->init(&gBitmapSkaderKeyNamespaceLabel, keySize);
|
||||
this->init(&gBitmapSkaderKeyNamespaceLabel, 0, keySize);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkThread.h"
|
||||
|
||||
@ -214,12 +215,18 @@ void SkPixelRef::addGenIDChangeListener(GenIDChangeListener* listener) {
|
||||
*fGenIDChangeListeners.append() = listener;
|
||||
}
|
||||
|
||||
// we need to be called *before* the genID gets changed or zerod
|
||||
void SkPixelRef::callGenIDChangeListeners() {
|
||||
// We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
|
||||
if (fUniqueGenerationID) {
|
||||
for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
|
||||
fGenIDChangeListeners[i]->onChange();
|
||||
}
|
||||
|
||||
// If we can flag the pixelref somehow whenever it was actually added to the cache,
|
||||
// perhaps it would be nice to only call this notifier in that case. For now we always
|
||||
// call it, since we don't know if it was cached or not.
|
||||
SkNotifyBitmapGenIDIsStale(fGenerationID);
|
||||
}
|
||||
// Listeners get at most one shot, so whether these triggered or not, blow them away.
|
||||
fGenIDChangeListeners.deleteAll();
|
||||
|
@ -6,12 +6,15 @@
|
||||
*/
|
||||
|
||||
#include "SkChecksum.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkMessageBus.h"
|
||||
#include "SkMipMap.h"
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkResourceCache.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
DECLARE_SKMESSAGEBUS_MESSAGE(SkResourceCache::PurgeSharedIDMessage)
|
||||
|
||||
// This can be defined by the caller's build system
|
||||
//#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
|
||||
|
||||
@ -23,18 +26,22 @@
|
||||
#define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
void SkResourceCache::Key::init(void* nameSpace, size_t length) {
|
||||
void SkResourceCache::Key::init(void* nameSpace, uint64_t sharedID, size_t length) {
|
||||
SkASSERT(SkAlign4(length) == length);
|
||||
|
||||
// fCount32 and fHash are not hashed
|
||||
static const int kUnhashedLocal32s = 2;
|
||||
static const int kLocal32s = kUnhashedLocal32s + (sizeof(fNamespace) >> 2);
|
||||
static const int kUnhashedLocal32s = 2; // fCache32 + fHash
|
||||
static const int kSharedIDLocal32s = 2; // fSharedID_lo + fSharedID_hi
|
||||
static const int kHashedLocal32s = kSharedIDLocal32s + (sizeof(fNamespace) >> 2);
|
||||
static const int kLocal32s = kUnhashedLocal32s + kHashedLocal32s;
|
||||
|
||||
SK_COMPILE_ASSERT(sizeof(Key) == (kLocal32s << 2), unaccounted_key_locals);
|
||||
SK_COMPILE_ASSERT(sizeof(Key) == offsetof(Key, fNamespace) + sizeof(fNamespace),
|
||||
namespace_field_must_be_last);
|
||||
|
||||
fCount32 = SkToS32(kLocal32s + (length >> 2));
|
||||
fSharedID_lo = (uint32_t)sharedID;
|
||||
fSharedID_hi = (uint32_t)(sharedID >> 32);
|
||||
fNamespace = nameSpace;
|
||||
// skip unhashed fields when computing the murmur
|
||||
fHash = SkChecksum::Murmur3(this->as32() + kUnhashedLocal32s,
|
||||
@ -199,7 +206,9 @@ SkResourceCache::~SkResourceCache() {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) {
|
||||
bool SkResourceCache::find(const Key& key, FindVisitor visitor, void* context) {
|
||||
this->checkMessages();
|
||||
|
||||
Rec* rec = fHash->find(key);
|
||||
if (rec) {
|
||||
if (visitor(*rec, context)) {
|
||||
@ -226,6 +235,8 @@ static void make_size_str(size_t size, SkString* str) {
|
||||
static bool gDumpCacheTransactions;
|
||||
|
||||
void SkResourceCache::add(Rec* rec) {
|
||||
this->checkMessages();
|
||||
|
||||
SkASSERT(rec);
|
||||
// See if we already have this key (racy inserts, etc.)
|
||||
Rec* existing = fHash->find(rec->getKey());
|
||||
@ -294,6 +305,24 @@ void SkResourceCache::purgeAsNeeded(bool forcePurge) {
|
||||
}
|
||||
}
|
||||
|
||||
void SkResourceCache::purgeSharedID(uint64_t sharedID) {
|
||||
if (0 == sharedID) {
|
||||
return;
|
||||
}
|
||||
|
||||
// go backwards, just like purgeAsNeeded, just to make the code similar.
|
||||
// could iterate either direction and still be correct.
|
||||
Rec* rec = fTail;
|
||||
while (rec) {
|
||||
Rec* prev = rec->fPrev;
|
||||
if (rec->getKey().getSharedID() == sharedID) {
|
||||
// SkDebugf("purgeSharedID id=%llx rec=%p\n", sharedID, rec);
|
||||
this->remove(rec);
|
||||
}
|
||||
rec = prev;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SkResourceCache::setTotalByteLimit(size_t newLimit) {
|
||||
size_t prevLimit = fTotalByteLimit;
|
||||
fTotalByteLimit = newLimit;
|
||||
@ -304,6 +333,8 @@ size_t SkResourceCache::setTotalByteLimit(size_t newLimit) {
|
||||
}
|
||||
|
||||
SkCachedData* SkResourceCache::newCachedData(size_t bytes) {
|
||||
this->checkMessages();
|
||||
|
||||
if (fDiscardableFactory) {
|
||||
SkDiscardableMemory* dm = fDiscardableFactory(bytes);
|
||||
return dm ? SkNEW_ARGS(SkCachedData, (bytes, dm)) : NULL;
|
||||
@ -451,6 +482,14 @@ size_t SkResourceCache::getEffectiveSingleAllocationByteLimit() const {
|
||||
return limit;
|
||||
}
|
||||
|
||||
void SkResourceCache::checkMessages() {
|
||||
SkTArray<PurgeSharedIDMessage> msgs;
|
||||
fPurgeSharedIDInbox.poll(&msgs);
|
||||
for (int i = 0; i < msgs.count(); ++i) {
|
||||
this->purgeSharedID(msgs[i].fSharedID);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkThread.h"
|
||||
@ -537,7 +576,7 @@ void SkResourceCache::PurgeAll() {
|
||||
return get_cache()->purgeAll();
|
||||
}
|
||||
|
||||
bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) {
|
||||
bool SkResourceCache::Find(const Key& key, FindVisitor visitor, void* context) {
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
return get_cache()->find(key, visitor, context);
|
||||
}
|
||||
@ -547,6 +586,12 @@ void SkResourceCache::Add(Rec* rec) {
|
||||
get_cache()->add(rec);
|
||||
}
|
||||
|
||||
void SkResourceCache::PostPurgeSharedID(uint64_t sharedID) {
|
||||
if (sharedID) {
|
||||
SkMessageBus<PurgeSharedIDMessage>::Post(PurgeSharedIDMessage(sharedID));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkGraphics.h"
|
||||
|
@ -9,6 +9,8 @@
|
||||
#define SkResourceCache_DEFINED
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkMessageBus.h"
|
||||
#include "SkTDArray.h"
|
||||
|
||||
class SkCachedData;
|
||||
class SkDiscardableMemory;
|
||||
@ -32,8 +34,12 @@ public:
|
||||
|
||||
// must call this after your private data has been written.
|
||||
// nameSpace must be unique per Key subclass.
|
||||
// sharedID == 0 means ignore this field : does not support group purging.
|
||||
// length must be a multiple of 4
|
||||
void init(void* nameSpace, size_t length);
|
||||
void init(void* nameSpace, uint64_t sharedID, size_t length);
|
||||
|
||||
void* getNamespace() const { return fNamespace; }
|
||||
uint64_t getSharedID() const { return ((uint64_t)fSharedID_hi << 32) | fSharedID_lo; }
|
||||
|
||||
// This is only valid after having called init().
|
||||
uint32_t hash() const { return fHash; }
|
||||
@ -52,6 +58,9 @@ public:
|
||||
private:
|
||||
int32_t fCount32; // local + user contents count32
|
||||
uint32_t fHash;
|
||||
// split uint64_t into hi and lo so we don't force ourselves to pad on 32bit machines.
|
||||
uint32_t fSharedID_lo;
|
||||
uint32_t fSharedID_hi;
|
||||
void* fNamespace; // A unique namespace tag. This is hashed.
|
||||
/* uint32_t fContents32[] */
|
||||
|
||||
@ -80,6 +89,13 @@ public:
|
||||
friend class SkResourceCache;
|
||||
};
|
||||
|
||||
// Used with SkMessageBus
|
||||
struct PurgeSharedIDMessage {
|
||||
PurgeSharedIDMessage(uint64_t sharedID) : fSharedID(sharedID) {}
|
||||
|
||||
uint64_t fSharedID;
|
||||
};
|
||||
|
||||
typedef const Rec* ID;
|
||||
|
||||
/**
|
||||
@ -92,7 +108,7 @@ public:
|
||||
* true, then the Rec is considered "valid". If false is returned, the Rec will be considered
|
||||
* "stale" and will be purged from the cache.
|
||||
*/
|
||||
typedef bool (*VisitorProc)(const Rec&, void* context);
|
||||
typedef bool (*FindVisitor)(const Rec&, void* context);
|
||||
|
||||
/**
|
||||
* Returns a locked/pinned SkDiscardableMemory instance for the specified
|
||||
@ -109,12 +125,12 @@ public:
|
||||
* Returns true if the visitor was called on a matching Key, and the visitor returned true.
|
||||
*
|
||||
* Find() will search the cache for the specified Key. If no match is found, return false and
|
||||
* do not call the VisitorProc. If a match is found, return whatever the visitor returns.
|
||||
* do not call the FindVisitor. If a match is found, return whatever the visitor returns.
|
||||
* Its return value is interpreted to mean:
|
||||
* true : Rec is valid
|
||||
* false : Rec is "stale" -- the cache will purge it.
|
||||
*/
|
||||
static bool Find(const Key& key, VisitorProc, void* context);
|
||||
static bool Find(const Key& key, FindVisitor, void* context);
|
||||
static void Add(Rec*);
|
||||
|
||||
static size_t GetTotalBytesUsed();
|
||||
@ -140,6 +156,8 @@ public:
|
||||
|
||||
static SkCachedData* NewCachedData(size_t bytes);
|
||||
|
||||
static void PostPurgeSharedID(uint64_t sharedID);
|
||||
|
||||
/**
|
||||
* Call SkDebugf() with diagnostic information about the state of the cache
|
||||
*/
|
||||
@ -169,12 +187,12 @@ public:
|
||||
* Returns true if the visitor was called on a matching Key, and the visitor returned true.
|
||||
*
|
||||
* find() will search the cache for the specified Key. If no match is found, return false and
|
||||
* do not call the VisitorProc. If a match is found, return whatever the visitor returns.
|
||||
* do not call the FindVisitor. If a match is found, return whatever the visitor returns.
|
||||
* Its return value is interpreted to mean:
|
||||
* true : Rec is valid
|
||||
* false : Rec is "stale" -- the cache will purge it.
|
||||
*/
|
||||
bool find(const Key&, VisitorProc, void* context);
|
||||
bool find(const Key&, FindVisitor, void* context);
|
||||
void add(Rec*);
|
||||
|
||||
size_t getTotalBytesUsed() const { return fTotalBytesUsed; }
|
||||
@ -198,6 +216,8 @@ public:
|
||||
*/
|
||||
size_t setTotalByteLimit(size_t newLimit);
|
||||
|
||||
void purgeSharedID(uint64_t sharedID);
|
||||
|
||||
void purgeAll() {
|
||||
this->purgeAsNeeded(true);
|
||||
}
|
||||
@ -228,6 +248,9 @@ private:
|
||||
size_t fSingleAllocationByteLimit;
|
||||
int fCount;
|
||||
|
||||
SkMessageBus<PurgeSharedIDMessage>::Inbox fPurgeSharedIDInbox;
|
||||
|
||||
void checkMessages();
|
||||
void purgeAsNeeded(bool forcePurge = false);
|
||||
|
||||
// linklist management
|
||||
|
@ -5,8 +5,9 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkYUVPlanesCache.h"
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkYUVPlanesCache.h"
|
||||
|
||||
#define CHECK_LOCAL(localCache, localName, globalName, ...) \
|
||||
((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
|
||||
@ -23,7 +24,8 @@ struct YUVPlanesKey : public SkResourceCache::Key {
|
||||
YUVPlanesKey(uint32_t genID)
|
||||
: fGenID(genID)
|
||||
{
|
||||
this->init(&gYUVPlanesKeyNamespaceLabel, sizeof(genID));
|
||||
this->init(&gYUVPlanesKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
|
||||
sizeof(genID));
|
||||
}
|
||||
|
||||
uint32_t fGenID;
|
||||
|
@ -14,8 +14,8 @@ static void* gGlobalAddress;
|
||||
struct TestingKey : public SkResourceCache::Key {
|
||||
intptr_t fValue;
|
||||
|
||||
TestingKey(intptr_t value) : fValue(value) {
|
||||
this->init(&gGlobalAddress, sizeof(fValue));
|
||||
TestingKey(intptr_t value, uint64_t sharedID = 0) : fValue(value) {
|
||||
this->init(&gGlobalAddress, sharedID, sizeof(fValue));
|
||||
}
|
||||
};
|
||||
struct TestingRec : public SkResourceCache::Rec {
|
||||
@ -71,6 +71,38 @@ static void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache, boo
|
||||
cache.setTotalByteLimit(0);
|
||||
}
|
||||
|
||||
static void test_cache_purge_shared_id(skiatest::Reporter* reporter, SkResourceCache& cache) {
|
||||
for (int i = 0; i < COUNT; ++i) {
|
||||
TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID
|
||||
cache.add(SkNEW_ARGS(TestingRec, (key, i)));
|
||||
}
|
||||
|
||||
// Ensure that everyone is present
|
||||
for (int i = 0; i < COUNT; ++i) {
|
||||
TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID
|
||||
intptr_t value = -1;
|
||||
|
||||
REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
|
||||
REPORTER_ASSERT(reporter, value == i);
|
||||
}
|
||||
|
||||
// Now purge the ones that had a non-zero sharedID (the odd-indexed ones)
|
||||
cache.purgeSharedID(1);
|
||||
|
||||
// Ensure that only the even ones are still present
|
||||
for (int i = 0; i < COUNT; ++i) {
|
||||
TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID
|
||||
intptr_t value = -1;
|
||||
|
||||
if (i & 1) {
|
||||
REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value));
|
||||
} else {
|
||||
REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
|
||||
REPORTER_ASSERT(reporter, value == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "SkDiscardableMemoryPool.h"
|
||||
|
||||
static SkDiscardableMemoryPool* gPool;
|
||||
@ -97,6 +129,10 @@ DEF_TEST(ImageCache, reporter) {
|
||||
SkResourceCache cache(SkDiscardableMemory::Create);
|
||||
test_cache(reporter, cache, false);
|
||||
}
|
||||
{
|
||||
SkResourceCache cache(defLimit);
|
||||
test_cache_purge_shared_id(reporter, cache);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(ImageCache_doubleAdd, r) {
|
||||
|
@ -156,6 +156,14 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
|
||||
mipmap = SkMipMapCache::AddAndRef(src, cache);
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
|
||||
{
|
||||
const SkMipMap* mm = SkMipMapCache::FindAndRef(src, cache);
|
||||
REPORTER_ASSERT(reporter, mm);
|
||||
REPORTER_ASSERT(reporter, mm == mipmap);
|
||||
mm->unref();
|
||||
}
|
||||
|
||||
check_data(reporter, mipmap, 2, kInCache, kLocked);
|
||||
|
||||
mipmap->unref();
|
||||
@ -173,6 +181,60 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
mipmap->unref();
|
||||
}
|
||||
|
||||
static void test_mipmap_notify(skiatest::Reporter* reporter, SkResourceCache* cache) {
|
||||
const int N = 3;
|
||||
SkBitmap src[N];
|
||||
for (int i = 0; i < N; ++i) {
|
||||
src[i].allocN32Pixels(5, 5);
|
||||
src[i].setImmutable();
|
||||
SkMipMapCache::AddAndRef(src[i], cache)->unref();
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(src[i], cache);
|
||||
if (cache) {
|
||||
// if cache is null, we're working on the global cache, and other threads might purge
|
||||
// it, making this check fragile.
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
}
|
||||
SkSafeUnref(mipmap);
|
||||
|
||||
src[i].reset(); // delete the underlying pixelref, which *should* remove us from the cache
|
||||
|
||||
mipmap = SkMipMapCache::FindAndRef(src[i], cache);
|
||||
REPORTER_ASSERT(reporter, !mipmap);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_bitmap_notify(skiatest::Reporter* reporter, SkResourceCache* cache) {
|
||||
const SkIRect subset = SkIRect::MakeWH(5, 5);
|
||||
const int N = 3;
|
||||
SkBitmap src[N], dst[N];
|
||||
for (int i = 0; i < N; ++i) {
|
||||
src[i].allocN32Pixels(5, 5);
|
||||
src[i].setImmutable();
|
||||
dst[i].allocN32Pixels(5, 5);
|
||||
dst[i].setImmutable();
|
||||
SkBitmapCache::Add(src[i].getGenerationID(), subset, dst[i], cache);
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
const uint32_t genID = src[i].getGenerationID();
|
||||
SkBitmap result;
|
||||
bool found = SkBitmapCache::Find(genID, subset, &result, cache);
|
||||
if (cache) {
|
||||
// if cache is null, we're working on the global cache, and other threads might purge
|
||||
// it, making this check fragile.
|
||||
REPORTER_ASSERT(reporter, found);
|
||||
}
|
||||
|
||||
src[i].reset(); // delete the underlying pixelref, which *should* remove us from the cache
|
||||
|
||||
found = SkBitmapCache::Find(genID, subset, &result, cache);
|
||||
REPORTER_ASSERT(reporter, !found);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(BitmapCache_discarded_bitmap, reporter) {
|
||||
SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory();
|
||||
SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
|
||||
@ -219,4 +281,6 @@ DEF_TEST(BitmapCache_discarded_bitmap, reporter) {
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
|
||||
test_mipmapcache(reporter, cache);
|
||||
test_bitmap_notify(reporter, cache);
|
||||
test_mipmap_notify(reporter, cache);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user