| 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 |