| 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 } | 146 } |
| 147 | 147 |
| 148 return layer; | 148 return layer; |
| 149 } | 149 } |
| 150 | 150 |
| 151 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool do
ntAtlas) { | 151 bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool do
ntAtlas) { |
| 152 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 152 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 153 | 153 |
| 154 if (layer->locked()) { | 154 if (layer->locked()) { |
| 155 // This layer is already locked | 155 // This layer is already locked |
| 156 #ifdef SK_DEBUG |
| 156 if (layer->isAtlased()) { | 157 if (layer->isAtlased()) { |
| 157 this->incPlotLock(layer->plot()->id()); | 158 // It claims to be atlased |
| 158 SkASSERT(!dontAtlas); | 159 SkASSERT(!dontAtlas); |
| 159 SkASSERT(layer->rect().width() == desc.fWidth); | 160 SkASSERT(layer->rect().width() == desc.fWidth); |
| 160 SkASSERT(layer->rect().height() == desc.fHeight); | 161 SkASSERT(layer->rect().height() == desc.fHeight); |
| 161 } | 162 } |
| 163 #endif |
| 162 return false; | 164 return false; |
| 163 } | 165 } |
| 164 | 166 |
| 165 if (layer->isAtlased()) { | 167 if (layer->isAtlased()) { |
| 166 // Hooray it is still in the atlas - make sure it stays there | 168 // Hooray it is still in the atlas - make sure it stays there |
| 167 SkASSERT(!dontAtlas); | 169 SkASSERT(!dontAtlas); |
| 168 layer->setLocked(true); | 170 layer->setLocked(true); |
| 169 this->incPlotLock(layer->plot()->id()); | 171 fPlotLocks[layer->plot()->id()]++; |
| 170 return false; | 172 return false; |
| 171 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { | 173 } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) { |
| 172 // Not in the atlas - will it fit? | 174 // Not in the atlas - will it fit? |
| 173 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 175 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 174 if (NULL == pictInfo) { | 176 if (NULL == pictInfo) { |
| 175 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); | 177 pictInfo = SkNEW_ARGS(GrPictureInfo, (layer->pictureID())); |
| 176 fPictureHash.add(pictInfo); | 178 fPictureHash.add(pictInfo); |
| 177 } | 179 } |
| 178 | 180 |
| 179 SkIPoint16 loc; | 181 SkIPoint16 loc; |
| 180 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge | 182 for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but a
re able to purge |
| 181 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, | 183 GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage, |
| 182 desc.fWidth, desc.fHeight, | 184 desc.fWidth, desc.fHeight, |
| 183 NULL, &loc); | 185 NULL, &loc); |
| 184 // addToAtlas can allocate the backing texture | 186 // addToAtlas can allocate the backing texture |
| 185 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); | 187 SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture())); |
| 186 if (plot) { | 188 if (plot) { |
| 187 // The layer was successfully added to the atlas | 189 // The layer was successfully added to the atlas |
| 188 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, | 190 GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY, |
| 189 SkToS16(desc.fWidth), | 191 SkToS16(desc.fWidth), |
| 190 SkToS16(desc.fHeight)); | 192 SkToS16(desc.fHeight)); |
| 191 layer->setTexture(fAtlas->getTexture(), bounds); | 193 layer->setTexture(fAtlas->getTexture(), bounds); |
| 192 layer->setPlot(plot); | 194 layer->setPlot(plot); |
| 193 layer->setLocked(true); | 195 layer->setLocked(true); |
| 194 this->incPlotLock(layer->plot()->id()); | 196 fPlotLocks[layer->plot()->id()]++; |
| 195 return true; | 197 return true; |
| 196 } | 198 } |
| 197 | 199 |
| 198 // The layer was rejected by the atlas (even though we know it is | 200 // The layer was rejected by the atlas (even though we know it is |
| 199 // plausibly atlas-able). See if a plot can be purged and try again. | 201 // plausibly atlas-able). See if a plot can be purged and try again. |
| 200 if (!this->purgePlot()) { | 202 if (!this->purgePlot()) { |
| 201 break; // We weren't able to purge any plots | 203 break; // We weren't able to purge any plots |
| 202 } | 204 } |
| 203 } | 205 } |
| 204 } | 206 } |
| 205 | 207 |
| 206 // The texture wouldn't fit in the cache - give it it's own texture. | 208 // The texture wouldn't fit in the cache - give it it's own texture. |
| 207 // This path always uses a new scratch texture and (thus) doesn't cache anyt
hing. | 209 // This path always uses a new scratch texture and (thus) doesn't cache anyt
hing. |
| 208 // This can yield a lot of re-rendering | 210 // This can yield a lot of re-rendering |
| 209 SkAutoTUnref<GrTexture> tex(fContext->lockAndRefScratchTexture(desc, | 211 SkAutoTUnref<GrTexture> tex(fContext->lockAndRefScratchTexture(desc, |
| 210 GrContext::kApprox_Scrat
chTexMatch)); | 212 GrContext::kApprox_Scrat
chTexMatch)); |
| 211 | 213 |
| 212 layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.
fHeight))); | 214 layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.
fHeight))); |
| 213 layer->setLocked(true); | 215 layer->setLocked(true); |
| 214 return true; | 216 return true; |
| 215 } | 217 } |
| 216 | 218 |
| 217 void GrLayerCache::unlock(GrCachedLayer* layer) { | 219 void GrLayerCache::unlock(GrCachedLayer* layer) { |
| 218 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) | 220 SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);) |
| 219 | 221 |
| 220 if (NULL == layer) { | 222 if (NULL == layer || !layer->locked()) { |
| 221 // invalid or not locked | 223 // invalid or not locked |
| 222 return; | 224 return; |
| 223 } | 225 } |
| 224 | 226 |
| 225 if (layer->isAtlased()) { | 227 if (layer->isAtlased()) { |
| 226 const int plotID = layer->plot()->id(); | 228 const int plotID = layer->plot()->id(); |
| 227 | 229 |
| 228 this->decPlotLock(plotID); | 230 SkASSERT(fPlotLocks[plotID] > 0); |
| 231 fPlotLocks[plotID]--; |
| 229 // At this point we could aggressively clear out un-locked plots but | 232 // At this point we could aggressively clear out un-locked plots but |
| 230 // by delaying we may be able to reuse some of the atlased layers later. | 233 // by delaying we may be able to reuse some of the atlased layers later. |
| 231 #if DISABLE_CACHING | 234 #if DISABLE_CACHING |
| 232 // This testing code aggressively removes the atlased layers. This | 235 // This testing code aggressively removes the atlased layers. This |
| 233 // can be used to separate the performance contribution of less | 236 // can be used to separate the performance contribution of less |
| 234 // render target pingponging from that due to the re-use of cached layer
s | 237 // render target pingponging from that due to the re-use of cached layer
s |
| 235 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 238 GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 236 SkASSERT(pictInfo); | 239 SkASSERT(pictInfo); |
| 237 | 240 |
| 238 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); | 241 GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot()); |
| 239 | 242 |
| 240 layer->setPlot(NULL); | 243 layer->setPlot(NULL); |
| 241 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 244 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 242 #endif | 245 #endif |
| 243 | 246 |
| 244 } else { | 247 } else { |
| 245 layer->setTexture(NULL, GrIRect16::MakeEmpty()); | 248 layer->setTexture(NULL, GrIRect16::MakeEmpty()); |
| 246 } | 249 } |
| 247 | 250 |
| 248 layer->setLocked(false); | 251 layer->setLocked(false); |
| 249 } | 252 } |
| 250 | 253 |
| 251 #ifdef SK_DEBUG | 254 #ifdef SK_DEBUG |
| 252 void GrLayerCache::validate() const { | 255 void GrLayerCache::validate() const { |
| 256 int plotLocks[kNumPlotsX * kNumPlotsY]; |
| 257 memset(plotLocks, 0, sizeof(plotLocks)); |
| 258 |
| 253 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); | 259 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::ConstIter iter(&fLayerHas
h); |
| 254 for (; !iter.done(); ++iter) { | 260 for (; !iter.done(); ++iter) { |
| 255 const GrCachedLayer* layer = &(*iter); | 261 const GrCachedLayer* layer = &(*iter); |
| 256 | 262 |
| 257 layer->validate(fAtlas->getTexture()); | 263 layer->validate(fAtlas->getTexture()); |
| 258 | 264 |
| 259 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); | 265 const GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID()); |
| 260 if (pictInfo) { | 266 if (pictInfo) { |
| 261 // In aggressive cleanup mode a picture info should only exist if | 267 // In aggressive cleanup mode a picture info should only exist if |
| 262 // it has some atlased layers | 268 // it has some atlased layers |
| 263 #if !DISABLE_CACHING | 269 #if !DISABLE_CACHING |
| 264 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); | 270 SkASSERT(!pictInfo->fPlotUsage.isEmpty()); |
| 265 #endif | 271 #endif |
| 266 } else { | 272 } else { |
| 267 // If there is no picture info for this picture then all of its | 273 // If there is no picture info for this layer then all of its |
| 268 // layers should be non-atlased. | 274 // layers should be non-atlased. |
| 269 SkASSERT(!layer->isAtlased()); | 275 SkASSERT(!layer->isAtlased()); |
| 270 } | 276 } |
| 271 | 277 |
| 272 if (layer->plot()) { | 278 if (layer->plot()) { |
| 273 SkASSERT(pictInfo); | 279 SkASSERT(pictInfo); |
| 274 SkASSERT(pictInfo->fPictureID == layer->pictureID()); | 280 SkASSERT(pictInfo->fPictureID == layer->pictureID()); |
| 275 | 281 |
| 276 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); | 282 SkASSERT(pictInfo->fPlotUsage.contains(layer->plot())); |
| 277 | 283 |
| 278 if (layer->locked()) { | 284 if (layer->locked()) { |
| 279 SkASSERT(fPlotLocks[layer->plot()->id()] > 0); | 285 plotLocks[layer->plot()->id()]++; |
| 280 } | 286 } |
| 281 } | 287 } |
| 282 } | 288 } |
| 289 |
| 290 for (int i = 0; i < kNumPlotsX*kNumPlotsY; ++i) { |
| 291 SkASSERT(plotLocks[i] == fPlotLocks[i]); |
| 292 } |
| 283 } | 293 } |
| 284 | 294 |
| 285 class GrAutoValidateCache : ::SkNoncopyable { | 295 class GrAutoValidateCache : ::SkNoncopyable { |
| 286 public: | 296 public: |
| 287 explicit GrAutoValidateCache(GrLayerCache* cache) | 297 explicit GrAutoValidateCache(GrLayerCache* cache) |
| 288 : fCache(cache) { | 298 : fCache(cache) { |
| 289 fCache->validate(); | 299 fCache->validate(); |
| 290 } | 300 } |
| 291 ~GrAutoValidateCache() { | 301 ~GrAutoValidateCache() { |
| 292 fCache->validate(); | 302 fCache->validate(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 | 417 |
| 408 void GrLayerCache::processDeletedPictures() { | 418 void GrLayerCache::processDeletedPictures() { |
| 409 SkTDArray<GrPictureDeletedMessage> deletedPictures; | 419 SkTDArray<GrPictureDeletedMessage> deletedPictures; |
| 410 fPictDeletionInbox.poll(&deletedPictures); | 420 fPictDeletionInbox.poll(&deletedPictures); |
| 411 | 421 |
| 412 for (int i = 0; i < deletedPictures.count(); i++) { | 422 for (int i = 0; i < deletedPictures.count(); i++) { |
| 413 this->purge(deletedPictures[i].pictureID); | 423 this->purge(deletedPictures[i].pictureID); |
| 414 } | 424 } |
| 415 } | 425 } |
| 416 | 426 |
| OLD | NEW |