Use SkImage to manage mip map cache purging, not Bitmap/PixelRef
Lazy and GPU images manage the notification themselves, but raster images now forward the notification request to the pixelRef. Bug: skia: Change-Id: I93e0ebd3749e3f7dbd506466299fde8923982435 Reviewed-on: https://skia-review.googlesource.com/c/161830 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
11dd1ab3b9
commit
087c917670
@ -7,6 +7,7 @@
|
||||
|
||||
#include "SkAtomics.h"
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkBitmapProvider.h"
|
||||
#include "SkImage.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkMipMap.h"
|
||||
@ -342,12 +343,18 @@ static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache)
|
||||
: SkResourceCache::GetDiscardableFactory();
|
||||
}
|
||||
|
||||
const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* localCache) {
|
||||
const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmapProvider& provider,
|
||||
SkResourceCache* localCache) {
|
||||
SkBitmap src;
|
||||
if (!provider.asBitmap(&src)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkMipMap* mipmap = SkMipMap::Build(src, get_fact(localCache));
|
||||
if (mipmap) {
|
||||
MipMapRec* rec = new MipMapRec(SkBitmapCacheDesc::Make(src), mipmap);
|
||||
MipMapRec* rec = new MipMapRec(provider.makeCacheDesc(), mipmap);
|
||||
CHECK_LOCAL(localCache, add, Add, rec);
|
||||
src.pixelRef()->notifyAddedToCache();
|
||||
provider.notifyAddedToCache();
|
||||
}
|
||||
return mipmap;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "SkBitmap.h"
|
||||
#include "SkMipMap.h"
|
||||
|
||||
class SkBitmapProvider;
|
||||
class SkImage;
|
||||
class SkResourceCache;
|
||||
|
||||
@ -61,7 +62,8 @@ class SkMipMapCache {
|
||||
public:
|
||||
static const SkMipMap* FindAndRef(const SkBitmapCacheDesc&,
|
||||
SkResourceCache* localCache = nullptr);
|
||||
static const SkMipMap* AddAndRef(const SkBitmap& src, SkResourceCache* localCache = nullptr);
|
||||
static const SkMipMap* AddAndRef(const SkBitmapProvider&,
|
||||
SkResourceCache* localCache = nullptr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -78,11 +78,7 @@ bool SkBitmapController::State::processMediumRequest(const SkBitmapProvider& pro
|
||||
if (invScaleSize.width() > SK_Scalar1 || invScaleSize.height() > SK_Scalar1) {
|
||||
fCurrMip.reset(SkMipMapCache::FindAndRef(provider.makeCacheDesc()));
|
||||
if (nullptr == fCurrMip.get()) {
|
||||
SkBitmap orig;
|
||||
if (!provider.asBitmap(&orig)) {
|
||||
return false;
|
||||
}
|
||||
fCurrMip.reset(SkMipMapCache::AddAndRef(orig));
|
||||
fCurrMip.reset(SkMipMapCache::AddAndRef(provider));
|
||||
if (nullptr == fCurrMip.get()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
|
||||
// Call when this image is part of the key to a resourcecache entry. This allows the cache
|
||||
// to know automatically those entries can be purged when this SkImage deleted.
|
||||
void notifyAddedToRasterCache() const {
|
||||
virtual void notifyAddedToRasterCache() const {
|
||||
fAddedToRasterCache.store(true);
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,13 @@ public:
|
||||
sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const override;
|
||||
|
||||
bool onIsValid(GrContext* context) const override { return true; }
|
||||
void notifyAddedToRasterCache() const override {
|
||||
// We explicitly DON'T want to call INHERITED::notifyAddedToRasterCache. That ties the
|
||||
// lifetime of derived/cached resources to the image. In this case, we only want cached
|
||||
// data (eg mips) tied to the lifetime of the underlying pixelRef.
|
||||
SkASSERT(fBitmap.pixelRef());
|
||||
fBitmap.pixelRef()->notifyAddedToCache();
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
sk_sp<GrTextureProxy> refPinnedTextureProxy(uint32_t* uniqueID) const override;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "Test.h"
|
||||
#include "SkBitmapCache.h"
|
||||
#include "SkBitmapProvider.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDiscardableMemoryPool.h"
|
||||
#include "SkGraphics.h"
|
||||
@ -43,15 +44,18 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
SkBitmap src;
|
||||
src.allocN32Pixels(5, 5);
|
||||
src.setImmutable();
|
||||
sk_sp<SkImage> img = SkImage::MakeFromBitmap(src);
|
||||
SkBitmapProvider provider(img.get());
|
||||
const auto desc = provider.makeCacheDesc();
|
||||
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(desc, cache);
|
||||
REPORTER_ASSERT(reporter, nullptr == mipmap);
|
||||
|
||||
mipmap = SkMipMapCache::AddAndRef(src, cache);
|
||||
mipmap = SkMipMapCache::AddAndRef(provider, cache);
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
|
||||
{
|
||||
const SkMipMap* mm = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
const SkMipMap* mm = SkMipMapCache::FindAndRef(desc, cache);
|
||||
REPORTER_ASSERT(reporter, mm);
|
||||
REPORTER_ASSERT(reporter, mm == mipmap);
|
||||
mm->unref();
|
||||
@ -65,7 +69,7 @@ static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cach
|
||||
check_data(reporter, mipmap, 1, kInCache, kNotLocked);
|
||||
|
||||
// find us again
|
||||
mipmap = SkMipMapCache::FindAndRef(SkBitmapCacheDesc::Make(src), cache);
|
||||
mipmap = SkMipMapCache::FindAndRef(desc, cache);
|
||||
check_data(reporter, mipmap, 2, kInCache, kLocked);
|
||||
|
||||
cache->purgeAll();
|
||||
@ -78,25 +82,29 @@ static void test_mipmap_notify(skiatest::Reporter* reporter, SkResourceCache* ca
|
||||
const int N = 3;
|
||||
|
||||
SkBitmap src[N];
|
||||
sk_sp<SkImage> img[N];
|
||||
SkBitmapCacheDesc desc[N];
|
||||
for (int i = 0; i < N; ++i) {
|
||||
src[i].allocN32Pixels(5, 5);
|
||||
src[i].setImmutable();
|
||||
SkMipMapCache::AddAndRef(src[i], cache)->unref();
|
||||
img[i] = SkImage::MakeFromBitmap(src[i]);
|
||||
SkBitmapProvider provider(img[i].get());
|
||||
SkMipMapCache::AddAndRef(provider, cache)->unref();
|
||||
desc[i] = provider.makeCacheDesc();
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
const auto desc = SkBitmapCacheDesc::Make(src[i]);
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(desc, 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);
|
||||
}
|
||||
const SkMipMap* mipmap = SkMipMapCache::FindAndRef(desc[i], cache);
|
||||
// We're always using a local cache, so we know we won't be purged by other threads
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
SkSafeUnref(mipmap);
|
||||
|
||||
src[i].reset(); // delete the underlying pixelref, which *should* remove us from the cache
|
||||
img[i].reset(); // delete the image, which *should not* remove us from the cache
|
||||
mipmap = SkMipMapCache::FindAndRef(desc[i], cache);
|
||||
REPORTER_ASSERT(reporter, mipmap);
|
||||
|
||||
mipmap = SkMipMapCache::FindAndRef(desc, cache);
|
||||
src[i].reset(); // delete the underlying pixelref, which *should* remove us from the cache
|
||||
mipmap = SkMipMapCache::FindAndRef(desc[i], cache);
|
||||
REPORTER_ASSERT(reporter, !mipmap);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user