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" |
(...skipping 23 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 /** | |
45 * PictureKey just wraps a picture's unique ID for GrTHashTable. It is used to | |
jvanverth1
2014/07/16 21:04:16
I don't think we're supposed to use GrTHashTable a
robertphillips
2014/07/17 11:57:45
Why don't I do that as a separate CL and just elim
| |
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 | |
44 #ifdef SK_DEBUG | 69 #ifdef SK_DEBUG |
45 void GrCachedLayer::validate(GrTexture* backingTexture) const { | 70 void GrCachedLayer::validate(const GrTexture* backingTexture) const { |
46 SkASSERT(SK_InvalidGenID != fPictureID); | 71 SkASSERT(SK_InvalidGenID != fPictureID); |
47 SkASSERT(-1 != fLayerID); | 72 SkASSERT(-1 != fLayerID); |
48 | 73 |
49 if (NULL != fTexture) { | 74 if (NULL != fTexture) { |
50 // If the layer is in some texture then it must occupy some rectangle | 75 // If the layer is in some texture then it must occupy some rectangle |
51 SkASSERT(!fRect.isEmpty()); | 76 SkASSERT(!fRect.isEmpty()); |
52 if (!this->isAtlased()) { | 77 if (!this->isAtlased()) { |
53 // If it isn't atlased then the rectangle should start at the origin | 78 // If it isn't atlased then the rectangle should start at the origin |
54 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); | 79 SkASSERT(0.0f == fRect.fLeft && 0.0f == fRect.fTop); |
55 } | 80 } |
56 } else { | 81 } else { |
57 SkASSERT(fRect.isEmpty()); | 82 SkASSERT(fRect.isEmpty()); |
83 SkASSERT(NULL == fPlot); | |
84 } | |
85 | |
86 if (NULL != fPlot) { | |
87 // If a layer has a plot (i.e., is atlased) then it must point to | |
88 // the backing texture. Additionally, its rect should be non-empty. | |
89 SkASSERT(NULL != fTexture && backingTexture == fTexture); | |
90 SkASSERT(!fRect.isEmpty()); | |
58 } | 91 } |
59 } | 92 } |
60 | 93 |
61 class GrAutoValidateLayer : ::SkNoncopyable { | 94 class GrAutoValidateLayer : ::SkNoncopyable { |
62 public: | 95 public: |
63 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) | 96 GrAutoValidateLayer(GrTexture* backingTexture, const GrCachedLayer* layer) |
64 : fBackingTexture(backingTexture) | 97 : fBackingTexture(backingTexture) |
65 , fLayer(layer) { | 98 , fLayer(layer) { |
66 if (NULL != fLayer) { | 99 if (NULL != fLayer) { |
67 fLayer->validate(backingTexture); | 100 fLayer->validate(backingTexture); |
68 } | 101 } |
69 } | 102 } |
70 ~GrAutoValidateLayer() { | 103 ~GrAutoValidateLayer() { |
71 if (NULL != fLayer) { | 104 if (NULL != fLayer) { |
72 fLayer->validate(fBackingTexture); | 105 fLayer->validate(fBackingTexture); |
73 } | 106 } |
74 } | 107 } |
108 void setBackingTexture(GrTexture* backingTexture) { | |
109 SkASSERT(NULL == fBackingTexture || fBackingTexture == backingTexture); | |
110 fBackingTexture = backingTexture; | |
111 } | |
75 | 112 |
76 private: | 113 private: |
77 GrTexture* fBackingTexture; | 114 const GrTexture* fBackingTexture; |
78 const GrCachedLayer* fLayer; | 115 const GrCachedLayer* fLayer; |
79 }; | 116 }; |
80 #endif | 117 #endif |
81 | 118 |
82 GrLayerCache::GrLayerCache(GrContext* context) | 119 GrLayerCache::GrLayerCache(GrContext* context) |
83 : fContext(context) { | 120 : fContext(context) { |
84 this->initAtlas(); | 121 this->initAtlas(); |
85 } | 122 } |
86 | 123 |
87 GrLayerCache::~GrLayerCache() { | 124 GrLayerCache::~GrLayerCache() { |
(...skipping 11 matching lines...) Expand all Loading... | |
99 void GrLayerCache::initAtlas() { | 136 void GrLayerCache::initAtlas() { |
100 static const int kAtlasTextureWidth = 1024; | 137 static const int kAtlasTextureWidth = 1024; |
101 static const int kAtlasTextureHeight = 1024; | 138 static const int kAtlasTextureHeight = 1024; |
102 | 139 |
103 SkASSERT(NULL == fAtlas.get()); | 140 SkASSERT(NULL == fAtlas.get()); |
104 | 141 |
105 // The layer cache only gets 1 plot | 142 // The layer cache only gets 1 plot |
106 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; | 143 SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight) ; |
107 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, | 144 fAtlas.reset(SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kSkia8888_GrPixelConfi g, |
108 kRenderTarget_GrTextureFlagBit, | 145 kRenderTarget_GrTextureFlagBit, |
109 textureSize, 1, 1, false))); | 146 textureSize, kNumPlotsX, kNumPlotsY, false ))); |
110 } | 147 } |
111 | 148 |
112 void GrLayerCache::freeAll() { | 149 void GrLayerCache::freeAll() { |
113 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 150 SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); |
114 for (int i = 0; i < fLayerHash.count(); ++i) { | 151 for (int i = 0; i < fLayerHash.count(); ++i) { |
115 this->unlock(layerArray[i]); | 152 this->unlock(layerArray[i]); |
116 } | 153 } |
117 | 154 |
118 fLayerHash.deleteAll(); | 155 fLayerHash.deleteAll(); |
119 | 156 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 if (layer->isAtlased()) { | 195 if (layer->isAtlased()) { |
159 // It claims to be atlased | 196 // It claims to be atlased |
160 SkASSERT(layer->rect().width() == desc.fWidth); | 197 SkASSERT(layer->rect().width() == desc.fWidth); |
161 SkASSERT(layer->rect().height() == desc.fHeight); | 198 SkASSERT(layer->rect().height() == desc.fHeight); |
162 } | 199 } |
163 #endif | 200 #endif |
164 return true; | 201 return true; |
165 } | 202 } |
166 | 203 |
167 #if USE_ATLAS | 204 #if USE_ATLAS |
168 SkIPoint16 loc; | 205 { |
169 GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, desc.fWidth, desc.fHeight, NU LL, &loc); | 206 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); |
170 if (NULL != plot) { | 207 if (NULL == pictInfo) { |
171 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 208 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
172 SkToS16(desc.fWidth), SkToS16(des c.fHeight)); | 209 fPictureHash.insert(PictureKey(layer->pictureID()), pictInfo); |
173 layer->setTexture(fAtlas->getTexture(), bounds); | 210 } |
174 layer->setAtlased(true); | 211 |
175 return false; | 212 SkIPoint16 loc; |
213 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | |
214 desc.fWidth, desc.fHeight, | |
215 NULL, &loc); | |
216 // addToAtlas can allocate the backing texture | |
217 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | |
218 if (NULL != plot) { | |
219 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | |
220 SkToS16(desc.fWidth), SkToS16 (desc.fHeight)); | |
221 layer->setTexture(fAtlas->getTexture(), bounds); | |
222 layer->setPlot(plot); | |
223 return false; | |
224 } | |
176 } | 225 } |
177 #endif | 226 #endif |
178 | 227 |
179 // The texture wouldn't fit in the cache - give it it's own texture. | 228 // The texture wouldn't fit in the cache - give it it's own texture. |
180 // This path always uses a new scratch texture and (thus) doesn't cache anyt hing. | 229 // This path always uses a new scratch texture and (thus) doesn't cache anyt hing. |
181 // This can yield a lot of re-rendering | 230 // This can yield a lot of re-rendering |
182 layer->setTexture(fContext->lockAndRefScratchTexture(desc, GrContext::kAppro x_ScratchTexMatch), | 231 layer->setTexture(fContext->lockAndRefScratchTexture(desc, GrContext::kAppro x_ScratchTexMatch), |
183 GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeig ht))); | 232 GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeig ht))); |
184 return false; | 233 return false; |
185 } | 234 } |
186 | 235 |
187 void GrLayerCache::unlock(GrCachedLayer* layer) { | 236 void GrLayerCache::unlock(GrCachedLayer* layer) { |
188 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 237 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
189 | 238 |
190 if (NULL == layer || NULL == layer->texture()) { | 239 if (NULL == layer || NULL == layer->texture()) { |
191 return; | 240 return; |
192 } | 241 } |
193 | 242 |
194 if (layer->isAtlased()) { | 243 if (layer->isAtlased()) { |
195 // The atlas doesn't currently use a scratch texture (and we would have | 244 SkASSERT(layer->texture() == fAtlas->getTexture()); |
196 // to free up space differently anyways) | 245 |
197 // TODO: unlock atlas space when a recycling rectanizer is available | 246 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(layer->pictureID( ))); |
247 SkASSERT(NULL != pictInfo); | |
248 pictInfo->fPlotUsage.isEmpty(); // just to silence compiler warnings for the time being | |
249 | |
250 // TODO: purging from atlas goes here | |
198 } else { | 251 } else { |
199 fContext->unlockScratchTexture(layer->texture()); | 252 fContext->unlockScratchTexture(layer->texture()); |
200 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 253 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
201 } | 254 } |
202 } | 255 } |
203 | 256 |
204 #ifdef SK_DEBUG | 257 #ifdef SK_DEBUG |
205 void GrLayerCache::validate() const { | 258 void GrLayerCache::validate() const { |
206 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); | 259 const SkTDArray<GrCachedLayer*>& layerArray = fLayerHash.getArray(); |
207 for (int i = 0; i < fLayerHash.count(); ++i) { | 260 for (int i = 0; i < fLayerHash.count(); ++i) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } | 293 } |
241 } | 294 } |
242 | 295 |
243 for (int i = 0; i < toBeRemoved.count(); ++i) { | 296 for (int i = 0; i < toBeRemoved.count(); ++i) { |
244 this->unlock(toBeRemoved[i]); | 297 this->unlock(toBeRemoved[i]); |
245 | 298 |
246 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); | 299 PictureLayerKey key(picture->uniqueID(), toBeRemoved[i]->layerID()); |
247 fLayerHash.remove(key, toBeRemoved[i]); | 300 fLayerHash.remove(key, toBeRemoved[i]); |
248 SkDELETE(toBeRemoved[i]); | 301 SkDELETE(toBeRemoved[i]); |
249 } | 302 } |
303 | |
304 GrPictureInfo* pictInfo = fPictureHash.find(PictureKey(picture->uniqueID())) ; | |
305 if (NULL != pictInfo) { | |
306 fPictureHash.remove(PictureKey(picture->uniqueID()), pictInfo); | |
307 SkDELETE(pictInfo); | |
308 } | |
250 } | 309 } |
OLD | NEW |