Chromium Code Reviews| 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 |