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 |