Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 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 "GrRectanizer.h" | 10 #include "GrRectanizer.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 void GrFontCache::freeAll() { | 55 void GrFontCache::freeAll() { |
| 56 fCache.deleteAll(); | 56 fCache.deleteAll(); |
| 57 delete fAtlasMgr; | 57 delete fAtlasMgr; |
| 58 fAtlasMgr = NULL; | 58 fAtlasMgr = NULL; |
| 59 fHead = NULL; | 59 fHead = NULL; |
| 60 fTail = NULL; | 60 fTail = NULL; |
| 61 } | 61 } |
| 62 | 62 |
| 63 void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { | 63 void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { |
| 64 GrTextStrike* strike = fTail; | 64 GrTextStrike* strike = fTail; |
| 65 bool purge = true; | |
| 66 while (strike) { | |
| 67 if (strike == preserveStrike) { | |
| 68 strike = strike->fPrev; | |
| 69 continue; | |
| 70 } | |
| 71 GrTextStrike* strikeToPurge = strike; | |
| 72 strike = strikeToPurge->fPrev; | |
| 73 if (purge) { | |
| 74 // keep purging if we won't free up any atlases with this strike. | |
| 75 purge = (NULL == strikeToPurge->fAtlas); | |
| 76 int index = fCache.slowFindIndex(strikeToPurge); | |
| 77 GrAssert(index >= 0); | |
| 78 fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); | |
| 79 this->detachStrikeFromList(strikeToPurge); | |
| 80 delete strikeToPurge; | |
| 81 } else { | |
| 82 // for the remaining strikes, we just mark them unused | |
| 83 strikeToPurge->markAtlasesUnused(); | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) { | |
| 89 GrTextStrike* strike = fTail; | |
| 65 while (strike) { | 90 while (strike) { |
| 66 if (strike == preserveStrike) { | 91 if (strike == preserveStrike) { |
| 67 strike = strike->fPrev; | 92 strike = strike->fPrev; |
| 68 continue; | 93 continue; |
| 69 } | 94 } |
| 70 GrTextStrike* strikeToPurge = strike; | 95 GrTextStrike* strikeToPurge = strike; |
| 71 // keep going if we won't free up any atlases with this strike. | 96 strike = strikeToPurge->fPrev; |
| 72 strike = (NULL == strikeToPurge->fAtlas) ? strikeToPurge->fPrev : NULL; | 97 if (strikeToPurge->removeUnusedAtlas()) { |
| 73 int index = fCache.slowFindIndex(strikeToPurge); | 98 if (NULL == strikeToPurge->fAtlas) { |
| 74 GrAssert(index >= 0); | 99 int index = fCache.slowFindIndex(strikeToPurge); |
| 75 fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); | 100 GrAssert(index >= 0); |
| 76 this->detachStrikeFromList(strikeToPurge); | 101 fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()) ; |
| 77 delete strikeToPurge; | 102 this->detachStrikeFromList(strikeToPurge); |
| 103 delete strikeToPurge; | |
| 104 } | |
| 105 break; | |
| 106 } | |
| 78 } | 107 } |
| 79 } | 108 } |
| 80 | 109 |
| 81 #if GR_DEBUG | 110 #if GR_DEBUG |
| 82 void GrFontCache::validate() const { | 111 void GrFontCache::validate() const { |
| 83 int count = fCache.count(); | 112 int count = fCache.count(); |
| 84 if (0 == count) { | 113 if (0 == count) { |
| 85 GrAssert(!fHead); | 114 GrAssert(!fHead); |
| 86 GrAssert(!fTail); | 115 GrAssert(!fTail); |
| 87 } else if (1 == count) { | 116 } else if (1 == count) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 163 |
| 135 fMaskFormat = format; | 164 fMaskFormat = format; |
| 136 | 165 |
| 137 #if GR_DEBUG | 166 #if GR_DEBUG |
| 138 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); | 167 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); |
| 139 gCounter += 1; | 168 gCounter += 1; |
| 140 #endif | 169 #endif |
| 141 } | 170 } |
| 142 | 171 |
| 143 static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } | 172 static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } |
| 144 | 173 |
|
robertphillips
2013/08/02 15:23:50
invalidate_glyph?
GrGlyph*?
bsalomon
2013/08/02 15:30:35
ref to a ptr feels weird to me. We aren't assignin
jvanverth1
2013/08/02 21:49:27
The ref is needed because this function is used in
bsalomon
2013/08/05 13:09:54
Gotcha, maybe a comment // this is used with SkTDA
| |
| 174 static void InvalidateGlyph(GrGlyph*& glyph) { | |
| 175 if (glyph->fAtlas && !glyph->fAtlas->fUsed) { | |
| 176 glyph->fAtlas = NULL; | |
| 177 } | |
| 178 } | |
| 179 | |
| 145 GrTextStrike::~GrTextStrike() { | 180 GrTextStrike::~GrTextStrike() { |
| 146 GrAtlas::FreeLList(fAtlas); | 181 GrAtlas::FreeLList(fAtlas); |
| 147 fFontScalerKey->unref(); | 182 fFontScalerKey->unref(); |
| 148 fCache.getArray().visitAll(FreeGlyph); | 183 fCache.getArray().visitAll(FreeGlyph); |
| 149 | 184 |
| 150 #if GR_DEBUG | 185 #if GR_DEBUG |
| 151 gCounter -= 1; | 186 gCounter -= 1; |
| 152 // GrPrintf("~GrTextStrike %p %d\n", this, gCounter); | 187 // GrPrintf("~GrTextStrike %p %d\n", this, gCounter); |
| 153 #endif | 188 #endif |
| 154 } | 189 } |
| 155 | 190 |
| 156 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, | 191 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, |
| 157 GrFontScaler* scaler) { | 192 GrFontScaler* scaler) { |
| 158 SkIRect bounds; | 193 SkIRect bounds; |
| 159 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { | 194 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { |
| 160 return NULL; | 195 return NULL; |
| 161 } | 196 } |
| 162 | 197 |
| 163 GrGlyph* glyph = fPool.alloc(); | 198 GrGlyph* glyph = fPool.alloc(); |
| 164 glyph->init(packed, bounds); | 199 glyph->init(packed, bounds); |
| 165 fCache.insert(packed, glyph); | 200 fCache.insert(packed, glyph); |
| 166 return glyph; | 201 return glyph; |
| 167 } | 202 } |
| 168 | 203 |
| 204 bool GrTextStrike::removeUnusedAtlas() { | |
|
robertphillips
2013/08/02 15:23:50
Why is prev a GrAtlas**?
jvanverth1
2013/08/02 21:49:27
Moved to GrAtlas.cpp, but that's done so I don't h
| |
| 205 GrAtlas** prev = &fAtlas; | |
| 206 GrAtlas* atlas = fAtlas; | |
| 207 while (atlas) { | |
| 208 if (!atlas->fUsed) { | |
| 209 fCache.getArray().visitAll(InvalidateGlyph); | |
| 210 *prev = atlas->fNext; | |
| 211 fAtlasMgr->deleteAtlas(atlas); | |
| 212 atlas = *prev; | |
| 213 return true; | |
| 214 } else { | |
| 215 prev = &atlas->fNext; | |
| 216 atlas = atlas->fNext; | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 void GrTextStrike::markAtlasesUnused() { | |
| 224 GrAtlas* atlas = fAtlas; | |
|
robertphillips
2013/08/02 15:23:50
NULL !=?
jvanverth1
2013/08/02 21:49:27
Done.
| |
| 225 while (atlas) { | |
| 226 atlas->fUsed = false; | |
| 227 atlas = atlas->fNext; | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 | |
| 169 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { | 232 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
| 170 #if 0 // testing hack to force us to flush our cache often | 233 #if 0 // testing hack to force us to flush our cache often |
| 171 static int gCounter; | 234 static int gCounter; |
| 172 if ((++gCounter % 10) == 0) return false; | 235 if ((++gCounter % 10) == 0) return false; |
| 173 #endif | 236 #endif |
| 174 | 237 |
| 175 GrAssert(glyph); | 238 GrAssert(glyph); |
| 176 GrAssert(scaler); | 239 GrAssert(scaler); |
| 177 GrAssert(fCache.contains(glyph)); | 240 GrAssert(fCache.contains(glyph)); |
| 178 if (glyph->fAtlas) { | 241 if (glyph->fAtlas) { |
| 242 glyph->fAtlas->fUsed = true; | |
| 179 return true; | 243 return true; |
| 180 } | 244 } |
| 181 | 245 |
| 182 GrAutoRef ar(scaler); | 246 GrAutoRef ar(scaler); |
| 183 | 247 |
| 184 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); | 248 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
| 185 size_t size = glyph->fBounds.area() * bytesPerPixel; | 249 size_t size = glyph->fBounds.area() * bytesPerPixel; |
| 186 SkAutoSMalloc<1024> storage(size); | 250 SkAutoSMalloc<1024> storage(size); |
| 187 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), | 251 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), |
| 188 glyph->height(), | 252 glyph->height(), |
| 189 glyph->width() * bytesPerPixel, | 253 glyph->width() * bytesPerPixel, |
| 190 storage.get())) { | 254 storage.get())) { |
| 191 return false; | 255 return false; |
| 192 } | 256 } |
| 193 | 257 |
| 194 GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), | 258 GrAtlas* atlas = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), |
| 195 glyph->height(), storage.get(), | 259 glyph->height(), storage.get(), |
| 196 fMaskFormat, | 260 fMaskFormat, |
| 197 &glyph->fAtlasLocation); | 261 &glyph->fAtlasLocation); |
| 198 if (NULL == atlas) { | 262 if (NULL == atlas) { |
| 199 return false; | 263 return false; |
| 200 } | 264 } |
| 201 | 265 |
| 202 // update fAtlas as well, since they may be chained in a linklist | 266 glyph->fAtlas = atlas; |
| 203 glyph->fAtlas = fAtlas = atlas; | 267 atlas->fUsed = true; |
| 204 return true; | 268 return true; |
| 205 } | 269 } |
| OLD | NEW |