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

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

Issue 1709263002: Update SkImageFilter's cache to handle SkSpecialImages and add unit test (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix comment Created 4 years, 10 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
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 #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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698