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 /** | 12 /** |
13 * PictureLayerKey just wraps a saveLayer's id in the picture for GrTHashTable. | 13 * PictureLayerKey just wraps a saveLayer's id in a picture for GrTHashTable. |
14 */ | 14 */ |
15 class GrLayerCache::PictureLayerKey { | 15 class GrLayerCache::PictureLayerKey { |
16 public: | 16 public: |
17 PictureLayerKey(uint32_t pictureID, int layerID) | 17 PictureLayerKey(uint32_t pictureID, int layerID) |
18 : fPictureID(pictureID) | 18 : fPictureID(pictureID) |
19 , fLayerID(layerID) { | 19 , fLayerID(layerID) { |
20 } | 20 } |
21 | 21 |
22 uint32_t pictureID() const { return fPictureID; } | 22 uint32_t pictureID() const { return fPictureID; } |
23 int layerID() const { return fLayerID; } | 23 int layerID() const { return fLayerID; } |
(...skipping 10 matching lines...) Expand all Loading... |
34 | 34 |
35 static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) { | 35 static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) { |
36 return layer.pictureID() == key.pictureID() && layer.layerID() == key.la
yerID(); | 36 return layer.pictureID() == key.pictureID() && layer.layerID() == key.la
yerID(); |
37 } | 37 } |
38 | 38 |
39 private: | 39 private: |
40 uint32_t fPictureID; | 40 uint32_t fPictureID; |
41 int fLayerID; | 41 int fLayerID; |
42 }; | 42 }; |
43 | 43 |
| 44 #ifdef SK_DEBUG |
| 45 void GrCachedLayer::validate(GrTexture* backingTexture) const { |
| 46 SkASSERT(SK_InvalidGenID != fPictureID); |
| 47 SkASSERT(-1 != fLayerID); |
| 48 |
| 49 if (NULL != fTexture) { |
| 50 // If the layer is in some texture then it must occupy some rectangle |
| 51 SkASSERT(!fRect.isEmpty()); |
| 52 if (!this->isAtlased()) { |
| 53 // If it isn't atlased then the rectangle should start at the origin |
| 54 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
| 55 } |
| 56 } else { |
| 57 SkASSERT(fRect.isEmpty()); |
| 58 } |
| 59 } |
| 60 |
| 61 class GrAutoValidateLayer : ::SkNoncopyable { |
| 62 public: |
| 63 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) |
| 64 : fBackingTexture(backingTexture) |
| 65 , fLayer(layer) { |
| 66 if (NULL != fLayer) { |
| 67 fLayer->validate(backingTexture); |
| 68 } |
| 69 } |
| 70 ~GrAutoValidateLayer() { |
| 71 if (NULL != fLayer) { |
| 72 fLayer->validate(fBackingTexture); |
| 73 } |
| 74 } |
| 75 |
| 76 private: |
| 77 GrTexture* fBackingTexture; |
| 78 const GrCachedLayer* fLayer; |
| 79 }; |
| 80 #endif |
| 81 |
44 GrLayerCache::GrLayerCache(GrContext* context) | 82 GrLayerCache::GrLayerCache(GrContext* context) |
45 : fContext(context) { | 83 : fContext(context) { |
46 this->initAtlas(); | 84 this->initAtlas(); |
47 } | 85 } |
48 | 86 |
49 GrLayerCache::~GrLayerCache() { | 87 GrLayerCache::~GrLayerCache() { |
50 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 88 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); |
51 for (int i = 0; i < fLayerHash.count(); ++i) { | 89 for (int i = 0; i < fLayerHash.count(); ++i) { |
52 this->unlock(layerArray[i]); | 90 this->unlock(layerArray[i]); |
53 } | 91 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 SkASSERT(picture->uniqueID() != SK_InvalidGenID); | 143 SkASSERT(picture->uniqueID() != SK_InvalidGenID); |
106 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(),
layerID)); | 144 GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(),
layerID)); |
107 if (NULL == layer) { | 145 if (NULL == layer) { |
108 layer = this->createLayer(picture, layerID); | 146 layer = this->createLayer(picture, layerID); |
109 } | 147 } |
110 | 148 |
111 return layer; | 149 return layer; |
112 } | 150 } |
113 | 151 |
114 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { | 152 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) { |
| 153 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
115 | 154 |
116 if (NULL != layer->texture()) { | 155 if (NULL != layer->texture()) { |
117 // This layer is already locked | 156 // This layer is already locked |
118 #ifdef SK_DEBUG | 157 #ifdef SK_DEBUG |
119 if (!layer->rect().isEmpty()) { | 158 if (layer->isAtlased()) { |
120 // It claims to be atlased | 159 // It claims to be atlased |
121 SkASSERT(layer->rect().width() == desc.fWidth); | 160 SkASSERT(layer->rect().width() == desc.fWidth); |
122 SkASSERT(layer->rect().height() == desc.fHeight); | 161 SkASSERT(layer->rect().height() == desc.fHeight); |
123 } | 162 } |
124 #endif | 163 #endif |
125 return true; | 164 return true; |
126 } | 165 } |
127 | 166 |
128 #if USE_ATLAS | 167 #if USE_ATLAS |
129 SkIPoint16 loc; | 168 SkIPoint16 loc; |
130 GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, desc.fWidth, desc.fHeight, NU
LL, &loc); | 169 GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, desc.fWidth, desc.fHeight, NU
LL, &loc); |
131 if (NULL != plot) { | 170 if (NULL != plot) { |
132 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 171 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
133 SkToS16(desc.fWidth), SkToS16(des
c.fHeight)); | 172 SkToS16(desc.fWidth), SkToS16(des
c.fHeight)); |
134 layer->setTexture(fAtlas->getTexture(), bounds); | 173 layer->setTexture(fAtlas->getTexture(), bounds); |
| 174 layer->setAtlased(true); |
135 return false; | 175 return false; |
136 } | 176 } |
137 #endif | 177 #endif |
138 | 178 |
| 179 // The texture wouldn't fit in the cache - give it it's own texture. |
139 // This path always uses a new scratch texture and (thus) doesn't cache anyt
hing. | 180 // This path always uses a new scratch texture and (thus) doesn't cache anyt
hing. |
140 // This can yield a lot of re-rendering | 181 // This can yield a lot of re-rendering |
141 layer->setTexture(fContext->lockAndRefScratchTexture(desc, GrContext::kAppro
x_ScratchTexMatch), | 182 layer->setTexture(fContext->lockAndRefScratchTexture(desc, GrContext::kAppro
x_ScratchTexMatch), |
142 GrIRect16::MakeEmpty()); | 183 GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeig
ht))); |
143 return false; | 184 return false; |
144 } | 185 } |
145 | 186 |
146 void GrLayerCache::unlock(GrCachedLayer* layer) { | 187 void GrLayerCache::unlock(GrCachedLayer* layer) { |
| 188 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 189 |
147 if (NULL == layer || NULL == layer->texture()) { | 190 if (NULL == layer || NULL == layer->texture()) { |
148 return; | 191 return; |
149 } | 192 } |
150 | 193 |
151 // The atlas doesn't currently use a scratch texture (and we would have | 194 if (layer->isAtlased()) { |
152 // to free up space differently anyways) | 195 // The atlas doesn't currently use a scratch texture (and we would have |
153 // TODO: unlock atlas space when a recycling rectanizer is available | 196 // to free up space differently anyways) |
154 if (layer->texture() != fAtlas->getTexture()) { | 197 // TODO: unlock atlas space when a recycling rectanizer is available |
| 198 } else { |
155 fContext->unlockScratchTexture(layer->texture()); | 199 fContext->unlockScratchTexture(layer->texture()); |
156 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 200 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
157 } | 201 } |
158 } | 202 } |
159 | 203 |
| 204 #ifdef SK_DEBUG |
| 205 void GrLayerCache::validate() const { |
| 206 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); |
| 207 for (int i = 0; i < fLayerHash.count(); ++i) { |
| 208 layerArray[i]->validate(fAtlas->getTexture()); |
| 209 } |
| 210 } |
| 211 |
| 212 class GrAutoValidateCache : ::SkNoncopyable { |
| 213 public: |
| 214 explicit GrAutoValidateCache(GrLayerCache* cache) |
| 215 : fCache(cache) { |
| 216 fCache->validate(); |
| 217 } |
| 218 ~GrAutoValidateCache() { |
| 219 fCache->validate(); |
| 220 } |
| 221 private: |
| 222 GrLayerCache* fCache; |
| 223 }; |
| 224 #endif |
| 225 |
160 void GrLayerCache::purge(const SkPicture* picture) { | 226 void GrLayerCache::purge(const SkPicture* picture) { |
| 227 SkDEBUGCODE(GrAutoValidateCache avc(this);) |
| 228 |
161 // This is somewhat of an abuse of GrTHashTable. We need to find all the | 229 // This is somewhat of an abuse of GrTHashTable. We need to find all the |
162 // layers associated with 'picture' but the usual hash calls only look for | 230 // layers associated with 'picture' but the usual hash calls only look for |
163 // exact key matches. This code peeks into the hash table's innards to | 231 // exact key matches. This code peeks into the hash table's innards to |
164 // find all the 'picture'-related layers. | 232 // find all the 'picture'-related layers. |
165 // TODO: use a different data structure for the layer hash? | 233 // TODO: use a different data structure for the layer hash? |
166 SkTDArray<GrCachedLayer*> toBeRemoved; | 234 SkTDArray<GrCachedLayer*> toBeRemoved; |
167 | 235 |
168 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 236 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); |
169 for (int i = 0; i < fLayerHash.count(); ++i) { | 237 for (int i = 0; i < fLayerHash.count(); ++i) { |
170 if (picture->uniqueID() == layerArray[i]->pictureID()) { | 238 if (picture->uniqueID() == layerArray[i]->pictureID()) { |
171 *toBeRemoved.append() = layerArray[i]; | 239 *toBeRemoved.append() = layerArray[i]; |
172 } | 240 } |
173 } | 241 } |
174 | 242 |
175 for (int i = 0; i < toBeRemoved.count(); ++i) { | 243 for (int i = 0; i < toBeRemoved.count(); ++i) { |
176 this->unlock(toBeRemoved[i]); | 244 this->unlock(toBeRemoved[i]); |
177 | 245 |
178 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | 246 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); |
179 fLayerHash.remove(key, toBeRemoved[i]); | 247 fLayerHash.remove(key, toBeRemoved[i]); |
180 SkDELETE(toBeRemoved[i]); | 248 SkDELETE(toBeRemoved[i]); |
181 } | 249 } |
182 } | 250 } |
OLD | NEW |