Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Unified Diff: src/core/SkImageFilter.cpp

Issue 230653005: Implement intra-frame cacheing in image filters. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Set minChildren to 2 by default; comment it. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/effects/SkDropShadowImageFilter.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
+ }
+}
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/effects/SkDropShadowImageFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698