OLD | NEW |
---|---|
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 "GrAtlas.h" | 8 #include "GrAtlas.h" |
9 #include "GrGpu.h" | 9 #include "GrGpu.h" |
10 #include "GrLayerCache.h" | 10 #include "GrLayerCache.h" |
11 | 11 |
12 /** | |
13 * PictureLayerKey just wraps a saveLayer's id in a picture for GrTHashTable. | |
14 */ | |
15 class GrLayerCache::PictureLayerKey { | |
16 public: | |
17 PictureLayerKey(uint32_t pictureID, int layerID) | |
18 : fPictureID(pictureID) | |
19 , fLayerID(layerID) { | |
20 } | |
21 | |
22 uint32_t pictureID() const { return fPictureID; } | |
23 int layerID() const { return fLayerID; } | |
24 | |
25 uint32_t getHash() const { return (fPictureID << 16) | fLayerID; } | |
26 | |
27 static bool LessThan(const GrCachedLayer& layer, const PictureLayerKey& key) { | |
28 if (layer.pictureID() == key.pictureID()) { | |
29 return layer.layerID() < key.layerID(); | |
30 } | |
31 | |
32 return layer.pictureID() < key.pictureID(); | |
33 } | |
34 | |
35 static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) { | |
36 return layer.pictureID() == key.pictureID() && layer.layerID() == key.la yerID(); | |
37 } | |
38 | |
39 private: | |
40 uint32_t fPictureID; | |
41 int fLayerID; | |
42 }; | |
43 | |
44 /** | |
45 * PictureKey just wraps a picture's unique ID for GrTHashTable. It is used to | |
46 * look up a picture's GrPictureInfo (i.e., its GrPlot usage). | |
47 */ | |
48 class GrLayerCache::PictureKey { | |
49 public: | |
50 PictureKey(uint32_t pictureID) : fPictureID(pictureID) { } | |
51 | |
52 uint32_t pictureID() const { return fPictureID; } | |
53 | |
54 uint32_t getHash() const { return fPictureID; } | |
55 | |
56 static bool LessThan(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
57 return pictInfo.fPictureID < key.pictureID(); | |
58 } | |
59 | |
60 static bool Equals(const GrPictureInfo& pictInfo, const PictureKey& key) { | |
61 return pictInfo.fPictureID == key.pictureID(); | |
62 | |
63 } | |
64 | |
65 private: | |
66 uint32_t fPictureID; | |
67 }; | |
68 | |
69 #ifdef SK_DEBUG | 12 #ifdef SK_DEBUG |
70 void GrCachedLayer::validate(const GrTexture* backingTexture) const { | 13 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
71 SkASSERT(SK_InvalidGenID != fPictureID); | 14 SkASSERT(SK_InvalidGenID != fKey.getPictureID()); |
72 SkASSERT(-1 != fLayerID); | 15 SkASSERT(-1 != fKey.getLayerID()); |
16 | |
73 | 17 |
74 if (NULL != fTexture) { | 18 if (NULL != fTexture) { |
75 // If the layer is in some texture then it must occupy some rectangle | 19 // If the layer is in some texture then it must occupy some rectangle |
76 SkASSERT(!fRect.isEmpty()); | 20 SkASSERT(!fRect.isEmpty()); |
77 if (!this->isAtlased()) { | 21 if (!this->isAtlased()) { |
78 // If it isn't atlased then the rectangle should start at the origin | 22 // If it isn't atlased then the rectangle should start at the origin |
79 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 23 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
80 } | 24 } |
81 } else { | 25 } else { |
82 SkASSERT(fRect.isEmpty()); | 26 SkASSERT(fRect.isEmpty()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 const GrTexture* fBackingTexture; | 58 const GrTexture* fBackingTexture; |
115 const GrCachedLayer* fLayer; | 59 const GrCachedLayer* fLayer; |
116 }; | 60 }; |
117 #endif | 61 #endif |
118 | 62 |
119 GrLayerCache::GrLayerCache(GrContext* context) | 63 GrLayerCache::GrLayerCache(GrContext* context) |
120 : fContext(context) { | 64 : fContext(context) { |
121 this->initAtlas(); | 65 this->initAtlas(); |
122 } | 66 } |
123 | 67 |
124 GrLayerCache::~GrLayerCache() { | 68 class UnlockAndDeleteFunctor { |
125 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 69 public: |
126 for (int i = 0; i < fLayerHash.count(); ++i) { | 70 UnlockAndDeleteFunctor(GrLayerCache* cache) : fCache(cache) {} |
mtklein
2014/07/17 20:23:29
Dead code now?
robertphillips
2014/07/18 15:00:36
Done.
| |
127 this->unlock(layerArray[i]); | 71 |
72 void operator()(GrCachedLayer& layer) { | |
73 fCache->unlock(&layer); | |
74 SkDELETE(&layer); | |
128 } | 75 } |
129 | 76 |
130 fLayerHash.deleteAll(); | 77 private: |
78 GrLayerCache* fCache; | |
79 }; | |
80 | |
81 GrLayerCache::~GrLayerCache() { | |
82 | |
83 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); | |
84 for (; !iter.done(); ++iter) { | |
85 GrCachedLayer* layer = &(*iter); | |
86 this->unlock(layer); | |
87 SkDELETE(layer); | |
88 } | |
131 | 89 |
132 // The atlas only lets go of its texture when the atlas is deleted. | 90 // The atlas only lets go of its texture when the atlas is deleted. |
133 fAtlas.free(); | 91 fAtlas.free(); |
134 } | 92 } |
135 | 93 |
136 void GrLayerCache::initAtlas() { | 94 void GrLayerCache::initAtlas() { |
137 static const int kAtlasTextureWidth = 1024; | 95 static const int kAtlasTextureWidth = 1024; |
138 static const int kAtlasTextureHeight = 1024; | 96 static const int kAtlasTextureHeight = 1024; |
139 | 97 |
140 SkASSERT(NULL == fAtlas.get()); | 98 SkASSERT(NULL == fAtlas.get()); |
141 | 99 |
142 // The layer cache only gets 1 plot | 100 // The layer cache only gets 1 plot |
143 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; | 101 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; |
144 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, | 102 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, |
145 kRenderTarget_GrTextureFlagBit, | 103 kRenderTarget_GrTextureFlagBit, |
146 textureSize, kNumPlotsX, kNumPlotsY, false ))); | 104 textureSize, kNumPlotsX, kNumPlotsY, false ))); |
147 } | 105 } |
148 | 106 |
149 void GrLayerCache::freeAll() { | 107 void GrLayerCache::freeAll() { |
150 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 108 |
151 for (int i = 0; i < fLayerHash.count(); ++i) { | 109 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
152 this->unlock(layerArray[i]); | 110 for (; !iter.done(); ++iter) { |
111 GrCachedLayer* layer = &(*iter); | |
112 this->unlock(layer); | |
113 SkDELETE(layer); | |
153 } | 114 } |
154 | 115 fLayerHash.rewind(); |
155 fLayerHash.deleteAll(); | |
156 | 116 |
157 // The atlas only lets go of its texture when the atlas is deleted. | 117 // The atlas only lets go of its texture when the atlas is deleted. |
158 fAtlas.free(); | 118 fAtlas.free(); |
159 // GrLayerCache always assumes an atlas exists so recreate it. The atlas | 119 // GrLayerCache always assumes an atlas exists so recreate it. The atlas |
160 // lazily allocates a replacement texture so reallocating a new | 120 // lazily allocates a replacement texture so reallocating a new |
161 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource s. | 121 // atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResource s. |
162 // TODO: Make GrLayerCache lazily allocate the atlas manager? | 122 // TODO: Make GrLayerCache lazily allocate the atlas manager? |
163 this->initAtlas(); | 123 this->initAtlas(); |
164 } | 124 } |
165 | 125 |
166 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID) { | 126 GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID) { |
167 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 127 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
168 | 128 |
169 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer ID)); | 129 GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), layer ID)); |
170 fLayerHash.insert(PictureLayerKey(picture->uniqueID(), layerID), layer); | 130 fLayerHash.add(layer); |
171 return layer; | 131 return layer; |
172 } | 132 } |
173 | 133 |
174 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { | 134 GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture, int layerID) { |
175 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 135 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
176 return fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 136 return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), layerID)); |
177 } | 137 } |
178 | 138 |
179 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay erID) { | 139 GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int lay erID) { |
180 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 140 SkASSERT(picture->uniqueID() != SK_InvalidGenID && layerID >= 0); |
181 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID)); | 141 GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID( ), layerID)); |
182 if (NULL == layer) { | 142 if (NULL == layer) { |
183 layer = this->createLayer(picture, layerID); | 143 layer = this->createLayer(picture, layerID); |
184 } | 144 } |
185 | 145 |
186 return layer; | 146 return layer; |
187 } | 147 } |
188 | 148 |
189 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { | 149 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { |
190 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 150 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
191 | 151 |
192 if (NULL != layer->texture()) { | 152 if (NULL != layer->texture()) { |
193 // This layer is already locked | 153 // This layer is already locked |
194 #ifdef SK_DEBUG | 154 #ifdef SK_DEBUG |
195 if (layer->isAtlased()) { | 155 if (layer->isAtlased()) { |
196 // It claims to be atlased | 156 // It claims to be atlased |
197 SkASSERT(layer->rect().width() == desc.fWidth); | 157 SkASSERT(layer->rect().width() == desc.fWidth); |
198 SkASSERT(layer->rect().height() == desc.fHeight); | 158 SkASSERT(layer->rect().height() == desc.fHeight); |
199 } | 159 } |
200 #endif | 160 #endif |
201 return true; | 161 return true; |
202 } | 162 } |
203 | 163 |
204 #if USE_ATLAS | 164 #if USE_ATLAS |
205 { | 165 { |
206 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); | 166 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
207 if (NULL == pictInfo) { | 167 if (NULL == pictInfo) { |
208 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 168 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
209 fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo); | 169 fPictureHash.add(pictInfo); |
210 } | 170 } |
211 | 171 |
212 SkIPoint16 loc; | 172 SkIPoint16 loc; |
213 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 173 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
214 desc.fWidth, desc.fHeight, | 174 desc.fWidth, desc.fHeight, |
215 NULL, &loc); | 175 NULL, &loc); |
216 // addToAtlas can allocate the backing texture | 176 // addToAtlas can allocate the backing texture |
217 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 177 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
218 if (NULL != plot) { | 178 if (NULL != plot) { |
219 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 179 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
(...skipping 16 matching lines...) Expand all Loading... | |
236 void GrLayerCache::unlock(GrCachedLayer* layer) { | 196 void GrLayerCache::unlock(GrCachedLayer* layer) { |
237 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 197 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
238 | 198 |
239 if (NULL == layer || NULL == layer->texture()) { | 199 if (NULL == layer || NULL == layer->texture()) { |
240 return; | 200 return; |
241 } | 201 } |
242 | 202 |
243 if (layer->isAtlased()) { | 203 if (layer->isAtlased()) { |
244 SkASSERT(layer->texture() == fAtlas->getTexture()); | 204 SkASSERT(layer->texture() == fAtlas->getTexture()); |
245 | 205 |
246 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); | 206 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
247 SkASSERT(NULL != pictInfo); | 207 SkASSERT(NULL != pictInfo); |
248 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being | 208 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being |
249 | 209 |
250 // TODO: purging from atlas goes here | 210 // TODO: purging from atlas goes here |
251 } else { | 211 } else { |
252 fContext->unlockScratchTexture(layer->texture()); | 212 fContext->unlockScratchTexture(layer->texture()); |
253 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 213 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
254 } | 214 } |
255 } | 215 } |
256 | 216 |
257 #ifdef SK_DEBUG | 217 #ifdef SK_DEBUG |
258 void GrLayerCache::validate() const { | 218 void GrLayerCache::validate() const { |
259 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 219 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas h); |
260 for (int i = 0; i < fLayerHash.count(); ++i) { | 220 for (; !iter.done(); ++iter) { |
261 layerArray[i]->validate(fAtlas->getTexture()); | 221 (*iter).validate(fAtlas->getTexture()); |
262 } | 222 } |
263 } | 223 } |
264 | 224 |
265 class GrAutoValidateCache : ::SkNoncopyable { | 225 class GrAutoValidateCache : ::SkNoncopyable { |
266 public: | 226 public: |
267 explicit GrAutoValidateCache(GrLayerCache* cache) | 227 explicit GrAutoValidateCache(GrLayerCache* cache) |
268 : fCache(cache) { | 228 : fCache(cache) { |
269 fCache->validate(); | 229 fCache->validate(); |
270 } | 230 } |
271 ~GrAutoValidateCache() { | 231 ~GrAutoValidateCache() { |
272 fCache->validate(); | 232 fCache->validate(); |
273 } | 233 } |
274 private: | 234 private: |
275 GrLayerCache* fCache; | 235 GrLayerCache* fCache; |
276 }; | 236 }; |
277 #endif | 237 #endif |
278 | 238 |
279 void GrLayerCache::purge(const SkPicture* picture) { | 239 void GrLayerCache::purge(const SkPicture* picture) { |
280 SkDEBUGCODE(GrAutoValidateCache avc(this);) | 240 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
281 | 241 |
282 // This is somewhat of an abuse of GrTHashTable. We need to find all the | 242 // We need to find all the layers associated with 'picture' and remove them. |
283 // layers associated with 'picture' but the usual hash calls only look for | |
284 // exact key matches. This code peeks into the hash table's innards to | |
285 // find all the 'picture'-related layers. | |
286 // TODO: use a different data structure for the layer hash? | |
287 SkTDArray<GrCachedLayer*> toBeRemoved; | 243 SkTDArray<GrCachedLayer*> toBeRemoved; |
288 | 244 |
289 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 245 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash); |
290 for (int i = 0; i < fLayerHash.count(); ++i) { | 246 for (; !iter.done(); ++iter) { |
291 if (picture->uniqueID() == layerArray[i]->pictureID()) { | 247 if (picture->uniqueID() == (*iter).pictureID()) { |
292 *toBeRemoved.append() = layerArray[i]; | 248 *toBeRemoved.append() = &(*iter); |
293 } | 249 } |
294 } | 250 } |
295 | 251 |
296 for (int i = 0; i < toBeRemoved.count(); ++i) { | 252 for (int i = 0; i < toBeRemoved.count(); ++i) { |
297 this->unlock(toBeRemoved[i]); | 253 this->unlock(toBeRemoved[i]); |
298 | 254 fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i])); |
299 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | |
300 fLayerHash.remove(key, toBeRemoved[i]); | |
301 SkDELETE(toBeRemoved[i]); | 255 SkDELETE(toBeRemoved[i]); |
302 } | 256 } |
303 | 257 |
304 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID())) ; | 258 GrPictureInfo* pictInfo = fPictureHash.find(picture->uniqueID()); |
305 if (NULL != pictInfo) { | 259 if (NULL != pictInfo) { |
306 fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo); | 260 fPictureHash.remove(picture->uniqueID()); |
307 SkDELETE(pictInfo); | 261 SkDELETE(pictInfo); |
308 } | 262 } |
309 } | 263 } |
OLD | NEW |