| 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" |
| 9 | 10 |
| 10 #include "SkBitmap.h" | 11 #include "SkBitmap.h" |
| 11 #include "SkBitmapDevice.h" | 12 #include "SkBitmapDevice.h" |
| 12 #include "SkChecksum.h" | 13 #include "SkChecksum.h" |
| 13 #include "SkDevice.h" | 14 #include "SkDevice.h" |
| 14 #include "SkLocalMatrixImageFilter.h" | 15 #include "SkLocalMatrixImageFilter.h" |
| 15 #include "SkMatrixImageFilter.h" | 16 #include "SkMatrixImageFilter.h" |
| 16 #include "SkOncePtr.h" | 17 #include "SkOncePtr.h" |
| 17 #include "SkReadBuffer.h" | 18 #include "SkReadBuffer.h" |
| 18 #include "SkRect.h" | 19 #include "SkRect.h" |
| 20 #include "SkSpecialImage.h" |
| 19 #include "SkTDynamicHash.h" | 21 #include "SkTDynamicHash.h" |
| 20 #include "SkTInternalLList.h" | 22 #include "SkTInternalLList.h" |
| 21 #include "SkValidationUtils.h" | 23 #include "SkValidationUtils.h" |
| 22 #include "SkWriteBuffer.h" | 24 #include "SkWriteBuffer.h" |
| 23 #if SK_SUPPORT_GPU | 25 #if SK_SUPPORT_GPU |
| 24 #include "GrContext.h" | 26 #include "GrContext.h" |
| 25 #include "GrDrawContext.h" | 27 #include "GrDrawContext.h" |
| 26 #include "SkGrPixelRef.h" | 28 #include "SkGrPixelRef.h" |
| 27 #include "SkGr.h" | 29 #include "SkGr.h" |
| 28 #endif | 30 #endif |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 static int32_t gImageFilterUniqueID; | 97 static int32_t gImageFilterUniqueID; |
| 96 | 98 |
| 97 // Never return 0. | 99 // Never return 0. |
| 98 int32_t id; | 100 int32_t id; |
| 99 do { | 101 do { |
| 100 id = sk_atomic_inc(&gImageFilterUniqueID) + 1; | 102 id = sk_atomic_inc(&gImageFilterUniqueID) + 1; |
| 101 } while (0 == id); | 103 } while (0 == id); |
| 102 return id; | 104 return id; |
| 103 } | 105 } |
| 104 | 106 |
| 105 struct SkImageFilter::Cache::Key { | |
| 106 Key(const uint32_t uniqueID, const SkMatrix& matrix, const SkIRect& clipBoun
ds, uint32_t srcGenID) | |
| 107 : fUniqueID(uniqueID), fMatrix(matrix), fClipBounds(clipBounds), fSrcGenID
(srcGenID) { | |
| 108 // Assert that Key is tightly-packed, since it is hashed. | |
| 109 static_assert(sizeof(Key) == sizeof(uint32_t) + sizeof(SkMatrix) + sizeo
f(SkIRect) + | |
| 110 sizeof(uint32_t), "image_filter_key_tight_p
acking"); | |
| 111 fMatrix.getType(); // force initialization of type, so hashes match | |
| 112 } | |
| 113 uint32_t fUniqueID; | |
| 114 SkMatrix fMatrix; | |
| 115 SkIRect fClipBounds; | |
| 116 uint32_t fSrcGenID; | |
| 117 bool operator==(const Key& other) const { | |
| 118 return fUniqueID == other.fUniqueID | |
| 119 && fMatrix == other.fMatrix | |
| 120 && fClipBounds == other.fClipBounds | |
| 121 && fSrcGenID == other.fSrcGenID; | |
| 122 } | |
| 123 }; | |
| 124 | |
| 125 SkImageFilter::Common::~Common() { | 107 SkImageFilter::Common::~Common() { |
| 126 for (int i = 0; i < fInputs.count(); ++i) { | 108 for (int i = 0; i < fInputs.count(); ++i) { |
| 127 SkSafeUnref(fInputs[i]); | 109 SkSafeUnref(fInputs[i]); |
| 128 } | 110 } |
| 129 } | 111 } |
| 130 | 112 |
| 131 void SkImageFilter::Common::allocInputs(int count) { | 113 void SkImageFilter::Common::allocInputs(int count) { |
| 132 const size_t size = count * sizeof(SkImageFilter*); | 114 const size_t size = count * sizeof(SkImageFilter*); |
| 133 fInputs.reset(count); | 115 fInputs.reset(count); |
| 134 sk_bzero(fInputs.get(), size); | 116 sk_bzero(fInputs.get(), size); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 buffer.writeRect(fCropRect.rect()); | 212 buffer.writeRect(fCropRect.rect()); |
| 231 buffer.writeUInt(fCropRect.flags()); | 213 buffer.writeUInt(fCropRect.flags()); |
| 232 } | 214 } |
| 233 | 215 |
| 234 bool SkImageFilter::filterImageDeprecated(Proxy* proxy, const SkBitmap& src, | 216 bool SkImageFilter::filterImageDeprecated(Proxy* proxy, const SkBitmap& src, |
| 235 const Context& context, | 217 const Context& context, |
| 236 SkBitmap* result, SkIPoint* offset) co
nst { | 218 SkBitmap* result, SkIPoint* offset) co
nst { |
| 237 SkASSERT(result); | 219 SkASSERT(result); |
| 238 SkASSERT(offset); | 220 SkASSERT(offset); |
| 239 uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0; | 221 uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0; |
| 240 Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID); | 222 Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), |
| 223 srcGenID, SkIRect::MakeWH(0, 0)); |
| 241 if (context.cache()) { | 224 if (context.cache()) { |
| 242 if (context.cache()->get(key, result, offset)) { | 225 if (context.cache()->get(key, result, offset)) { |
| 243 return true; | 226 return true; |
| 244 } | 227 } |
| 245 } | 228 } |
| 246 /* | 229 /* |
| 247 * Give the proxy first shot at the filter. If it returns false, ask | 230 * Give the proxy first shot at the filter. If it returns false, ask |
| 248 * the filter to do it. | 231 * the filter to do it. |
| 249 */ | 232 */ |
| 250 if ((proxy && proxy->filterImage(this, src, context, result, offset)) || | 233 if ((proxy && proxy->filterImage(this, src, context, result, offset)) || |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 } else { | 507 } else { |
| 525 return false; | 508 return false; |
| 526 } | 509 } |
| 527 } | 510 } |
| 528 #endif | 511 #endif |
| 529 | 512 |
| 530 namespace { | 513 namespace { |
| 531 | 514 |
| 532 class CacheImpl : public SkImageFilter::Cache { | 515 class CacheImpl : public SkImageFilter::Cache { |
| 533 public: | 516 public: |
| 534 CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) { | 517 CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) { } |
| 535 } | 518 ~CacheImpl() override { |
| 536 virtual ~CacheImpl() { | |
| 537 SkTDynamicHash<Value, Key>::Iter iter(&fLookup); | 519 SkTDynamicHash<Value, Key>::Iter iter(&fLookup); |
| 538 | 520 |
| 539 while (!iter.done()) { | 521 while (!iter.done()) { |
| 540 Value* v = &*iter; | 522 Value* v = &*iter; |
| 541 ++iter; | 523 ++iter; |
| 542 delete v; | 524 delete v; |
| 543 } | 525 } |
| 544 } | 526 } |
| 545 struct Value { | 527 struct Value { |
| 546 Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset) | 528 Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset) |
| 547 : fKey(key), fBitmap(bitmap), fOffset(offset) {} | 529 : fKey(key), fBitmap(bitmap), fOffset(offset) {} |
| 530 Value(const Key& key, SkSpecialImage* image, const SkIPoint& offset) |
| 531 : fKey(key), fImage(SkRef(image)), fOffset(offset) {} |
| 532 |
| 548 Key fKey; | 533 Key fKey; |
| 549 SkBitmap fBitmap; | 534 SkBitmap fBitmap; |
| 535 SkAutoTUnref<SkSpecialImage> fImage; |
| 550 SkIPoint fOffset; | 536 SkIPoint fOffset; |
| 551 static const Key& GetKey(const Value& v) { | 537 static const Key& GetKey(const Value& v) { |
| 552 return v.fKey; | 538 return v.fKey; |
| 553 } | 539 } |
| 554 static uint32_t Hash(const Key& key) { | 540 static uint32_t Hash(const Key& key) { |
| 555 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key),
sizeof(Key)); | 541 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key),
sizeof(Key)); |
| 556 } | 542 } |
| 557 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value); | 543 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value); |
| 558 }; | 544 }; |
| 545 |
| 559 bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const override
{ | 546 bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const override
{ |
| 560 SkAutoMutexAcquire mutex(fMutex); | 547 SkAutoMutexAcquire mutex(fMutex); |
| 561 if (Value* v = fLookup.find(key)) { | 548 if (Value* v = fLookup.find(key)) { |
| 562 *result = v->fBitmap; | 549 *result = v->fBitmap; |
| 563 *offset = v->fOffset; | 550 *offset = v->fOffset; |
| 564 if (v != fLRU.head()) { | 551 if (v != fLRU.head()) { |
| 565 fLRU.remove(v); | 552 fLRU.remove(v); |
| 566 fLRU.addToHead(v); | 553 fLRU.addToHead(v); |
| 567 } | 554 } |
| 568 return true; | 555 return true; |
| 569 } | 556 } |
| 570 return false; | 557 return false; |
| 571 } | 558 } |
| 559 |
| 560 SkSpecialImage* get(const Key& key, SkIPoint* offset) const override { |
| 561 SkAutoMutexAcquire mutex(fMutex); |
| 562 if (Value* v = fLookup.find(key)) { |
| 563 *offset = v->fOffset; |
| 564 if (v != fLRU.head()) { |
| 565 fLRU.remove(v); |
| 566 fLRU.addToHead(v); |
| 567 } |
| 568 return v->fImage; |
| 569 } |
| 570 return nullptr; |
| 571 } |
| 572 |
| 572 void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) ove
rride { | 573 void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) ove
rride { |
| 573 SkAutoMutexAcquire mutex(fMutex); | 574 SkAutoMutexAcquire mutex(fMutex); |
| 574 if (Value* v = fLookup.find(key)) { | 575 if (Value* v = fLookup.find(key)) { |
| 575 removeInternal(v); | 576 this->removeInternal(v); |
| 576 } | 577 } |
| 577 Value* v = new Value(key, result, offset); | 578 Value* v = new Value(key, result, offset); |
| 578 fLookup.add(v); | 579 fLookup.add(v); |
| 579 fLRU.addToHead(v); | 580 fLRU.addToHead(v); |
| 580 fCurrentBytes += result.getSize(); | 581 fCurrentBytes += result.getSize(); |
| 581 while (fCurrentBytes > fMaxBytes) { | 582 while (fCurrentBytes > fMaxBytes) { |
| 582 Value* tail = fLRU.tail(); | 583 Value* tail = fLRU.tail(); |
| 583 SkASSERT(tail); | 584 SkASSERT(tail); |
| 584 if (tail == v) { | 585 if (tail == v) { |
| 585 break; | 586 break; |
| 586 } | 587 } |
| 587 removeInternal(tail); | 588 this->removeInternal(tail); |
| 588 } | 589 } |
| 589 } | 590 } |
| 590 | 591 |
| 592 void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) over
ride { |
| 593 SkAutoMutexAcquire mutex(fMutex); |
| 594 if (Value* v = fLookup.find(key)) { |
| 595 this->removeInternal(v); |
| 596 } |
| 597 Value* v = new Value(key, image, offset); |
| 598 fLookup.add(v); |
| 599 fLRU.addToHead(v); |
| 600 fCurrentBytes += image->getSize(); |
| 601 while (fCurrentBytes > fMaxBytes) { |
| 602 Value* tail = fLRU.tail(); |
| 603 SkASSERT(tail); |
| 604 if (tail == v) { |
| 605 break; |
| 606 } |
| 607 this->removeInternal(tail); |
| 608 } |
| 609 } |
| 610 |
| 591 void purge() override { | 611 void purge() override { |
| 592 SkAutoMutexAcquire mutex(fMutex); | 612 SkAutoMutexAcquire mutex(fMutex); |
| 593 while (fCurrentBytes > 0) { | 613 while (fCurrentBytes > 0) { |
| 594 Value* tail = fLRU.tail(); | 614 Value* tail = fLRU.tail(); |
| 595 SkASSERT(tail); | 615 SkASSERT(tail); |
| 596 this->removeInternal(tail); | 616 this->removeInternal(tail); |
| 597 } | 617 } |
| 598 } | 618 } |
| 599 | 619 |
| 600 void purgeByKeys(const Key keys[], int count) override { | 620 void purgeByKeys(const Key keys[], int count) override { |
| 601 SkAutoMutexAcquire mutex(fMutex); | 621 SkAutoMutexAcquire mutex(fMutex); |
| 602 for (int i = 0; i < count; i++) { | 622 for (int i = 0; i < count; i++) { |
| 603 if (Value* v = fLookup.find(keys[i])) { | 623 if (Value* v = fLookup.find(keys[i])) { |
| 604 this->removeInternal(v); | 624 this->removeInternal(v); |
| 605 } | 625 } |
| 606 } | 626 } |
| 607 } | 627 } |
| 608 | 628 |
| 609 private: | 629 private: |
| 610 void removeInternal(Value* v) { | 630 void removeInternal(Value* v) { |
| 611 fCurrentBytes -= v->fBitmap.getSize(); | 631 if (v->fImage) { |
| 632 fCurrentBytes -= v->fImage->getSize(); |
| 633 } else { |
| 634 fCurrentBytes -= v->fBitmap.getSize(); |
| 635 } |
| 612 fLRU.remove(v); | 636 fLRU.remove(v); |
| 613 fLookup.remove(v->fKey); | 637 fLookup.remove(v->fKey); |
| 614 delete v; | 638 delete v; |
| 615 } | 639 } |
| 616 private: | 640 private: |
| 617 SkTDynamicHash<Value, Key> fLookup; | 641 SkTDynamicHash<Value, Key> fLookup; |
| 618 mutable SkTInternalLList<Value> fLRU; | 642 mutable SkTInternalLList<Value> fLRU; |
| 619 size_t fMaxBytes; | 643 size_t fMaxBytes; |
| 620 size_t fCurrentBytes; | 644 size_t fCurrentBytes; |
| 621 mutable SkMutex fMutex; | 645 mutable SkMutex fMutex; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 } | 677 } |
| 654 return dev; | 678 return dev; |
| 655 } | 679 } |
| 656 | 680 |
| 657 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, | 681 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, |
| 658 const SkImageFilter::Context& ctx, | 682 const SkImageFilter::Context& ctx, |
| 659 SkBitmap* result, SkIPoint* offset) { | 683 SkBitmap* result, SkIPoint* offset) { |
| 660 return fDevice->filterImage(filter, src, ctx, result, offset); | 684 return fDevice->filterImage(filter, src, ctx, result, offset); |
| 661 } | 685 } |
| 662 | 686 |
| OLD | NEW |