Chromium Code Reviews| Index: src/core/SkImageFilter.cpp |
| diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp |
| index 2be66e787c5c6efba9148de9884c3e26a85b012f..8d0c22de285a51ac5de63483233507d8533725a1 100644 |
| --- a/src/core/SkImageFilter.cpp |
| +++ b/src/core/SkImageFilter.cpp |
| @@ -12,6 +12,7 @@ |
| #include "SkReadBuffer.h" |
| #include "SkWriteBuffer.h" |
| #include "SkRect.h" |
| +#include "SkTDynamicHash.h" |
| #include "SkValidationUtils.h" |
| #if SK_SUPPORT_GPU |
| #include "GrContext.h" |
| @@ -96,14 +97,23 @@ void SkImageFilter::flatten(SkWriteBuffer& buffer) const { |
| bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, |
| const Context& context, |
| SkBitmap* result, SkIPoint* offset) const { |
| + Cache* cache = context.cache(); |
| SkASSERT(result); |
| SkASSERT(offset); |
| + SkASSERT(cache); |
| + if (cache->get(this, result, offset)) { |
| + return true; |
| + } |
| /* |
| * Give the proxy first shot at the filter. If it returns false, ask |
| * the filter to do it. |
| */ |
| - return (proxy && proxy->filterImage(this, src, context, result, offset)) || |
| - this->onFilterImage(proxy, src, context, result, offset); |
| + if ((proxy && proxy->filterImage(this, src, context, result, offset)) || |
| + this->onFilterImage(proxy, src, context, result, offset)) { |
| + cache->set(this, *result, *offset); |
| + return true; |
| + } |
| + return false; |
| } |
| bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, |
| @@ -321,3 +331,83 @@ bool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy, |
| } |
| } |
| #endif |
| + |
| +static uint32_t compute_hash(const uint32_t* data, int count) { |
| + uint32_t hash = 0; |
| + |
| + for (int i = 0; i < count; ++i) { |
| + uint32_t k = data[i]; |
| + k *= 0xcc9e2d51; |
| + k = (k << 15) | (k >> 17); |
| + k *= 0x1b873593; |
| + |
| + hash ^= k; |
| + hash = (hash << 13) | (hash >> 19); |
| + hash *= 5; |
| + hash += 0xe6546b64; |
| + } |
| + |
| + // hash ^= size; |
| + hash ^= hash >> 16; |
| + hash *= 0x85ebca6b; |
| + hash ^= hash >> 13; |
| + hash *= 0xc2b2ae35; |
| + hash ^= hash >> 16; |
| + |
| + return hash; |
| +} |
| + |
| +class CacheImpl : public SkImageFilter::Cache { |
| +public: |
| + explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {} |
| + virtual ~CacheImpl(); |
| + bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; |
| + void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE; |
| +private: |
| + typedef const SkImageFilter* Key; |
| + struct Value { |
| + Value(Key key, const SkBitmap& bitmap, const SkIPoint& offset) |
| + : fKey(key), fBitmap(bitmap), fOffset(offset) {} |
| + Key fKey; |
| + SkBitmap fBitmap; |
| + SkIPoint fOffset; |
| + static const Key& GetKey(const Value& v) { |
| + return v.fKey; |
| + } |
| + static uint32_t Hash(Key key) { |
| + return compute_hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key) / sizeof(uint32_t)); |
|
bungeman-skia
2014/04/14 16:47:48
You do realize that this is computing a hash which
Stephen White
2014/04/14 17:24:45
Unless I've messed up totally, this should just be
bungeman-skia
2014/04/14 18:05:10
Ah, I see, the Key here is SkImageFilter*, so this
|
| + } |
| + }; |
| + SkTDynamicHash<Value, Key> fData; |
| + int fMinChildren; |
| +}; |
| + |
| +bool CacheImpl::get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) { |
| + Value* v = fData.find(key); |
| + if (v) { |
| + *result = v->fBitmap; |
| + *offset = v->fOffset; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +void CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) { |
| + if (key->getRefCnt() >= fMinChildren) { |
|
bungeman-skia
2014/04/14 16:47:48
This is somewhat crazy. 'getRefCnt' is marked 'Use
Stephen White
2014/04/14 17:24:45
I think it would probably be better long-term to k
bungeman-skia
2014/04/14 18:05:10
Sure, although SkImageFilter, being SkRefCnt, is a
|
| + fData.add(new Value(key, result, offset)); |
| + } |
| +} |
| + |
| +SkImageFilter::Cache* SkImageFilter::Cache::Create(int minChildren) { |
| + return new CacheImpl(minChildren); |
| +} |
| + |
| +CacheImpl::~CacheImpl() { |
| + SkTDynamicHash<Value, Key>::Iter iter(&fData); |
| + |
| + while (!iter.done()) { |
| + Value* v = &*iter; |
| + ++iter; |
| + delete v; |
| + } |
| +} |