Add SkMaskCache
BUG=skia: Review URL: https://codereview.chromium.org/670063004
This commit is contained in:
parent
26979c8260
commit
d9aac34ece
@ -104,6 +104,7 @@
|
||||
'<(skia_src_path)/core/SkLineClipper.cpp',
|
||||
'<(skia_src_path)/core/SkMallocPixelRef.cpp',
|
||||
'<(skia_src_path)/core/SkMask.cpp',
|
||||
'<(skia_src_path)/core/SkMaskCache.cpp',
|
||||
'<(skia_src_path)/core/SkMaskFilter.cpp',
|
||||
'<(skia_src_path)/core/SkMaskGamma.cpp',
|
||||
'<(skia_src_path)/core/SkMaskGamma.h',
|
||||
|
@ -133,6 +133,7 @@
|
||||
'../tests/LazyPtrTest.cpp',
|
||||
'../tests/MD5Test.cpp',
|
||||
'../tests/MallocPixelRefTest.cpp',
|
||||
'../tests/MaskCacheTest.cpp',
|
||||
'../tests/MathTest.cpp',
|
||||
'../tests/Matrix44Test.cpp',
|
||||
'../tests/MatrixClipCollapseTest.cpp',
|
||||
|
173
src/core/SkMaskCache.cpp
Normal file
173
src/core/SkMaskCache.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkMaskCache.h"
|
||||
|
||||
#define CHECK_LOCAL(localCache, localName, globalName, ...) \
|
||||
((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
|
||||
|
||||
struct MaskValue {
|
||||
SkMask fMask;
|
||||
SkCachedData* fData;
|
||||
};
|
||||
|
||||
namespace {
|
||||
static unsigned gRRectBlurKeyNamespaceLabel;
|
||||
|
||||
struct RRectBlurKey : public SkResourceCache::Key {
|
||||
public:
|
||||
RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality)
|
||||
: fSigma(sigma)
|
||||
, fRRect(rrect)
|
||||
, fStyle(style)
|
||||
, fQuality(quality) {
|
||||
this->init(&gRRectBlurKeyNamespaceLabel,
|
||||
sizeof(fSigma) + sizeof(fRRect) + sizeof(fStyle) + sizeof(fQuality));
|
||||
}
|
||||
|
||||
SkScalar fSigma;
|
||||
SkRRect fRRect;
|
||||
int32_t fStyle;
|
||||
int32_t fQuality;
|
||||
};
|
||||
|
||||
struct RRectBlurRec : public SkResourceCache::Rec {
|
||||
RRectBlurRec(RRectBlurKey key, const SkMask& mask, SkCachedData* data)
|
||||
: fKey(key)
|
||||
{
|
||||
fValue.fMask = mask;
|
||||
fValue.fData = data;
|
||||
fValue.fData->attachToCacheAndRef();
|
||||
}
|
||||
~RRectBlurRec() {
|
||||
fValue.fData->detachFromCacheAndUnref();
|
||||
}
|
||||
|
||||
RRectBlurKey fKey;
|
||||
MaskValue fValue;
|
||||
|
||||
virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
|
||||
virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(*this) + fValue.fData->size(); }
|
||||
|
||||
static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) {
|
||||
const RRectBlurRec& rec = static_cast<const RRectBlurRec&>(baseRec);
|
||||
MaskValue* result = (MaskValue*)contextData;
|
||||
|
||||
SkCachedData* tmpData = rec.fValue.fData;
|
||||
tmpData->ref();
|
||||
if (NULL == tmpData->data()) {
|
||||
tmpData->unref();
|
||||
return false;
|
||||
}
|
||||
*result = rec.fValue;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style,
|
||||
SkBlurQuality quality, SkMask* mask,
|
||||
SkResourceCache* localCache) {
|
||||
MaskValue result;
|
||||
RRectBlurKey key(sigma, rrect, style, quality);
|
||||
if (!CHECK_LOCAL(localCache, find, Find, key, RRectBlurRec::Visitor, &result)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*mask = result.fMask;
|
||||
mask->fImage = (uint8_t*)(result.fData->data());
|
||||
return result.fData;
|
||||
}
|
||||
|
||||
void SkMaskCache::Add(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style,
|
||||
SkBlurQuality quality, const SkMask& mask, SkCachedData* data,
|
||||
SkResourceCache* localCache) {
|
||||
RRectBlurKey key(sigma, rrect, style, quality);
|
||||
return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RRectBlurRec, (key, mask, data)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
static unsigned gRectsBlurKeyNamespaceLabel;
|
||||
|
||||
struct RectsBlurKey : public SkResourceCache::Key {
|
||||
public:
|
||||
RectsBlurKey(SkScalar sigma, int count, const SkRect rects[], SkBlurStyle style)
|
||||
: fSigma(sigma)
|
||||
, fRecCount(count)
|
||||
, fStyle(style){
|
||||
SkASSERT(1 == count || 2 == count);
|
||||
fRects[0] = SkRect::MakeEmpty();
|
||||
fRects[1] = SkRect::MakeEmpty();
|
||||
for (int i = 0; i < count; i++) {
|
||||
fRects[i] = rects[i];
|
||||
}
|
||||
this->init(&gRectsBlurKeyNamespaceLabel,
|
||||
sizeof(fSigma) + sizeof(fRecCount) + sizeof(fRects) + sizeof(fStyle));
|
||||
}
|
||||
|
||||
SkScalar fSigma;
|
||||
int fRecCount;
|
||||
SkRect fRects[2];
|
||||
int32_t fStyle;
|
||||
};
|
||||
|
||||
struct RectsBlurRec : public SkResourceCache::Rec {
|
||||
RectsBlurRec(RectsBlurKey key, const SkMask& mask, SkCachedData* data)
|
||||
: fKey(key)
|
||||
{
|
||||
fValue.fMask = mask;
|
||||
fValue.fData = data;
|
||||
fValue.fData->attachToCacheAndRef();
|
||||
}
|
||||
~RectsBlurRec() {
|
||||
fValue.fData->detachFromCacheAndUnref();
|
||||
}
|
||||
|
||||
RectsBlurKey fKey;
|
||||
MaskValue fValue;
|
||||
|
||||
virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
|
||||
virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(*this) + fValue.fData->size(); }
|
||||
|
||||
static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) {
|
||||
const RectsBlurRec& rec = static_cast<const RectsBlurRec&>(baseRec);
|
||||
MaskValue* result = (MaskValue*)contextData;
|
||||
|
||||
SkCachedData* tmpData = rec.fValue.fData;
|
||||
tmpData->ref();
|
||||
if (NULL == tmpData->data()) {
|
||||
tmpData->unref();
|
||||
return false;
|
||||
}
|
||||
*result = rec.fValue;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRect rects[], int count,
|
||||
SkBlurStyle style, SkMask* mask,
|
||||
SkResourceCache* localCache) {
|
||||
MaskValue result;
|
||||
RectsBlurKey key(sigma, count, rects, style);
|
||||
if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*mask = result.fMask;
|
||||
mask->fImage = (uint8_t*)(result.fData->data());
|
||||
return result.fData;
|
||||
}
|
||||
|
||||
void SkMaskCache::Add(SkScalar sigma, const SkRect rects[], int count, SkBlurStyle style,
|
||||
const SkMask& mask, SkCachedData* data,
|
||||
SkResourceCache* localCache) {
|
||||
RectsBlurKey key(sigma, count, rects, style);
|
||||
return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RectsBlurRec, (key, mask, data)));
|
||||
}
|
42
src/core/SkMaskCache.h
Normal file
42
src/core/SkMaskCache.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkMaskCache_DEFINED
|
||||
#define SkMaskCache_DEFINED
|
||||
|
||||
#include "SkBlurTypes.h"
|
||||
#include "SkCachedData.h"
|
||||
#include "SkMask.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "SkRRect.h"
|
||||
|
||||
class SkMaskCache {
|
||||
public:
|
||||
/**
|
||||
* On success, return a ref to the SkCachedData that holds the pixels, and have mask
|
||||
* already point to that memory.
|
||||
*
|
||||
* On failure, return NULL.
|
||||
*/
|
||||
static SkCachedData* FindAndRef(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style,
|
||||
SkBlurQuality quality, SkMask* mask,
|
||||
SkResourceCache* localCache = NULL);
|
||||
static SkCachedData* FindAndRef(SkScalar sigma, const SkRect rects[], int count,
|
||||
SkBlurStyle style,SkMask* mask,
|
||||
SkResourceCache* localCache = NULL);
|
||||
|
||||
/**
|
||||
* Add a mask and its pixel-data to the cache.
|
||||
*/
|
||||
static void Add(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality,
|
||||
const SkMask& mask, SkCachedData* data, SkResourceCache* localCache = NULL);
|
||||
static void Add(SkScalar sigma, const SkRect rects[], int count, SkBlurStyle style,
|
||||
const SkMask& mask, SkCachedData* data, SkResourceCache* localCache = NULL);
|
||||
};
|
||||
|
||||
#endif
|
@ -303,6 +303,15 @@ size_t SkResourceCache::setTotalByteLimit(size_t newLimit) {
|
||||
return prevLimit;
|
||||
}
|
||||
|
||||
SkCachedData* SkResourceCache::newCachedData(size_t bytes) {
|
||||
if (fDiscardableFactory) {
|
||||
SkDiscardableMemory* dm = fDiscardableFactory(bytes);
|
||||
return dm ? SkNEW_ARGS(SkCachedData, (bytes, dm)) : NULL;
|
||||
} else {
|
||||
return SkNEW_ARGS(SkCachedData, (sk_malloc_throw(bytes), bytes));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkResourceCache::detach(Rec* rec) {
|
||||
@ -482,6 +491,11 @@ SkBitmap::Allocator* SkResourceCache::GetAllocator() {
|
||||
return get_cache()->allocator();
|
||||
}
|
||||
|
||||
SkCachedData* SkResourceCache::NewCachedData(size_t bytes) {
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
return get_cache()->newCachedData(bytes);
|
||||
}
|
||||
|
||||
void SkResourceCache::Dump() {
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
get_cache()->dump();
|
||||
|
@ -137,6 +137,8 @@ public:
|
||||
*/
|
||||
static SkBitmap::Allocator* GetAllocator();
|
||||
|
||||
static SkCachedData* NewCachedData(size_t bytes);
|
||||
|
||||
/**
|
||||
* Call SkDebugf() with diagnostic information about the state of the cache
|
||||
*/
|
||||
|
105
tests/MaskCacheTest.cpp
Normal file
105
tests/MaskCacheTest.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkCachedData.h"
|
||||
#include "SkMaskCache.h"
|
||||
#include "SkResourceCache.h"
|
||||
#include "Test.h"
|
||||
|
||||
enum LockedState {
|
||||
kUnlocked,
|
||||
kLocked,
|
||||
};
|
||||
|
||||
enum CachedState {
|
||||
kNotInCache,
|
||||
kInCache,
|
||||
};
|
||||
|
||||
static void check_data(skiatest::Reporter* reporter, SkCachedData* data,
|
||||
int refcnt, CachedState cacheState, LockedState lockedState) {
|
||||
REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
|
||||
REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
|
||||
bool isLocked = (data->data() != NULL);
|
||||
REPORTER_ASSERT(reporter, isLocked == (lockedState == kLocked));
|
||||
}
|
||||
|
||||
DEF_TEST(RRectMaskCache, reporter) {
|
||||
SkResourceCache cache(1024);
|
||||
|
||||
SkScalar sigma = 0.8f;
|
||||
SkRect rect = SkRect::MakeWH(100, 100);
|
||||
SkRRect rrect;
|
||||
rrect.setRectXY(rect, 30, 30);
|
||||
SkBlurStyle style = kNormal_SkBlurStyle;
|
||||
SkBlurQuality quality = kLow_SkBlurQuality;
|
||||
SkMask mask;
|
||||
|
||||
SkCachedData* data = SkMaskCache::FindAndRef(sigma, rrect, style, quality, &mask, &cache);
|
||||
REPORTER_ASSERT(reporter, NULL == data);
|
||||
|
||||
size_t size = 256;
|
||||
data = cache.newCachedData(size);
|
||||
memset(data->writable_data(), 0xff, size);
|
||||
mask.fBounds.setXYWH(0, 0, 100, 100);
|
||||
mask.fRowBytes = 100;
|
||||
mask.fFormat = SkMask::kBW_Format;
|
||||
SkMaskCache::Add(sigma, rrect, style, quality, mask, data, &cache);
|
||||
check_data(reporter, data, 2, kInCache, kLocked);
|
||||
|
||||
data->unref();
|
||||
check_data(reporter, data, 1, kInCache, kUnlocked);
|
||||
|
||||
sk_bzero(&mask, sizeof(mask));
|
||||
data = SkMaskCache::FindAndRef(sigma, rrect, style, quality, &mask, &cache);
|
||||
REPORTER_ASSERT(reporter, data);
|
||||
REPORTER_ASSERT(reporter, data->size() == size);
|
||||
REPORTER_ASSERT(reporter, mask.fBounds.top() == 0 && mask.fBounds.bottom() == 100);
|
||||
REPORTER_ASSERT(reporter, data->data() == (const void*)mask.fImage);
|
||||
check_data(reporter, data, 2, kInCache, kLocked);
|
||||
|
||||
cache.purgeAll();
|
||||
check_data(reporter, data, 1, kNotInCache, kLocked);
|
||||
data->unref();
|
||||
}
|
||||
|
||||
DEF_TEST(RectsMaskCache, reporter) {
|
||||
SkResourceCache cache(1024);
|
||||
|
||||
SkScalar sigma = 0.8f;
|
||||
SkRect rect = SkRect::MakeWH(100, 100);
|
||||
SkRect rects[2] = {rect};
|
||||
SkBlurStyle style = kNormal_SkBlurStyle;
|
||||
SkMask mask;
|
||||
|
||||
SkCachedData* data = SkMaskCache::FindAndRef(sigma, rects, 1, style, &mask, &cache);
|
||||
REPORTER_ASSERT(reporter, NULL == data);
|
||||
|
||||
size_t size = 256;
|
||||
data = cache.newCachedData(size);
|
||||
memset(data->writable_data(), 0xff, size);
|
||||
mask.fBounds.setXYWH(0, 0, 100, 100);
|
||||
mask.fRowBytes = 100;
|
||||
mask.fFormat = SkMask::kBW_Format;
|
||||
SkMaskCache::Add(sigma, rects, 1, style, mask, data, &cache);
|
||||
check_data(reporter, data, 2, kInCache, kLocked);
|
||||
|
||||
data->unref();
|
||||
check_data(reporter, data, 1, kInCache, kUnlocked);
|
||||
|
||||
sk_bzero(&mask, sizeof(mask));
|
||||
data = SkMaskCache::FindAndRef(sigma, rects, 1, style, &mask, &cache);
|
||||
REPORTER_ASSERT(reporter, data);
|
||||
REPORTER_ASSERT(reporter, data->size() == size);
|
||||
REPORTER_ASSERT(reporter, mask.fBounds.top() == 0 && mask.fBounds.bottom() == 100);
|
||||
REPORTER_ASSERT(reporter, data->data() == (const void*)mask.fImage);
|
||||
check_data(reporter, data, 2, kInCache, kLocked);
|
||||
|
||||
cache.purgeAll();
|
||||
check_data(reporter, data, 1, kNotInCache, kLocked);
|
||||
data->unref();
|
||||
}
|
Loading…
Reference in New Issue
Block a user