OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrTextureStripAtlas.h" | 9 #include "GrTextureStripAtlas.h" |
10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 if (NULL == gAtlasCache) { | 29 if (NULL == gAtlasCache) { |
30 gAtlasCache = SkNEW((GrTHashTable<AtlasEntry, AtlasHashKey, 8>)); | 30 gAtlasCache = SkNEW((GrTHashTable<AtlasEntry, AtlasHashKey, 8>)); |
31 } | 31 } |
32 | 32 |
33 return gAtlasCache; | 33 return gAtlasCache; |
34 } | 34 } |
35 | 35 |
36 // Remove the specified atlas from the cache | 36 // Remove the specified atlas from the cache |
37 void GrTextureStripAtlas::CleanUp(const GrContext*, void* info) { | 37 void GrTextureStripAtlas::CleanUp(const GrContext*, void* info) { |
38 GrAssert(NULL != info); | 38 SkASSERT(NULL != info); |
39 | 39 |
40 AtlasEntry* entry = static_cast<AtlasEntry*>(info); | 40 AtlasEntry* entry = static_cast<AtlasEntry*>(info); |
41 | 41 |
42 // remove the cache entry | 42 // remove the cache entry |
43 GetCache()->remove(entry->fKey, entry); | 43 GetCache()->remove(entry->fKey, entry); |
44 | 44 |
45 // remove the actual entry | 45 // remove the actual entry |
46 SkDELETE(entry); | 46 SkDELETE(entry); |
47 | 47 |
48 if (0 == GetCache()->count()) { | 48 if (0 == GetCache()->count()) { |
(...skipping 22 matching lines...) Expand all Loading... |
71 | 71 |
72 GrTextureStripAtlas::GrTextureStripAtlas(GrTextureStripAtlas::Desc desc) | 72 GrTextureStripAtlas::GrTextureStripAtlas(GrTextureStripAtlas::Desc desc) |
73 : fCacheKey(sk_atomic_inc(&gCacheCount)) | 73 : fCacheKey(sk_atomic_inc(&gCacheCount)) |
74 , fLockedRows(0) | 74 , fLockedRows(0) |
75 , fDesc(desc) | 75 , fDesc(desc) |
76 , fNumRows(desc.fHeight / desc.fRowHeight) | 76 , fNumRows(desc.fHeight / desc.fRowHeight) |
77 , fTexture(NULL) | 77 , fTexture(NULL) |
78 , fRows(SkNEW_ARRAY(AtlasRow, fNumRows)) | 78 , fRows(SkNEW_ARRAY(AtlasRow, fNumRows)) |
79 , fLRUFront(NULL) | 79 , fLRUFront(NULL) |
80 , fLRUBack(NULL) { | 80 , fLRUBack(NULL) { |
81 GrAssert(fNumRows * fDesc.fRowHeight == fDesc.fHeight); | 81 SkASSERT(fNumRows * fDesc.fRowHeight == fDesc.fHeight); |
82 this->initLRU(); | 82 this->initLRU(); |
83 VALIDATE; | 83 VALIDATE; |
84 } | 84 } |
85 | 85 |
86 GrTextureStripAtlas::~GrTextureStripAtlas() { | 86 GrTextureStripAtlas::~GrTextureStripAtlas() { |
87 SkDELETE_ARRAY(fRows); | 87 SkDELETE_ARRAY(fRows); |
88 } | 88 } |
89 | 89 |
90 int GrTextureStripAtlas::lockRow(const SkBitmap& data) { | 90 int GrTextureStripAtlas::lockRow(const SkBitmap& data) { |
91 VALIDATE; | 91 VALIDATE; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 // that is not currently in use | 157 // that is not currently in use |
158 fDesc.fContext->writeTexturePixels(fTexture, | 158 fDesc.fContext->writeTexturePixels(fTexture, |
159 0, rowNumber * fDesc.fRowHeight, | 159 0, rowNumber * fDesc.fRowHeight, |
160 fDesc.fWidth, fDesc.fRowHeight, | 160 fDesc.fWidth, fDesc.fRowHeight, |
161 SkBitmapConfig2GrPixelConfig(data.con
fig()), | 161 SkBitmapConfig2GrPixelConfig(data.con
fig()), |
162 data.getPixels(), | 162 data.getPixels(), |
163 data.rowBytes(), | 163 data.rowBytes(), |
164 GrContext::kDontFlush_PixelOpsFlag); | 164 GrContext::kDontFlush_PixelOpsFlag); |
165 } | 165 } |
166 | 166 |
167 GrAssert(rowNumber >= 0); | 167 SkASSERT(rowNumber >= 0); |
168 VALIDATE; | 168 VALIDATE; |
169 return rowNumber; | 169 return rowNumber; |
170 } | 170 } |
171 | 171 |
172 void GrTextureStripAtlas::unlockRow(int row) { | 172 void GrTextureStripAtlas::unlockRow(int row) { |
173 VALIDATE; | 173 VALIDATE; |
174 --fRows[row].fLocks; | 174 --fRows[row].fLocks; |
175 --fLockedRows; | 175 --fLockedRows; |
176 GrAssert(fRows[row].fLocks >= 0 && fLockedRows >= 0); | 176 SkASSERT(fRows[row].fLocks >= 0 && fLockedRows >= 0); |
177 if (0 == fRows[row].fLocks) { | 177 if (0 == fRows[row].fLocks) { |
178 this->appendLRU(fRows + row); | 178 this->appendLRU(fRows + row); |
179 } | 179 } |
180 if (0 == fLockedRows) { | 180 if (0 == fLockedRows) { |
181 this->unlockTexture(); | 181 this->unlockTexture(); |
182 } | 182 } |
183 VALIDATE; | 183 VALIDATE; |
184 } | 184 } |
185 | 185 |
186 GrTextureStripAtlas::AtlasRow* GrTextureStripAtlas::getLRU() { | 186 GrTextureStripAtlas::AtlasRow* GrTextureStripAtlas::getLRU() { |
(...skipping 15 matching lines...) Expand all Loading... |
202 memset(key.fData32 + 1, 0, sizeof(key) - sizeof(uint32_t)); | 202 memset(key.fData32 + 1, 0, sizeof(key) - sizeof(uint32_t)); |
203 GrCacheID cacheID(gTextureStripAtlasDomain, key); | 203 GrCacheID cacheID(gTextureStripAtlasDomain, key); |
204 | 204 |
205 fTexture = fDesc.fContext->findAndRefTexture(texDesc, cacheID, ¶ms); | 205 fTexture = fDesc.fContext->findAndRefTexture(texDesc, cacheID, ¶ms); |
206 if (NULL == fTexture) { | 206 if (NULL == fTexture) { |
207 fTexture = fDesc.fContext->createTexture(¶ms, texDesc, cacheID, NULL
, 0); | 207 fTexture = fDesc.fContext->createTexture(¶ms, texDesc, cacheID, NULL
, 0); |
208 // This is a new texture, so all of our cache info is now invalid | 208 // This is a new texture, so all of our cache info is now invalid |
209 this->initLRU(); | 209 this->initLRU(); |
210 fKeyTable.rewind(); | 210 fKeyTable.rewind(); |
211 } | 211 } |
212 GrAssert(NULL != fTexture); | 212 SkASSERT(NULL != fTexture); |
213 } | 213 } |
214 | 214 |
215 void GrTextureStripAtlas::unlockTexture() { | 215 void GrTextureStripAtlas::unlockTexture() { |
216 GrAssert(NULL != fTexture && 0 == fLockedRows); | 216 SkASSERT(NULL != fTexture && 0 == fLockedRows); |
217 fTexture->unref(); | 217 fTexture->unref(); |
218 fTexture = NULL; | 218 fTexture = NULL; |
219 fDesc.fContext->purgeCache(); | 219 fDesc.fContext->purgeCache(); |
220 } | 220 } |
221 | 221 |
222 void GrTextureStripAtlas::initLRU() { | 222 void GrTextureStripAtlas::initLRU() { |
223 fLRUFront = NULL; | 223 fLRUFront = NULL; |
224 fLRUBack = NULL; | 224 fLRUBack = NULL; |
225 // Initially all the rows are in the LRU list | 225 // Initially all the rows are in the LRU list |
226 for (int i = 0; i < fNumRows; ++i) { | 226 for (int i = 0; i < fNumRows; ++i) { |
227 fRows[i].fKey = kEmptyAtlasRowKey; | 227 fRows[i].fKey = kEmptyAtlasRowKey; |
228 fRows[i].fNext = NULL; | 228 fRows[i].fNext = NULL; |
229 fRows[i].fPrev = NULL; | 229 fRows[i].fPrev = NULL; |
230 this->appendLRU(fRows + i); | 230 this->appendLRU(fRows + i); |
231 } | 231 } |
232 GrAssert(NULL == fLRUFront || NULL == fLRUFront->fPrev); | 232 SkASSERT(NULL == fLRUFront || NULL == fLRUFront->fPrev); |
233 GrAssert(NULL == fLRUBack || NULL == fLRUBack->fNext); | 233 SkASSERT(NULL == fLRUBack || NULL == fLRUBack->fNext); |
234 } | 234 } |
235 | 235 |
236 void GrTextureStripAtlas::appendLRU(AtlasRow* row) { | 236 void GrTextureStripAtlas::appendLRU(AtlasRow* row) { |
237 GrAssert(NULL == row->fPrev && NULL == row->fNext); | 237 SkASSERT(NULL == row->fPrev && NULL == row->fNext); |
238 if (NULL == fLRUFront && NULL == fLRUBack) { | 238 if (NULL == fLRUFront && NULL == fLRUBack) { |
239 fLRUFront = row; | 239 fLRUFront = row; |
240 fLRUBack = row; | 240 fLRUBack = row; |
241 } else { | 241 } else { |
242 row->fPrev = fLRUBack; | 242 row->fPrev = fLRUBack; |
243 fLRUBack->fNext = row; | 243 fLRUBack->fNext = row; |
244 fLRUBack = row; | 244 fLRUBack = row; |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 void GrTextureStripAtlas::removeFromLRU(AtlasRow* row) { | 248 void GrTextureStripAtlas::removeFromLRU(AtlasRow* row) { |
249 GrAssert(NULL != row); | 249 SkASSERT(NULL != row); |
250 if (NULL != row->fNext && NULL != row->fPrev) { | 250 if (NULL != row->fNext && NULL != row->fPrev) { |
251 row->fPrev->fNext = row->fNext; | 251 row->fPrev->fNext = row->fNext; |
252 row->fNext->fPrev = row->fPrev; | 252 row->fNext->fPrev = row->fPrev; |
253 } else { | 253 } else { |
254 if (NULL == row->fNext) { | 254 if (NULL == row->fNext) { |
255 GrAssert(row == fLRUBack); | 255 SkASSERT(row == fLRUBack); |
256 fLRUBack = row->fPrev; | 256 fLRUBack = row->fPrev; |
257 if (fLRUBack) { | 257 if (fLRUBack) { |
258 fLRUBack->fNext = NULL; | 258 fLRUBack->fNext = NULL; |
259 } | 259 } |
260 } | 260 } |
261 if (NULL == row->fPrev) { | 261 if (NULL == row->fPrev) { |
262 GrAssert(row == fLRUFront); | 262 SkASSERT(row == fLRUFront); |
263 fLRUFront = row->fNext; | 263 fLRUFront = row->fNext; |
264 if (fLRUFront) { | 264 if (fLRUFront) { |
265 fLRUFront->fPrev = NULL; | 265 fLRUFront->fPrev = NULL; |
266 } | 266 } |
267 } | 267 } |
268 } | 268 } |
269 row->fNext = NULL; | 269 row->fNext = NULL; |
270 row->fPrev = NULL; | 270 row->fPrev = NULL; |
271 } | 271 } |
272 | 272 |
273 int GrTextureStripAtlas::searchByKey(uint32_t key) { | 273 int GrTextureStripAtlas::searchByKey(uint32_t key) { |
274 AtlasRow target; | 274 AtlasRow target; |
275 target.fKey = key; | 275 target.fKey = key; |
276 return SkTSearch<const AtlasRow, | 276 return SkTSearch<const AtlasRow, |
277 GrTextureStripAtlas::KeyLess>((const AtlasRow**)fKeyTable.b
egin(), | 277 GrTextureStripAtlas::KeyLess>((const AtlasRow**)fKeyTable.b
egin(), |
278 fKeyTable.count(), | 278 fKeyTable.count(), |
279 &target, | 279 &target, |
280 sizeof(AtlasRow*)); | 280 sizeof(AtlasRow*)); |
281 } | 281 } |
282 | 282 |
283 #ifdef SK_DEBUG | 283 #ifdef SK_DEBUG |
284 void GrTextureStripAtlas::validate() { | 284 void GrTextureStripAtlas::validate() { |
285 | 285 |
286 // Our key table should be sorted | 286 // Our key table should be sorted |
287 uint32_t prev = 1 > fKeyTable.count() ? 0 : fKeyTable[0]->fKey; | 287 uint32_t prev = 1 > fKeyTable.count() ? 0 : fKeyTable[0]->fKey; |
288 for (int i = 1; i < fKeyTable.count(); ++i) { | 288 for (int i = 1; i < fKeyTable.count(); ++i) { |
289 GrAssert(prev < fKeyTable[i]->fKey); | 289 SkASSERT(prev < fKeyTable[i]->fKey); |
290 GrAssert(fKeyTable[i]->fKey != kEmptyAtlasRowKey); | 290 SkASSERT(fKeyTable[i]->fKey != kEmptyAtlasRowKey); |
291 prev = fKeyTable[i]->fKey; | 291 prev = fKeyTable[i]->fKey; |
292 } | 292 } |
293 | 293 |
294 int lruCount = 0; | 294 int lruCount = 0; |
295 // Validate LRU pointers, and count LRU entries | 295 // Validate LRU pointers, and count LRU entries |
296 GrAssert(NULL == fLRUFront || NULL == fLRUFront->fPrev); | 296 SkASSERT(NULL == fLRUFront || NULL == fLRUFront->fPrev); |
297 GrAssert(NULL == fLRUBack || NULL == fLRUBack->fNext); | 297 SkASSERT(NULL == fLRUBack || NULL == fLRUBack->fNext); |
298 for (AtlasRow* r = fLRUFront; r != NULL; r = r->fNext) { | 298 for (AtlasRow* r = fLRUFront; r != NULL; r = r->fNext) { |
299 if (NULL == r->fNext) { | 299 if (NULL == r->fNext) { |
300 GrAssert(r == fLRUBack); | 300 SkASSERT(r == fLRUBack); |
301 } else { | 301 } else { |
302 GrAssert(r->fNext->fPrev == r); | 302 SkASSERT(r->fNext->fPrev == r); |
303 } | 303 } |
304 ++lruCount; | 304 ++lruCount; |
305 } | 305 } |
306 | 306 |
307 int rowLocks = 0; | 307 int rowLocks = 0; |
308 int freeRows = 0; | 308 int freeRows = 0; |
309 | 309 |
310 for (int i = 0; i < fNumRows; ++i) { | 310 for (int i = 0; i < fNumRows; ++i) { |
311 rowLocks += fRows[i].fLocks; | 311 rowLocks += fRows[i].fLocks; |
312 if (0 == fRows[i].fLocks) { | 312 if (0 == fRows[i].fLocks) { |
313 ++freeRows; | 313 ++freeRows; |
314 bool inLRU = false; | 314 bool inLRU = false; |
315 // Step through the LRU and make sure it's present | 315 // Step through the LRU and make sure it's present |
316 for (AtlasRow* r = fLRUFront; r != NULL; r = r->fNext) { | 316 for (AtlasRow* r = fLRUFront; r != NULL; r = r->fNext) { |
317 if (r == &fRows[i]) { | 317 if (r == &fRows[i]) { |
318 inLRU = true; | 318 inLRU = true; |
319 break; | 319 break; |
320 } | 320 } |
321 } | 321 } |
322 GrAssert(inLRU); | 322 SkASSERT(inLRU); |
323 } else { | 323 } else { |
324 // If we are locked, we should have a key | 324 // If we are locked, we should have a key |
325 GrAssert(kEmptyAtlasRowKey != fRows[i].fKey); | 325 SkASSERT(kEmptyAtlasRowKey != fRows[i].fKey); |
326 } | 326 } |
327 | 327 |
328 // If we have a key != kEmptyAtlasRowKey, it should be in the key table | 328 // If we have a key != kEmptyAtlasRowKey, it should be in the key table |
329 GrAssert(fRows[i].fKey == kEmptyAtlasRowKey || this->searchByKey(fRows[i
].fKey) >= 0); | 329 SkASSERT(fRows[i].fKey == kEmptyAtlasRowKey || this->searchByKey(fRows[i
].fKey) >= 0); |
330 } | 330 } |
331 | 331 |
332 // Our count of locks should equal the sum of row locks, unless we ran out o
f rows and flushed, | 332 // Our count of locks should equal the sum of row locks, unless we ran out o
f rows and flushed, |
333 // in which case we'll have one more lock than recorded in the rows (to repr
esent the pending | 333 // in which case we'll have one more lock than recorded in the rows (to repr
esent the pending |
334 // lock of a row; which ensures we don't unlock the texture prematurely). | 334 // lock of a row; which ensures we don't unlock the texture prematurely). |
335 GrAssert(rowLocks == fLockedRows || rowLocks + 1 == fLockedRows); | 335 SkASSERT(rowLocks == fLockedRows || rowLocks + 1 == fLockedRows); |
336 | 336 |
337 // We should have one lru entry for each free row | 337 // We should have one lru entry for each free row |
338 GrAssert(freeRows == lruCount); | 338 SkASSERT(freeRows == lruCount); |
339 | 339 |
340 // If we have locked rows, we should have a locked texture, otherwise | 340 // If we have locked rows, we should have a locked texture, otherwise |
341 // it should be unlocked | 341 // it should be unlocked |
342 if (fLockedRows == 0) { | 342 if (fLockedRows == 0) { |
343 GrAssert(NULL == fTexture); | 343 SkASSERT(NULL == fTexture); |
344 } else { | 344 } else { |
345 GrAssert(NULL != fTexture); | 345 SkASSERT(NULL != fTexture); |
346 } | 346 } |
347 } | 347 } |
348 #endif | 348 #endif |
OLD | NEW |