OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |