allow SkBitmapCache to operate on a local instance, for testability
BUG=skia: R=mtklein@google.com, danakj@chromium.org, piotaixr@chromium.org, junov@chromium.org Author: reed@google.com Review URL: https://codereview.chromium.org/576763002
This commit is contained in:
parent
4815fe5a0a
commit
30ad5306be
@ -70,33 +70,41 @@ struct BitmapRec : public SkResourceCache::Rec {
|
||||
}
|
||||
};
|
||||
|
||||
bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
|
||||
SkBitmap* result) {
|
||||
#define CHECK_LOCAL(localCache, localName, globalName, ...) \
|
||||
(localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__)
|
||||
|
||||
bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result,
|
||||
SkResourceCache* localCache) {
|
||||
if (0 == invScaleX || 0 == invScaleY) {
|
||||
// degenerate, and the key we use for mipmaps
|
||||
return false;
|
||||
}
|
||||
BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
|
||||
return SkResourceCache::Find(key, BitmapRec::Visitor, result);
|
||||
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
|
||||
}
|
||||
|
||||
void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
|
||||
const SkBitmap& result) {
|
||||
const SkBitmap& result, SkResourceCache* localCache) {
|
||||
if (0 == invScaleX || 0 == invScaleY) {
|
||||
// degenerate, and the key we use for mipmaps
|
||||
return;
|
||||
}
|
||||
SkASSERT(result.isImmutable());
|
||||
SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
|
||||
get_bounds_from_bitmap(src), result)));
|
||||
BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
|
||||
get_bounds_from_bitmap(src), result));
|
||||
CHECK_LOCAL(localCache, add, Add, rec);
|
||||
}
|
||||
|
||||
bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result) {
|
||||
bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
|
||||
SkResourceCache* localCache) {
|
||||
BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
|
||||
return SkResourceCache::Find(key, BitmapRec::Visitor, result);
|
||||
|
||||
return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
|
||||
}
|
||||
|
||||
bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result) {
|
||||
bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result,
|
||||
SkResourceCache* localCache) {
|
||||
SkASSERT(result.isImmutable());
|
||||
|
||||
if (subset.isEmpty()
|
||||
@ -106,9 +114,9 @@ bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& r
|
||||
|| result.height() != subset.height()) {
|
||||
return false;
|
||||
} else {
|
||||
SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1,
|
||||
subset, result)));
|
||||
BitmapRec* rec = SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1, subset, result));
|
||||
|
||||
CHECK_LOCAL(localCache, add, Add, rec);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "SkScalar.h"
|
||||
#include "SkBitmap.h"
|
||||
|
||||
class SkResourceCache;
|
||||
class SkMipMap;
|
||||
|
||||
class SkBitmapCache {
|
||||
@ -25,25 +26,28 @@ public:
|
||||
* Search based on the src bitmap and inverse scales in X and Y. If found, returns true and
|
||||
* result will be set to the matching bitmap with its pixels already locked.
|
||||
*/
|
||||
static bool Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result);
|
||||
static bool Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result,
|
||||
SkResourceCache* localCache = NULL);
|
||||
|
||||
/*
|
||||
* result must be marked isImmutable()
|
||||
*/
|
||||
static void Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
|
||||
const SkBitmap& result);
|
||||
const SkBitmap& result, SkResourceCache* localCache = NULL);
|
||||
|
||||
/**
|
||||
* Search based on the bitmap's genID and subset. If found, returns true and
|
||||
* result will be set to the matching bitmap with its pixels already locked.
|
||||
*/
|
||||
static bool Find(uint32_t genID, const SkIRect& subset, SkBitmap* result);
|
||||
static bool Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
|
||||
SkResourceCache* localCache = NULL);
|
||||
|
||||
/**
|
||||
* The width and the height of the provided subset must be the same as the result bitmap ones.
|
||||
* result must be marked isImmutable()
|
||||
*/
|
||||
static bool Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result);
|
||||
static bool Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result,
|
||||
SkResourceCache* localCache = NULL);
|
||||
};
|
||||
|
||||
class SkMipMapCache {
|
||||
|
@ -432,6 +432,11 @@ size_t SkResourceCache::SetTotalByteLimit(size_t newLimit) {
|
||||
return get_cache()->setTotalByteLimit(newLimit);
|
||||
}
|
||||
|
||||
SkResourceCache::DiscardableFactory SkResourceCache::GetDiscardableFactory() {
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
return get_cache()->discardableFactory();
|
||||
}
|
||||
|
||||
SkBitmap::Allocator* SkResourceCache::GetAllocator() {
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
return get_cache()->allocator();
|
||||
|
@ -125,6 +125,11 @@ public:
|
||||
|
||||
static void PurgeAll();
|
||||
|
||||
/**
|
||||
* Returns the DiscardableFactory used by the global cache, or NULL.
|
||||
*/
|
||||
static DiscardableFactory GetDiscardableFactory();
|
||||
|
||||
/**
|
||||
* Use this allocator for bitmaps, so they can use ashmem when available.
|
||||
* Returns NULL if the ResourceCache has not been initialized with a DiscardableFactory.
|
||||
@ -189,6 +194,7 @@ public:
|
||||
this->purgeAsNeeded(true);
|
||||
}
|
||||
|
||||
DiscardableFactory discardableFactory() const { return fDiscardableFactory; }
|
||||
SkBitmap::Allocator* allocator() const { return fAllocator; };
|
||||
|
||||
/**
|
||||
|
@ -4,11 +4,13 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Test.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDiscardableMemoryPool.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkResourceCache.h"
|
||||
|
||||
static const int kCanvasSize = 1;
|
||||
static const int kBitmapSize = 16;
|
||||
@ -74,72 +76,93 @@ DEF_TEST(ResourceCache_SingleAllocationByteLimit, reporter) {
|
||||
SkGraphics::SetResourceCacheTotalByteLimit(originalByteLimit);
|
||||
}
|
||||
|
||||
#if 0 // skia:2912
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkBitmap createAllocatedBitmap(const SkImageInfo& info) {
|
||||
SkBitmap cachedBitmap;
|
||||
cachedBitmap.setInfo(info);
|
||||
SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
|
||||
static void make_bitmap(SkBitmap* bitmap, const SkImageInfo& info, SkBitmap::Allocator* allocator) {
|
||||
if (allocator) {
|
||||
allocator->allocPixelRef(&cachedBitmap, 0);
|
||||
bitmap->setInfo(info);
|
||||
allocator->allocPixelRef(bitmap, 0);
|
||||
} else {
|
||||
cachedBitmap.allocPixels();
|
||||
bitmap->allocPixels(info);
|
||||
}
|
||||
|
||||
return cachedBitmap;
|
||||
}
|
||||
|
||||
// http://skbug.com/2894
|
||||
DEF_TEST(BitmapCache_add_rect, reporter) {
|
||||
SkBitmap bm;
|
||||
SkIRect rect = SkIRect::MakeWH(5, 5);
|
||||
SkBitmap cachedBitmap = createAllocatedBitmap(SkImageInfo::MakeN32Premul(5, 5));
|
||||
SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory();
|
||||
SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
|
||||
|
||||
SkAutoTDelete<SkResourceCache> cache;
|
||||
if (factory) {
|
||||
cache.reset(SkNEW_ARGS(SkResourceCache, (factory)));
|
||||
} else {
|
||||
const size_t byteLimit = 100 * 1024;
|
||||
cache.reset(SkNEW_ARGS(SkResourceCache, (byteLimit)));
|
||||
}
|
||||
SkBitmap cachedBitmap;
|
||||
make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
|
||||
cachedBitmap.setImmutable();
|
||||
|
||||
SkBitmap bm;
|
||||
SkIRect rect = SkIRect::MakeWH(5, 5);
|
||||
|
||||
// Wrong subset size
|
||||
REPORTER_ASSERT(reporter, ! SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeWH(4, 6), cachedBitmap));
|
||||
REPORTER_ASSERT(reporter, ! SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeWH(4, 6), cachedBitmap, cache));
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
// Wrong offset value
|
||||
REPORTER_ASSERT(reporter, ! SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeXYWH(-1, 0, 5, 5), cachedBitmap));
|
||||
REPORTER_ASSERT(reporter, ! SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeXYWH(-1, 0, 5, 5), cachedBitmap, cache));
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
|
||||
// Should not be in the cache
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
|
||||
// Should be in the cache, we just added it
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
}
|
||||
|
||||
DEF_TEST(BitmapCache_discarded_bitmap, reporter) {
|
||||
SkBitmap bm;
|
||||
SkIRect rect = SkIRect::MakeWH(5, 5);
|
||||
SkBitmap cachedBitmap = createAllocatedBitmap(SkImageInfo::MakeN32Premul(5, 5));
|
||||
SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory();
|
||||
SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
|
||||
|
||||
SkAutoTDelete<SkResourceCache> cache;
|
||||
if (factory) {
|
||||
cache.reset(SkNEW_ARGS(SkResourceCache, (factory)));
|
||||
} else {
|
||||
const size_t byteLimit = 100 * 1024;
|
||||
cache.reset(SkNEW_ARGS(SkResourceCache, (byteLimit)));
|
||||
}
|
||||
SkBitmap cachedBitmap;
|
||||
make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
|
||||
cachedBitmap.setImmutable();
|
||||
cachedBitmap.unlockPixels();
|
||||
|
||||
SkBitmap bm;
|
||||
SkIRect rect = SkIRect::MakeWH(5, 5);
|
||||
|
||||
// Add a bitmap to the cache.
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
|
||||
// Finding more than once works fine.
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
bm.unlockPixels();
|
||||
|
||||
// Drop the pixels in the bitmap.
|
||||
REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() > 0);
|
||||
SkGetGlobalDiscardableMemoryPool()->dumpPool();
|
||||
REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() == 0);
|
||||
if (factory) {
|
||||
REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() > 0);
|
||||
SkGetGlobalDiscardableMemoryPool()->dumpPool();
|
||||
REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() == 0);
|
||||
|
||||
// The bitmap is not in the cache since it has been dropped.
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
// The bitmap is not in the cache since it has been dropped.
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
}
|
||||
|
||||
cachedBitmap = createAllocatedBitmap(SkImageInfo::MakeN32Premul(5, 5));
|
||||
make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
|
||||
cachedBitmap.setImmutable();
|
||||
cachedBitmap.unlockPixels();
|
||||
|
||||
// We can add the bitmap back to the cache and find it again.
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
|
||||
REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user