Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(472)

Side by Side Diff: src/core/SkImageFilter.cpp

Issue 414483003: Implement a persistent uniqueID-based cache for SkImageFilter. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix cross-process issue (revert those changes to HEAD^^) Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkCanvas.cpp ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698