Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: src/gpu/GrFontCache.cpp

Issue 1104343003: remove old text contexts and fontcache (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweak Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrFontCache.h ('k') | src/gpu/GrStencilAndCoverTextContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrFontCache.h"
9 #include "GrFontAtlasSizes.h"
10 #include "GrGpu.h"
11 #include "GrRectanizer.h"
12 #include "GrSurfacePriv.h"
13 #include "SkString.h"
14
15 #include "SkDistanceFieldGen.h"
16
17 ///////////////////////////////////////////////////////////////////////////////
18
19 #define FONT_CACHE_STATS 0
20 #if FONT_CACHE_STATS
21 static int g_PurgeCount = 0;
22 #endif
23
24 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
25 gpu->ref();
26 for (int i = 0; i < kAtlasCount; ++i) {
27 fAtlases[i] = NULL;
28 }
29
30 fHead = fTail = NULL;
31 }
32
33 GrFontCache::~GrFontCache() {
34 SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache);
35 while (!iter.done()) {
36 SkDELETE(&(*iter));
37 ++iter;
38 }
39 for (int i = 0; i < kAtlasCount; ++i) {
40 delete fAtlases[i];
41 }
42 fGpu->unref();
43 #if FONT_CACHE_STATS
44 SkDebugf("Num purges: %d\n", g_PurgeCount);
45 #endif
46 }
47
48 static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
49 static const GrPixelConfig sPixelConfigs[] = {
50 kAlpha_8_GrPixelConfig,
51 kRGB_565_GrPixelConfig,
52 kSkia8888_GrPixelConfig
53 };
54 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sPixelConfigs) == kMaskFormatCount, array_s ize_mismatch);
55
56 return sPixelConfigs[format];
57 }
58
59 static int mask_format_to_atlas_index(GrMaskFormat format) {
60 static const int sAtlasIndices[] = {
61 GrFontCache::kA8_AtlasType,
62 GrFontCache::k565_AtlasType,
63 GrFontCache::k8888_AtlasType
64 };
65 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_s ize_mismatch);
66
67 SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount);
68 return sAtlasIndices[format];
69 }
70
71 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler) {
72 GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, (this, scaler->getKey()));
73 fCache.add(strike);
74
75 if (fHead) {
76 fHead->fPrev = strike;
77 } else {
78 SkASSERT(NULL == fTail);
79 fTail = strike;
80 }
81 strike->fPrev = NULL;
82 strike->fNext = fHead;
83 fHead = strike;
84
85 return strike;
86 }
87
88 void GrFontCache::freeAll() {
89 SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache);
90 while (!iter.done()) {
91 SkDELETE(&(*iter));
92 ++iter;
93 }
94 fCache.rewind();
95 for (int i = 0; i < kAtlasCount; ++i) {
96 delete fAtlases[i];
97 fAtlases[i] = NULL;
98 }
99 fHead = NULL;
100 fTail = NULL;
101 }
102
103 void GrFontCache::purgeStrike(GrTextStrike* strike) {
104 fCache.remove(*(strike->fFontScalerKey));
105 this->detachStrikeFromList(strike);
106 delete strike;
107 }
108
109
110 GrPlot* GrFontCache::addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* u sage,
111 int width, int height, const void* image,
112 SkIPoint16* loc) {
113 GrPixelConfig config = mask_format_to_pixel_config(format);
114 int atlasIndex = mask_format_to_atlas_index(format);
115 if (NULL == fAtlases[atlasIndex]) {
116 if (kA8_GrMaskFormat == format) {
117 SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_A8_TEXTURE_WIDTH,
118 GR_FONT_ATLAS_TEXTURE_HEIGHT);
119 fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSu rfaceFlags,
120 textureSize,
121 GR_FONT_ATLAS_A8_NUM_PLO TS_X,
122 GR_FONT_ATLAS_NUM_PLOTS_ Y,
123 true));
124 } else {
125 SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_TEXTURE_WIDTH,
126 GR_FONT_ATLAS_TEXTURE_HEIGHT);
127 fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSu rfaceFlags,
128 textureSize,
129 GR_FONT_ATLAS_NUM_PLOTS_ X,
130 GR_FONT_ATLAS_NUM_PLOTS_ Y,
131 true));
132 }
133 }
134 return fAtlases[atlasIndex]->addToAtlas(usage, width, height, image, loc);
135 }
136
137
138 bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* gl yph) {
139 SkASSERT(preserveStrike);
140
141 int index = mask_format_to_atlas_index(glyph->fMaskFormat);
142 GrAtlas* atlas = fAtlases[index];
143 GrPlot* plot = atlas->getUnusedPlot();
144 if (NULL == plot) {
145 return false;
146 }
147 plot->resetRects();
148
149 GrTextStrike* strike = fHead;
150 while (strike) {
151 GrTextStrike* strikeToPurge = strike;
152 strike = strikeToPurge->fNext;
153 strikeToPurge->removePlot(plot);
154
155 // clear out any empty strikes (except this one)
156 if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty ()) {
157 this->purgeStrike(strikeToPurge);
158 }
159 }
160
161 #if FONT_CACHE_STATS
162 ++g_PurgeCount;
163 #endif
164
165 return true;
166 }
167
168 #ifdef SK_DEBUG
169 void GrFontCache::validate() const {
170 int count = fCache.count();
171 if (0 == count) {
172 SkASSERT(!fHead);
173 SkASSERT(!fTail);
174 } else if (1 == count) {
175 SkASSERT(fHead == fTail);
176 } else {
177 SkASSERT(fHead != fTail);
178 }
179
180 int count2 = 0;
181 const GrTextStrike* strike = fHead;
182 while (strike) {
183 count2 += 1;
184 strike = strike->fNext;
185 }
186 SkASSERT(count == count2);
187
188 count2 = 0;
189 strike = fTail;
190 while (strike) {
191 count2 += 1;
192 strike = strike->fPrev;
193 }
194 SkASSERT(count == count2);
195 }
196 #endif
197
198 void GrFontCache::dump() const {
199 static int gDumpCount = 0;
200 for (int i = 0; i < kAtlasCount; ++i) {
201 if (fAtlases[i]) {
202 GrTexture* texture = fAtlases[i]->getTexture();
203 if (texture) {
204 SkString filename;
205 #ifdef SK_BUILD_FOR_ANDROID
206 filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
207 #else
208 filename.printf("fontcache_%d%d.png", gDumpCount, i);
209 #endif
210 texture->surfacePriv().savePixels(filename.c_str());
211 }
212 }
213 }
214 ++gDumpCount;
215 }
216
217 ///////////////////////////////////////////////////////////////////////////////
218
219 #ifdef SK_DEBUG
220 static int gCounter;
221 #endif
222
223 /*
224 The text strike is specific to a given font/style/matrix setup, which is
225 represented by the GrHostFontScaler object we are given in getGlyph().
226
227 We map a 32bit glyphID to a GrGlyph record, which in turn points to a
228 atlas and a position within that texture.
229 */
230
231 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key)
232 : fPool(9/*start allocations at 512 bytes*/) {
233 fFontScalerKey = key;
234 fFontScalerKey->ref();
235
236 fFontCache = cache; // no need to ref, it won't go away before we do
237
238 #ifdef SK_DEBUG
239 // SkDebugf(" GrTextStrike %p %d\n", this, gCounter);
240 gCounter += 1;
241 #endif
242 }
243
244 GrTextStrike::~GrTextStrike() {
245 fFontScalerKey->unref();
246 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
247 while (!iter.done()) {
248 (*iter).free();
249 ++iter;
250 }
251
252 #ifdef SK_DEBUG
253 gCounter -= 1;
254 // SkDebugf("~GrTextStrike %p %d\n", this, gCounter);
255 #endif
256 }
257
258 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
259 GrFontScaler* scaler) {
260 SkIRect bounds;
261 if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(packed)) {
262 if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) {
263 return NULL;
264 }
265 } else {
266 if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
267 return NULL;
268 }
269 }
270 GrMaskFormat format = scaler->getPackedGlyphMaskFormat(packed);
271
272 GrGlyph* glyph = (GrGlyph*)fPool.alloc(sizeof(GrGlyph), SK_MALLOC_THROW);
273 glyph->init(packed, bounds, format);
274 fCache.add(glyph);
275 return glyph;
276 }
277
278 void GrTextStrike::removePlot(const GrPlot* plot) {
279 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
280 while (!iter.done()) {
281 if (plot == (*iter).fPlot) {
282 (*iter).fPlot = NULL;
283 }
284 ++iter;
285 }
286
287 GrAtlas::RemovePlot(&fPlotUsage, plot);
288 }
289
290 bool GrTextStrike::glyphTooLargeForAtlas(GrGlyph* glyph) {
291 int width = glyph->fBounds.width();
292 int height = glyph->fBounds.height();
293 bool useDistanceField =
294 (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle (glyph->fPackedID));
295 int pad = useDistanceField ? 2 * SK_DistanceFieldPad : 0;
296 int plotWidth = (kA8_GrMaskFormat == glyph->fMaskFormat) ? GR_FONT_ATLAS_A8_ PLOT_WIDTH
297 : GR_FONT_ATLAS_PLO T_WIDTH;
298 if (width + pad > plotWidth) {
299 return true;
300 }
301 if (height + pad > GR_FONT_ATLAS_PLOT_HEIGHT) {
302 return true;
303 }
304
305 return false;
306 }
307
308 bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
309 #if 0 // testing hack to force us to flush our cache often
310 static int gCounter;
311 if ((++gCounter % 10) == 0) return false;
312 #endif
313
314 SkASSERT(glyph);
315 SkASSERT(scaler);
316 SkASSERT(fCache.find(glyph->fPackedID));
317 SkASSERT(NULL == glyph->fPlot);
318
319 SkAutoUnref ar(SkSafeRef(scaler));
320
321 int bytesPerPixel = GrMaskFormatBytesPerPixel(glyph->fMaskFormat);
322
323 size_t size = glyph->fBounds.area() * bytesPerPixel;
324 GrAutoMalloc<1024> storage(size);
325
326 if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedI D)) {
327 if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(),
328 glyph->height(),
329 storage.get())) {
330 return false;
331 }
332 } else {
333 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
334 glyph->height(),
335 glyph->width() * bytesPerPixel,
336 storage.get())) {
337 return false;
338 }
339 }
340
341 GrPlot* plot = fFontCache->addToAtlas(glyph->fMaskFormat, &fPlotUsage,
342 glyph->width(), glyph->height(),
343 storage.get(), &glyph->fAtlasLocation) ;
344
345 if (NULL == plot) {
346 return false;
347 }
348
349 glyph->fPlot = plot;
350 return true;
351 }
OLDNEW
« no previous file with comments | « src/gpu/GrFontCache.h ('k') | src/gpu/GrStencilAndCoverTextContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698