Chromium Code Reviews| 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 |