| 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 #include "SkImageFilterCacheKey.h" | |
| 10 | 9 |
| 11 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| 12 #include "SkChecksum.h" | |
| 13 #include "SkFuzzLogging.h" | 11 #include "SkFuzzLogging.h" |
| 12 #include "SkImageFilterCache.h" |
| 14 #include "SkLocalMatrixImageFilter.h" | 13 #include "SkLocalMatrixImageFilter.h" |
| 15 #include "SkMatrixImageFilter.h" | 14 #include "SkMatrixImageFilter.h" |
| 16 #include "SkOncePtr.h" | |
| 17 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
| 18 #include "SkRect.h" | 16 #include "SkRect.h" |
| 19 #include "SkSpecialImage.h" | 17 #include "SkSpecialImage.h" |
| 20 #include "SkSpecialSurface.h" | 18 #include "SkSpecialSurface.h" |
| 21 #include "SkTDynamicHash.h" | |
| 22 #include "SkTInternalLList.h" | |
| 23 #include "SkValidationUtils.h" | 19 #include "SkValidationUtils.h" |
| 24 #include "SkWriteBuffer.h" | 20 #include "SkWriteBuffer.h" |
| 25 #if SK_SUPPORT_GPU | 21 #if SK_SUPPORT_GPU |
| 26 #include "GrContext.h" | 22 #include "GrContext.h" |
| 27 #include "GrDrawContext.h" | 23 #include "GrDrawContext.h" |
| 28 #endif | 24 #endif |
| 29 | 25 |
| 30 #ifdef SK_BUILD_FOR_IOS | |
| 31 enum { kDefaultCacheSize = 2 * 1024 * 1024 }; | |
| 32 #else | |
| 33 enum { kDefaultCacheSize = 128 * 1024 * 1024 }; | |
| 34 #endif | |
| 35 | |
| 36 #ifndef SK_IGNORE_TO_STRING | 26 #ifndef SK_IGNORE_TO_STRING |
| 37 void SkImageFilter::CropRect::toString(SkString* str) const { | 27 void SkImageFilter::CropRect::toString(SkString* str) const { |
| 38 if (!fFlags) { | 28 if (!fFlags) { |
| 39 return; | 29 return; |
| 40 } | 30 } |
| 41 | 31 |
| 42 str->appendf("cropRect ("); | 32 str->appendf("cropRect ("); |
| 43 if (fFlags & CropRect::kHasLeft_CropEdge) { | 33 if (fFlags & CropRect::kHasLeft_CropEdge) { |
| 44 str->appendf("%.2f, ", fRect.fLeft); | 34 str->appendf("%.2f, ", fRect.fLeft); |
| 45 } else { | 35 } else { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 162 |
| 173 SkImageFilter::SkImageFilter(sk_sp<SkImageFilter>* inputs, | 163 SkImageFilter::SkImageFilter(sk_sp<SkImageFilter>* inputs, |
| 174 int inputCount, | 164 int inputCount, |
| 175 const CropRect* cropRect) | 165 const CropRect* cropRect) |
| 176 : fUsesSrcInput(false) | 166 : fUsesSrcInput(false) |
| 177 , fUniqueID(next_image_filter_unique_id()) { | 167 , fUniqueID(next_image_filter_unique_id()) { |
| 178 this->init(inputs, inputCount, cropRect); | 168 this->init(inputs, inputCount, cropRect); |
| 179 } | 169 } |
| 180 | 170 |
| 181 SkImageFilter::~SkImageFilter() { | 171 SkImageFilter::~SkImageFilter() { |
| 182 Cache::Get()->purgeByKeys(fCacheKeys.begin(), fCacheKeys.count()); | 172 SkImageFilterCache::Get()->purgeByKeys(fCacheKeys.begin(), fCacheKeys.count(
)); |
| 183 } | 173 } |
| 184 | 174 |
| 185 SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) | 175 SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) |
| 186 : fUsesSrcInput(false) | 176 : fUsesSrcInput(false) |
| 187 , fCropRect(SkRect(), 0x0) | 177 , fCropRect(SkRect(), 0x0) |
| 188 , fUniqueID(next_image_filter_unique_id()) { | 178 , fUniqueID(next_image_filter_unique_id()) { |
| 189 Common common; | 179 Common common; |
| 190 if (common.unflatten(buffer, inputCount)) { | 180 if (common.unflatten(buffer, inputCount)) { |
| 191 this->init(common.inputs(), common.inputCount(), &common.cropRect()); | 181 this->init(common.inputs(), common.inputCount(), &common.cropRect()); |
| 192 } | 182 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 204 buffer.writeRect(fCropRect.rect()); | 194 buffer.writeRect(fCropRect.rect()); |
| 205 buffer.writeUInt(fCropRect.flags()); | 195 buffer.writeUInt(fCropRect.flags()); |
| 206 } | 196 } |
| 207 | 197 |
| 208 sk_sp<SkSpecialImage> SkImageFilter::filterImage(SkSpecialImage* src, const Cont
ext& context, | 198 sk_sp<SkSpecialImage> SkImageFilter::filterImage(SkSpecialImage* src, const Cont
ext& context, |
| 209 SkIPoint* offset) const { | 199 SkIPoint* offset) const { |
| 210 SkASSERT(src && offset); | 200 SkASSERT(src && offset); |
| 211 | 201 |
| 212 uint32_t srcGenID = fUsesSrcInput ? src->uniqueID() : 0; | 202 uint32_t srcGenID = fUsesSrcInput ? src->uniqueID() : 0; |
| 213 const SkIRect srcSubset = fUsesSrcInput ? src->subset() : SkIRect::MakeWH(0,
0); | 203 const SkIRect srcSubset = fUsesSrcInput ? src->subset() : SkIRect::MakeWH(0,
0); |
| 214 Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID, src
Subset); | 204 SkImageFilterCacheKey key(fUniqueID, context.ctm(), context.clipBounds(), sr
cGenID, srcSubset); |
| 215 if (context.cache()) { | 205 if (context.cache()) { |
| 216 SkSpecialImage* result = context.cache()->get(key, offset); | 206 SkSpecialImage* result = context.cache()->get(key, offset); |
| 217 if (result) { | 207 if (result) { |
| 218 return sk_sp<SkSpecialImage>(SkRef(result)); | 208 return sk_sp<SkSpecialImage>(SkRef(result)); |
| 219 } | 209 } |
| 220 } | 210 } |
| 221 | 211 |
| 222 sk_sp<SkSpecialImage> result(this->onFilterImage(src, context, offset)); | 212 sk_sp<SkSpecialImage> result(this->onFilterImage(src, context, offset)); |
| 223 | 213 |
| 224 #if SK_SUPPORT_GPU | 214 #if SK_SUPPORT_GPU |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 return sk_sp<SkSpecialImage>(SkRef(src)); | 445 return sk_sp<SkSpecialImage>(SkRef(src)); |
| 456 } | 446 } |
| 457 | 447 |
| 458 sk_sp<SkSpecialImage> result(input->filterImage(src, this->mapContext(ctx),
offset)); | 448 sk_sp<SkSpecialImage> result(input->filterImage(src, this->mapContext(ctx),
offset)); |
| 459 | 449 |
| 460 SkASSERT(!result || src->isTextureBacked() == result->isTextureBacked()); | 450 SkASSERT(!result || src->isTextureBacked() == result->isTextureBacked()); |
| 461 | 451 |
| 462 return result; | 452 return result; |
| 463 } | 453 } |
| 464 | 454 |
| 465 namespace { | 455 void SkImageFilter::PurgeCache() { |
| 466 | 456 SkImageFilterCache::Get()->purge(); |
| 467 class CacheImpl : public SkImageFilter::Cache { | |
| 468 public: | |
| 469 CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) { } | |
| 470 ~CacheImpl() override { | |
| 471 SkTDynamicHash<Value, Key>::Iter iter(&fLookup); | |
| 472 | |
| 473 while (!iter.done()) { | |
| 474 Value* v = &*iter; | |
| 475 ++iter; | |
| 476 delete v; | |
| 477 } | |
| 478 } | |
| 479 struct Value { | |
| 480 Value(const Key& key, SkSpecialImage* image, const SkIPoint& offset) | |
| 481 : fKey(key), fImage(SkRef(image)), fOffset(offset) {} | |
| 482 | |
| 483 Key fKey; | |
| 484 SkAutoTUnref<SkSpecialImage> fImage; | |
| 485 SkIPoint fOffset; | |
| 486 static const Key& GetKey(const Value& v) { | |
| 487 return v.fKey; | |
| 488 } | |
| 489 static uint32_t Hash(const Key& key) { | |
| 490 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key),
sizeof(Key)); | |
| 491 } | |
| 492 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value); | |
| 493 }; | |
| 494 | |
| 495 SkSpecialImage* get(const Key& key, SkIPoint* offset) const override { | |
| 496 SkAutoMutexAcquire mutex(fMutex); | |
| 497 if (Value* v = fLookup.find(key)) { | |
| 498 *offset = v->fOffset; | |
| 499 if (v != fLRU.head()) { | |
| 500 fLRU.remove(v); | |
| 501 fLRU.addToHead(v); | |
| 502 } | |
| 503 return v->fImage; | |
| 504 } | |
| 505 return nullptr; | |
| 506 } | |
| 507 | |
| 508 void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) over
ride { | |
| 509 SkAutoMutexAcquire mutex(fMutex); | |
| 510 if (Value* v = fLookup.find(key)) { | |
| 511 this->removeInternal(v); | |
| 512 } | |
| 513 Value* v = new Value(key, image, offset); | |
| 514 fLookup.add(v); | |
| 515 fLRU.addToHead(v); | |
| 516 fCurrentBytes += image->getSize(); | |
| 517 while (fCurrentBytes > fMaxBytes) { | |
| 518 Value* tail = fLRU.tail(); | |
| 519 SkASSERT(tail); | |
| 520 if (tail == v) { | |
| 521 break; | |
| 522 } | |
| 523 this->removeInternal(tail); | |
| 524 } | |
| 525 } | |
| 526 | |
| 527 void purge() override { | |
| 528 SkAutoMutexAcquire mutex(fMutex); | |
| 529 while (fCurrentBytes > 0) { | |
| 530 Value* tail = fLRU.tail(); | |
| 531 SkASSERT(tail); | |
| 532 this->removeInternal(tail); | |
| 533 } | |
| 534 } | |
| 535 | |
| 536 void purgeByKeys(const Key keys[], int count) override { | |
| 537 SkAutoMutexAcquire mutex(fMutex); | |
| 538 for (int i = 0; i < count; i++) { | |
| 539 if (Value* v = fLookup.find(keys[i])) { | |
| 540 this->removeInternal(v); | |
| 541 } | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 SkDEBUGCODE(int count() const override { return fLookup.count(); }) | |
| 546 private: | |
| 547 void removeInternal(Value* v) { | |
| 548 SkASSERT(v->fImage); | |
| 549 fCurrentBytes -= v->fImage->getSize(); | |
| 550 fLRU.remove(v); | |
| 551 fLookup.remove(v->fKey); | |
| 552 delete v; | |
| 553 } | |
| 554 private: | |
| 555 SkTDynamicHash<Value, Key> fLookup; | |
| 556 mutable SkTInternalLList<Value> fLRU; | |
| 557 size_t fMaxBytes; | |
| 558 size_t fCurrentBytes; | |
| 559 mutable SkMutex fMutex; | |
| 560 }; | |
| 561 | |
| 562 } // namespace | |
| 563 | |
| 564 SkImageFilter::Cache* SkImageFilter::Cache::Create(size_t maxBytes) { | |
| 565 return new CacheImpl(maxBytes); | |
| 566 } | 457 } |
| 567 | |
| 568 SK_DECLARE_STATIC_ONCE_PTR(SkImageFilter::Cache, cache); | |
| 569 SkImageFilter::Cache* SkImageFilter::Cache::Get() { | |
| 570 return cache.get([]{ return SkImageFilter::Cache::Create(kDefaultCacheSize);
}); | |
| 571 } | |
| 572 | |
| 573 void SkImageFilter::PurgeCache() { | |
| 574 Cache::Get()->purge(); | |
| 575 } | |
| 576 | |
| OLD | NEW |