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 "SkChecksum.h" | 11 #include "SkChecksum.h" |
12 #include "SkDevice.h" | 12 #include "SkDevice.h" |
| 13 #include "SkLazyPtr.h" |
13 #include "SkReadBuffer.h" | 14 #include "SkReadBuffer.h" |
14 #include "SkWriteBuffer.h" | 15 #include "SkWriteBuffer.h" |
15 #include "SkRect.h" | 16 #include "SkRect.h" |
16 #include "SkTDynamicHash.h" | 17 #include "SkTDynamicHash.h" |
| 18 #include "SkTInternalLList.h" |
17 #include "SkValidationUtils.h" | 19 #include "SkValidationUtils.h" |
18 #if SK_SUPPORT_GPU | 20 #if SK_SUPPORT_GPU |
19 #include "GrContext.h" | 21 #include "GrContext.h" |
20 #include "SkGrPixelRef.h" | 22 #include "SkGrPixelRef.h" |
21 #include "SkGr.h" | 23 #include "SkGr.h" |
22 #endif | 24 #endif |
23 | 25 |
| 26 enum { kDefaultCacheSize = 128 * 1024 * 1024 }; |
| 27 |
| 28 static int32_t next_image_filter_unique_id() { |
| 29 static int32_t gImageFilterUniqueID; |
| 30 |
| 31 // Never return 0. |
| 32 int32_t id; |
| 33 do { |
| 34 id = sk_atomic_inc(&gImageFilterUniqueID) + 1; |
| 35 } while (0 == id); |
| 36 return id; |
| 37 } |
| 38 |
| 39 struct SkImageFilter::UniqueIDCache::Key { |
| 40 Key(const uint32_t uniqueID, const SkMatrix& matrix, const SkIRect& clipBoun
ds, uint32_t srcGenID) |
| 41 : fUniqueID(uniqueID), fMatrix(matrix), fClipBounds(clipBounds), fSrcGenID
(srcGenID) { |
| 42 // Assert that Key is tightly-packed, since it is hashed. |
| 43 SK_COMPILE_ASSERT(sizeof(Key) == sizeof(uint32_t) + sizeof(SkMatrix) + s
izeof(SkIRect) + |
| 44 sizeof(uint32_t), image_filter_key_tigh
t_packing); |
| 45 fMatrix.getType(); // force initialization of type, so hashes match |
| 46 } |
| 47 uint32_t fUniqueID; |
| 48 SkMatrix fMatrix; |
| 49 SkIRect fClipBounds; |
| 50 uint32_t fSrcGenID; |
| 51 bool operator==(const Key& other) const { |
| 52 return fUniqueID == other.fUniqueID |
| 53 && fMatrix == other.fMatrix |
| 54 && fClipBounds == other.fClipBounds |
| 55 && fSrcGenID == other.fSrcGenID; |
| 56 } |
| 57 }; |
| 58 |
24 SkImageFilter::Common::~Common() { | 59 SkImageFilter::Common::~Common() { |
25 for (int i = 0; i < fInputs.count(); ++i) { | 60 for (int i = 0; i < fInputs.count(); ++i) { |
26 SkSafeUnref(fInputs[i]); | 61 SkSafeUnref(fInputs[i]); |
27 } | 62 } |
28 } | 63 } |
29 | 64 |
30 void SkImageFilter::Common::allocInputs(int count) { | 65 void SkImageFilter::Common::allocInputs(int count) { |
31 const size_t size = count * sizeof(SkImageFilter*); | 66 const size_t size = count * sizeof(SkImageFilter*); |
32 fInputs.reset(count); | 67 fInputs.reset(count); |
33 sk_bzero(fInputs.get(), size); | 68 sk_bzero(fInputs.get(), size); |
(...skipping 24 matching lines...) Expand all Loading... |
58 } | 93 } |
59 } | 94 } |
60 SkRect rect; | 95 SkRect rect; |
61 buffer.readRect(&rect); | 96 buffer.readRect(&rect); |
62 if (!buffer.isValid() || !buffer.validate(SkIsValidRect(rect))) { | 97 if (!buffer.isValid() || !buffer.validate(SkIsValidRect(rect))) { |
63 return false; | 98 return false; |
64 } | 99 } |
65 | 100 |
66 uint32_t flags = buffer.readUInt(); | 101 uint32_t flags = buffer.readUInt(); |
67 fCropRect = CropRect(rect, flags); | 102 fCropRect = CropRect(rect, flags); |
| 103 if (buffer.isVersionLT(SkReadBuffer::kImageFilterUniqueID_Version)) { |
| 104 fUniqueID = next_image_filter_unique_id(); |
| 105 } else { |
| 106 fUniqueID = buffer.readUInt(); |
| 107 } |
68 return buffer.isValid(); | 108 return buffer.isValid(); |
69 } | 109 } |
70 | 110 |
71 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 111 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
72 | 112 |
73 SkImageFilter::Cache* gExternalCache; | 113 SkImageFilter::Cache* gExternalCache; |
74 | 114 |
75 SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropR
ect* cropRect) | 115 SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropR
ect* cropRect) |
76 : fInputCount(inputCount), | 116 : fInputCount(inputCount), |
77 fInputs(new SkImageFilter*[inputCount]), | 117 fInputs(new SkImageFilter*[inputCount]), |
78 fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { | 118 fUsesSrcInput(false), |
| 119 fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)), |
| 120 fUniqueID(next_image_filter_unique_id()) { |
79 for (int i = 0; i < inputCount; ++i) { | 121 for (int i = 0; i < inputCount; ++i) { |
| 122 if (NULL == inputs[i] || inputs[i]->usesSrcInput()) { |
| 123 fUsesSrcInput = true; |
| 124 } |
80 fInputs[i] = inputs[i]; | 125 fInputs[i] = inputs[i]; |
81 SkSafeRef(fInputs[i]); | 126 SkSafeRef(fInputs[i]); |
82 } | 127 } |
83 } | 128 } |
84 | 129 |
85 SkImageFilter::~SkImageFilter() { | 130 SkImageFilter::~SkImageFilter() { |
86 for (int i = 0; i < fInputCount; i++) { | 131 for (int i = 0; i < fInputCount; i++) { |
87 SkSafeUnref(fInputs[i]); | 132 SkSafeUnref(fInputs[i]); |
88 } | 133 } |
89 delete[] fInputs; | 134 delete[] fInputs; |
90 } | 135 } |
91 | 136 |
92 SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) { | 137 SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) |
| 138 : fUsesSrcInput(false) { |
93 Common common; | 139 Common common; |
94 if (common.unflatten(buffer, inputCount)) { | 140 if (common.unflatten(buffer, inputCount)) { |
95 fCropRect = common.cropRect(); | 141 fCropRect = common.cropRect(); |
96 fInputCount = common.inputCount(); | 142 fInputCount = common.inputCount(); |
97 fInputs = SkNEW_ARRAY(SkImageFilter*, fInputCount); | 143 fInputs = SkNEW_ARRAY(SkImageFilter*, fInputCount); |
98 common.detachInputs(fInputs); | 144 common.detachInputs(fInputs); |
| 145 for (int i = 0; i < fInputCount; ++i) { |
| 146 if (NULL == fInputs[i] || fInputs[i]->usesSrcInput()) { |
| 147 fUsesSrcInput = true; |
| 148 } |
| 149 } |
| 150 fUniqueID = buffer.isCrossProcess() ? next_image_filter_unique_id() : co
mmon.uniqueID(); |
99 } else { | 151 } else { |
100 fInputCount = 0; | 152 fInputCount = 0; |
101 fInputs = NULL; | 153 fInputs = NULL; |
102 } | 154 } |
103 } | 155 } |
104 | 156 |
105 void SkImageFilter::flatten(SkWriteBuffer& buffer) const { | 157 void SkImageFilter::flatten(SkWriteBuffer& buffer) const { |
106 buffer.writeInt(fInputCount); | 158 buffer.writeInt(fInputCount); |
107 for (int i = 0; i < fInputCount; i++) { | 159 for (int i = 0; i < fInputCount; i++) { |
108 SkImageFilter* input = getInput(i); | 160 SkImageFilter* input = getInput(i); |
109 buffer.writeBool(input != NULL); | 161 buffer.writeBool(input != NULL); |
110 if (input != NULL) { | 162 if (input != NULL) { |
111 buffer.writeFlattenable(input); | 163 buffer.writeFlattenable(input); |
112 } | 164 } |
113 } | 165 } |
114 buffer.writeRect(fCropRect.rect()); | 166 buffer.writeRect(fCropRect.rect()); |
115 buffer.writeUInt(fCropRect.flags()); | 167 buffer.writeUInt(fCropRect.flags()); |
| 168 buffer.writeUInt(fUniqueID); |
116 } | 169 } |
117 | 170 |
118 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, | 171 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, |
119 const Context& context, | 172 const Context& context, |
120 SkBitmap* result, SkIPoint* offset) const { | 173 SkBitmap* result, SkIPoint* offset) const { |
121 Cache* cache = context.cache(); | |
122 SkASSERT(result); | 174 SkASSERT(result); |
123 SkASSERT(offset); | 175 SkASSERT(offset); |
124 SkASSERT(cache); | 176 uint32_t srcGenID = fUsesSrcInput ? src.getGenerationID() : 0; |
125 if (cache->get(this, result, offset)) { | 177 Cache* externalCache = GetExternalCache(); |
126 return true; | 178 UniqueIDCache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGe
nID); |
| 179 if (NULL != externalCache) { |
| 180 if (externalCache->get(this, result, offset)) { |
| 181 return true; |
| 182 } |
| 183 } else if (context.cache()) { |
| 184 if (context.cache()->get(key, result, offset)) { |
| 185 return true; |
| 186 } |
127 } | 187 } |
128 /* | 188 /* |
129 * Give the proxy first shot at the filter. If it returns false, ask | 189 * Give the proxy first shot at the filter. If it returns false, ask |
130 * the filter to do it. | 190 * the filter to do it. |
131 */ | 191 */ |
132 if ((proxy && proxy->filterImage(this, src, context, result, offset)) || | 192 if ((proxy && proxy->filterImage(this, src, context, result, offset)) || |
133 this->onFilterImage(proxy, src, context, result, offset)) { | 193 this->onFilterImage(proxy, src, context, result, offset)) { |
134 cache->set(this, *result, *offset); | 194 if (externalCache) { |
| 195 externalCache->set(this, *result, *offset); |
| 196 } else if (context.cache()) { |
| 197 context.cache()->set(key, *result, *offset); |
| 198 } |
135 return true; | 199 return true; |
136 } | 200 } |
137 return false; | 201 return false; |
138 } | 202 } |
139 | 203 |
140 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, | 204 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, |
141 SkIRect* dst) const { | 205 SkIRect* dst) const { |
142 SkASSERT(&src); | 206 SkASSERT(&src); |
143 SkASSERT(dst); | 207 SkASSERT(dst); |
144 if (SkImageFilter::GetExternalCache()) { | 208 if (SkImageFilter::GetExternalCache()) { |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 | 496 |
433 CacheImpl::~CacheImpl() { | 497 CacheImpl::~CacheImpl() { |
434 SkTDynamicHash<Value, Key>::Iter iter(&fData); | 498 SkTDynamicHash<Value, Key>::Iter iter(&fData); |
435 | 499 |
436 while (!iter.done()) { | 500 while (!iter.done()) { |
437 Value* v = &*iter; | 501 Value* v = &*iter; |
438 ++iter; | 502 ++iter; |
439 delete v; | 503 delete v; |
440 } | 504 } |
441 } | 505 } |
| 506 |
| 507 namespace { |
| 508 |
| 509 class UniqueIDCacheImpl : public SkImageFilter::UniqueIDCache { |
| 510 public: |
| 511 UniqueIDCacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) { |
| 512 } |
| 513 virtual ~UniqueIDCacheImpl() { |
| 514 SkTDynamicHash<Value, Key>::Iter iter(&fLookup); |
| 515 |
| 516 while (!iter.done()) { |
| 517 Value* v = &*iter; |
| 518 ++iter; |
| 519 delete v; |
| 520 } |
| 521 } |
| 522 struct Value { |
| 523 Value(const Key& key, const SkBitmap& bitmap, const SkIPoint& offset) |
| 524 : fKey(key), fBitmap(bitmap), fOffset(offset) {} |
| 525 Key fKey; |
| 526 SkBitmap fBitmap; |
| 527 SkIPoint fOffset; |
| 528 static const Key& GetKey(const Value& v) { |
| 529 return v.fKey; |
| 530 } |
| 531 static uint32_t Hash(const Key& key) { |
| 532 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key),
sizeof(Key)); |
| 533 } |
| 534 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value); |
| 535 }; |
| 536 virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const { |
| 537 SkAutoMutexAcquire mutex(fMutex); |
| 538 if (Value* v = fLookup.find(key)) { |
| 539 *result = v->fBitmap; |
| 540 *offset = v->fOffset; |
| 541 if (v != fLRU.head()) { |
| 542 fLRU.remove(v); |
| 543 fLRU.addToHead(v); |
| 544 } |
| 545 return true; |
| 546 } |
| 547 return false; |
| 548 } |
| 549 virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& off
set) { |
| 550 SkAutoMutexAcquire mutex(fMutex); |
| 551 if (Value* v = fLookup.find(key)) { |
| 552 removeInternal(v); |
| 553 } |
| 554 Value* v = new Value(key, result, offset); |
| 555 fLookup.add(v); |
| 556 fLRU.addToHead(v); |
| 557 fCurrentBytes += result.getSize(); |
| 558 while (fCurrentBytes > fMaxBytes) { |
| 559 Value* tail = fLRU.tail(); |
| 560 SkASSERT(tail); |
| 561 if (tail == v) { |
| 562 break; |
| 563 } |
| 564 removeInternal(tail); |
| 565 } |
| 566 } |
| 567 private: |
| 568 void removeInternal(Value* v) { |
| 569 fCurrentBytes -= v->fBitmap.getSize(); |
| 570 fLRU.remove(v); |
| 571 fLookup.remove(v->fKey); |
| 572 delete v; |
| 573 } |
| 574 private: |
| 575 SkTDynamicHash<Value, Key> fLookup; |
| 576 mutable SkTInternalLList<Value> fLRU; |
| 577 size_t fMaxBytes; |
| 578 size_t fCurrentBytes; |
| 579 mutable SkMutex fMutex; |
| 580 }; |
| 581 |
| 582 SkImageFilter::UniqueIDCache* CreateCache() { |
| 583 return SkImageFilter::UniqueIDCache::Create(kDefaultCacheSize); |
| 584 } |
| 585 |
| 586 } // namespace |
| 587 |
| 588 SkImageFilter::UniqueIDCache* SkImageFilter::UniqueIDCache::Create(size_t maxByt
es) { |
| 589 return SkNEW_ARGS(UniqueIDCacheImpl, (maxBytes)); |
| 590 } |
| 591 |
| 592 SkImageFilter::UniqueIDCache* SkImageFilter::UniqueIDCache::Get() { |
| 593 SK_DECLARE_STATIC_LAZY_PTR(SkImageFilter::UniqueIDCache, cache, CreateCache)
; |
| 594 return cache.get(); |
| 595 } |
OLD | NEW |