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

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

Issue 825263005: notify resource caches when pixelref genID goes stale (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add test for purge notifications Created 5 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
« no previous file with comments | « src/core/SkBitmapCache.h ('k') | src/core/SkPixelRef.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 2014 Google Inc. 2 * Copyright 2014 Google Inc.
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 "SkBitmapCache.h" 8 #include "SkBitmapCache.h"
9 #include "SkResourceCache.h" 9 #include "SkResourceCache.h"
10 #include "SkMipMap.h" 10 #include "SkMipMap.h"
(...skipping 15 matching lines...) Expand all
26 } 26 }
27 SkIPoint origin = bm.pixelRefOrigin(); 27 SkIPoint origin = bm.pixelRefOrigin();
28 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height()); 28 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
29 } 29 }
30 30
31 namespace { 31 namespace {
32 static unsigned gBitmapKeyNamespaceLabel; 32 static unsigned gBitmapKeyNamespaceLabel;
33 33
34 struct BitmapKey : public SkResourceCache::Key { 34 struct BitmapKey : public SkResourceCache::Key {
35 public: 35 public:
36 BitmapKey(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& b ounds) 36 BitmapKey(uint32_t genID, SkScalar sx, SkScalar sy, const SkIRect& bounds)
37 : fGenID(genID) 37 : fGenID(genID)
38 , fScaleX(scaleX) 38 , fScaleX(sx)
39 , fScaleY(scaleY) 39 , fScaleY(sy)
40 , fBounds(bounds) 40 , fBounds(bounds)
41 { 41 {
42 this->init(&gBitmapKeyNamespaceLabel, 42 this->init(&gBitmapKeyNamespaceLabel,
43 sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(f Bounds)); 43 sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(f Bounds));
44 } 44 }
45 45
46 uint32_t fGenID; 46 uint32_t fGenID;
47 SkScalar fScaleX; 47 SkScalar fScaleX;
48 SkScalar fScaleY; 48 SkScalar fScaleY;
49 SkIRect fBounds; 49 SkIRect fBounds;
50 }; 50 };
51 51
52 //////////////////////////////////////////////////////////////////////////////// //////////
53
54 struct BitmapRec : public SkResourceCache::Rec { 52 struct BitmapRec : public SkResourceCache::Rec {
55 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& b ounds, 53 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& b ounds,
56 const SkBitmap& result) 54 const SkBitmap& result)
57 : fKey(genID, scaleX, scaleY, bounds) 55 : fKey(genID, scaleX, scaleY, bounds)
58 , fBitmap(result) 56 , fBitmap(result)
59 {} 57 {}
60 58
61 BitmapKey fKey;
62 SkBitmap fBitmap;
63
64 const Key& getKey() const SK_OVERRIDE { return fKey; } 59 const Key& getKey() const SK_OVERRIDE { return fKey; }
65 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize (); } 60 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize (); }
66 61
67 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap ) { 62 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
68 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec); 63 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
69 SkBitmap* result = (SkBitmap*)contextBitmap; 64 SkBitmap* result = (SkBitmap*)contextBitmap;
70 65
71 *result = rec.fBitmap; 66 *result = rec.fBitmap;
72 result->lockPixels(); 67 result->lockPixels();
73 return SkToBool(result->getPixels()); 68 return SkToBool(result->getPixels());
74 } 69 }
70
71 static SkResourceCache::PurgeVisitorResult PurgeGenID(const SkResourceCache: :Rec& baseRec,
72 void* contextGenID) {
73 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
74 uintptr_t genID = (uintptr_t)contextGenID;
75 if (rec.fKey.fGenID == genID) {
76 // SkDebugf("BitmapRec purging genID %d\n", genID);
77 return SkResourceCache::kPurgeAndContinue_PurgeVisitorResult;
78 } else {
79 return SkResourceCache::kRetainAndContinue_PurgeVisitorResult;
80 }
81 }
82
83 private:
84 BitmapKey fKey;
85 SkBitmap fBitmap;
75 }; 86 };
76 } // namespace 87 } // namespace
77 88
78 #define CHECK_LOCAL(localCache, localName, globalName, ...) \ 89 #define CHECK_LOCAL(localCache, localName, globalName, ...) \
79 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::global Name(__VA_ARGS__)) 90 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::global Name(__VA_ARGS__))
80 91
81 bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invSc aleY, SkBitmap* result, 92 bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invSc aleY, SkBitmap* result,
82 SkResourceCache* localCache) { 93 SkResourceCache* localCache) {
83 if (0 == invScaleX || 0 == invScaleY) { 94 if (0 == invScaleX || 0 == invScaleY) {
84 // degenerate, and the key we use for mipmaps 95 // degenerate, and the key we use for mipmaps
85 return false; 96 return false;
86 } 97 }
87 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_b itmap(src)); 98 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_b itmap(src));
88 99
89 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result); 100 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
90 } 101 }
91 102
92 void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invSca leY, 103 void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invSca leY,
93 const SkBitmap& result, SkResourceCache* localCache) { 104 const SkBitmap& result, SkResourceCache* localCache) {
94 if (0 == invScaleX || 0 == invScaleY) { 105 if (0 == invScaleX || 0 == invScaleY) {
95 // degenerate, and the key we use for mipmaps 106 // degenerate, and the key we use for mipmaps
96 return; 107 return;
97 } 108 }
98 SkASSERT(result.isImmutable()); 109 SkASSERT(result.isImmutable());
99 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, in vScaleY, 110 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, in vScaleY,
100 get_bounds_from_bitmap(src), result) ); 111 get_bounds_from_bitmap(src), result) );
101 CHECK_LOCAL(localCache, add, Add, rec); 112 CHECK_LOCAL(localCache, add, Add, rec);
102 } 113 }
103 114
104 bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result , 115 bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result ,
105 SkResourceCache* localCache) { 116 SkResourceCache* localCache) {
106 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset); 117 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
107 118
108 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result); 119 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
109 } 120 }
110 121
111 bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& r esult, 122 bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& r esult,
112 SkResourceCache* localCache) { 123 SkResourceCache* localCache) {
113 SkASSERT(result.isImmutable()); 124 SkASSERT(result.isImmutable());
114 125
115 if (subset.isEmpty() 126 if (subset.isEmpty()
116 || subset.top() < 0 127 || subset.top() < 0
117 || subset.left() < 0 128 || subset.left() < 0
118 || result.width() != subset.width() 129 || result.width() != subset.width()
119 || result.height() != subset.height()) { 130 || result.height() != subset.height()) {
120 return false; 131 return false;
121 } else { 132 } else {
122 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1, s ubset, result)); 133 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1, s ubset, result));
123 134
124 CHECK_LOCAL(localCache, add, Add, rec); 135 CHECK_LOCAL(localCache, add, Add, rec);
125 return true; 136 return true;
126 } 137 }
127 } 138 }
139
140 void SkBitmapCache::NotifyGenIDStale(uint32_t genID) {
141 SkResourceCache::Purge(&gBitmapKeyNamespaceLabel, BitmapRec::PurgeGenID,
142 (void*)((uintptr_t)genID));
143 }
144
128 //////////////////////////////////////////////////////////////////////////////// ////////// 145 //////////////////////////////////////////////////////////////////////////////// //////////
146 //////////////////////////////////////////////////////////////////////////////// //////////
147
148 namespace {
149 static unsigned gMipMapKeyNamespaceLabel;
150
151 struct MipMapKey : public SkResourceCache::Key {
152 public:
153 MipMapKey(uint32_t genID, const SkIRect& bounds) : fGenID(genID), fBounds(bo unds) {
154 this->init(&gMipMapKeyNamespaceLabel, sizeof(fGenID) + sizeof(fBounds));
155 }
156
157 uint32_t fGenID;
158 SkIRect fBounds;
159 };
129 160
130 struct MipMapRec : public SkResourceCache::Rec { 161 struct MipMapRec : public SkResourceCache::Rec {
131 MipMapRec(const SkBitmap& src, const SkMipMap* result) 162 MipMapRec(const SkBitmap& src, const SkMipMap* result)
132 : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src)) 163 : fKey(src.getGenerationID(), get_bounds_from_bitmap(src))
133 , fMipMap(result) 164 , fMipMap(result)
134 { 165 {
135 fMipMap->attachToCacheAndRef(); 166 fMipMap->attachToCacheAndRef();
136 } 167 }
137 168
138 virtual ~MipMapRec() { 169 virtual ~MipMapRec() {
139 fMipMap->detachFromCacheAndUnref(); 170 fMipMap->detachFromCacheAndUnref();
140 } 171 }
141 172
142 const Key& getKey() const SK_OVERRIDE { return fKey; } 173 const Key& getKey() const SK_OVERRIDE { return fKey; }
143 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->size() ; } 174 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->size() ; }
144 175
145 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) { 176 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
146 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec); 177 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
147 const SkMipMap* mm = SkRef(rec.fMipMap); 178 const SkMipMap* mm = SkRef(rec.fMipMap);
148 // the call to ref() above triggers a "lock" in the case of discardable memory, 179 // the call to ref() above triggers a "lock" in the case of discardable memory,
149 // which means we can now check for null (in case the lock failed). 180 // which means we can now check for null (in case the lock failed).
150 if (NULL == mm->data()) { 181 if (NULL == mm->data()) {
151 mm->unref(); // balance our call to ref() 182 mm->unref(); // balance our call to ref()
152 return false; 183 return false;
153 } 184 }
154 // the call must call unref() when they are done. 185 // the call must call unref() when they are done.
155 *(const SkMipMap**)contextMip = mm; 186 *(const SkMipMap**)contextMip = mm;
156 return true; 187 return true;
157 } 188 }
158 189
190 static SkResourceCache::PurgeVisitorResult PurgeGenID(const SkResourceCache: :Rec& baseRec,
191 void* contextGenID) {
192 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
193 uintptr_t genID = (uintptr_t)contextGenID;
194 if (rec.fKey.fGenID == genID) {
195 // SkDebugf("MipMapRec purging genID %d\n", genID);
196 return SkResourceCache::kPurgeAndContinue_PurgeVisitorResult;
197 } else {
198 return SkResourceCache::kRetainAndContinue_PurgeVisitorResult;
199 }
200 }
201
159 private: 202 private:
160 BitmapKey fKey; 203 MipMapKey fKey;
161 const SkMipMap* fMipMap; 204 const SkMipMap* fMipMap;
162 }; 205 };
206 }
163 207
164 const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) { 208 const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) {
165 BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src)); 209 MipMapKey key(src.getGenerationID(), get_bounds_from_bitmap(src));
166 const SkMipMap* result; 210 const SkMipMap* result;
167 211
168 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Visitor, &result)) { 212 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
169 result = NULL; 213 result = NULL;
170 } 214 }
171 return result; 215 return result;
172 } 216 }
173 217
174 static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) { 218 static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) {
175 return localCache ? localCache->GetDiscardableFactory() 219 return localCache ? localCache->GetDiscardableFactory()
176 : SkResourceCache::GetDiscardableFactory(); 220 : SkResourceCache::GetDiscardableFactory();
177 } 221 }
178 222
179 const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* l ocalCache) { 223 const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* l ocalCache) {
180 SkMipMap* mipmap = SkMipMap::Build(src, get_fact(localCache)); 224 SkMipMap* mipmap = SkMipMap::Build(src, get_fact(localCache));
181 if (mipmap) { 225 if (mipmap) {
182 MipMapRec* rec = SkNEW_ARGS(MipMapRec, (src, mipmap)); 226 MipMapRec* rec = SkNEW_ARGS(MipMapRec, (src, mipmap));
183 CHECK_LOCAL(localCache, add, Add, rec); 227 CHECK_LOCAL(localCache, add, Add, rec);
184 } 228 }
185 return mipmap; 229 return mipmap;
186 } 230 }
187 231
232 void SkMipMapCache::NotifyGenIDStale(uint32_t genID) {
233 SkResourceCache::Purge(&gMipMapKeyNamespaceLabel, MipMapRec::PurgeGenID,
234 (void*)((uintptr_t)genID));
235 }
OLDNEW
« no previous file with comments | « src/core/SkBitmapCache.h ('k') | src/core/SkPixelRef.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698