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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/effects/SkDropShadowImageFilter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The Android Open Source Project 2 * Copyright 2012 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkImageFilter.h" 8 #include "SkImageFilter.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkDevice.h" 11 #include "SkDevice.h"
12 #include "SkReadBuffer.h" 12 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
14 #include "SkRect.h" 14 #include "SkRect.h"
15 #include "SkTDynamicHash.h"
15 #include "SkValidationUtils.h" 16 #include "SkValidationUtils.h"
16 #if SK_SUPPORT_GPU 17 #if SK_SUPPORT_GPU
17 #include "GrContext.h" 18 #include "GrContext.h"
18 #include "SkGrPixelRef.h" 19 #include "SkGrPixelRef.h"
19 #include "SkGr.h" 20 #include "SkGr.h"
20 #endif 21 #endif
21 22
22 SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropR ect* cropRect) 23 SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropR ect* cropRect)
23 : fInputCount(inputCount), 24 : fInputCount(inputCount),
24 fInputs(new SkImageFilter*[inputCount]), 25 fInputs(new SkImageFilter*[inputCount]),
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 buffer.writeFlattenable(input); 90 buffer.writeFlattenable(input);
90 } 91 }
91 } 92 }
92 buffer.writeRect(fCropRect.rect()); 93 buffer.writeRect(fCropRect.rect());
93 buffer.writeUInt(fCropRect.flags()); 94 buffer.writeUInt(fCropRect.flags());
94 } 95 }
95 96
96 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, 97 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
97 const Context& context, 98 const Context& context,
98 SkBitmap* result, SkIPoint* offset) const { 99 SkBitmap* result, SkIPoint* offset) const {
100 Cache* cache = context.cache();
99 SkASSERT(result); 101 SkASSERT(result);
100 SkASSERT(offset); 102 SkASSERT(offset);
103 SkASSERT(cache);
104 if (cache->get(this, result, offset)) {
105 return true;
106 }
101 /* 107 /*
102 * Give the proxy first shot at the filter. If it returns false, ask 108 * Give the proxy first shot at the filter. If it returns false, ask
103 * the filter to do it. 109 * the filter to do it.
104 */ 110 */
105 return (proxy && proxy->filterImage(this, src, context, result, offset)) || 111 if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
106 this->onFilterImage(proxy, src, context, result, offset); 112 this->onFilterImage(proxy, src, context, result, offset)) {
113 cache->set(this, *result, *offset);
114 return true;
115 }
116 return false;
107 } 117 }
108 118
109 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, 119 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
110 SkIRect* dst) const { 120 SkIRect* dst) const {
111 SkASSERT(&src); 121 SkASSERT(&src);
112 SkASSERT(dst); 122 SkASSERT(dst);
113 return this->onFilterBounds(src, ctm, dst); 123 return this->onFilterBounds(src, ctm, dst);
114 } 124 }
115 125
116 void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 126 void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref(); 324 result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
315 GrUnlockAndUnrefCachedBitmapTexture(resultTex); 325 GrUnlockAndUnrefCachedBitmapTexture(resultTex);
316 } 326 }
317 return true; 327 return true;
318 } else { 328 } else {
319 return false; 329 return false;
320 } 330 }
321 } 331 }
322 } 332 }
323 #endif 333 #endif
334
335 static uint32_t compute_hash(const uint32_t* data, int count) {
336 uint32_t hash = 0;
337
338 for (int i = 0; i < count; ++i) {
339 uint32_t k = data[i];
340 k *= 0xcc9e2d51;
341 k = (k << 15) | (k >> 17);
342 k *= 0x1b873593;
343
344 hash ^= k;
345 hash = (hash << 13) | (hash >> 19);
346 hash *= 5;
347 hash += 0xe6546b64;
348 }
349
350 // hash ^= size;
351 hash ^= hash >> 16;
352 hash *= 0x85ebca6b;
353 hash ^= hash >> 13;
354 hash *= 0xc2b2ae35;
355 hash ^= hash >> 16;
356
357 return hash;
358 }
359
360 class CacheImpl : public SkImageFilter::Cache {
361 public:
362 explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {}
363 virtual ~CacheImpl();
364 bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OV ERRIDE;
365 void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& o ffset) SK_OVERRIDE;
366 private:
367 typedef const SkImageFilter* Key;
368 struct Value {
369 Value(Key key, const SkBitmap& bitmap, const SkIPoint& offset)
370 : fKey(key), fBitmap(bitmap), fOffset(offset) {}
371 Key fKey;
372 SkBitmap fBitmap;
373 SkIPoint fOffset;
374 static const Key& GetKey(const Value& v) {
375 return v.fKey;
376 }
377 static uint32_t Hash(Key key) {
378 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
379 }
380 };
381 SkTDynamicHash<Value, Key> fData;
382 int fMinChildren;
383 };
384
385 bool CacheImpl::get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset ) {
386 Value* v = fData.find(key);
387 if (v) {
388 *result = v->fBitmap;
389 *offset = v->fOffset;
390 return true;
391 }
392 return false;
393 }
394
395 void CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIP oint& offset) {
396 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
397 fData.add(new Value(key, result, offset));
398 }
399 }
400
401 SkImageFilter::Cache* SkImageFilter::Cache::Create(int minChildren) {
402 return new CacheImpl(minChildren);
403 }
404
405 CacheImpl::~CacheImpl() {
406 SkTDynamicHash<Value, Key>::Iter iter(&fData);
407
408 while (!iter.done()) {
409 Value* v = &*iter;
410 ++iter;
411 delete v;
412 }
413 }
OLDNEW
« 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