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

Side by Side Diff: src/gpu/batches/GrAtlasTextBatch.cpp

Issue 1466333003: Move GrAtlasTextBatch blob regeneration to template (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: minor Created 5 years, 1 month 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/batches/GrAtlasTextBatch.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 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 "GrAtlasTextBatch.h" 8 #include "GrAtlasTextBatch.h"
9 9
10 #include "GrBatchFontCache.h" 10 #include "GrBatchFontCache.h"
11 #include "GrBatchFlushState.h" 11 #include "GrBatchFlushState.h"
12 #include "GrBatchTest.h" 12 #include "GrBatchTest.h"
13 #include "GrResourceProvider.h" 13 #include "GrResourceProvider.h"
14 14
15 #include "SkDistanceFieldGen.h" 15 #include "SkDistanceFieldGen.h"
16 #include "SkGlyphCache.h" 16 #include "SkGlyphCache.h"
17 17
18 #include "effects/GrBitmapTextGeoProc.h" 18 #include "effects/GrBitmapTextGeoProc.h"
19 #include "effects/GrDistanceFieldGeoProc.h" 19 #include "effects/GrDistanceFieldGeoProc.h"
20 20
21 //////////////////////////////////////////////////////////////////////////////// ////////////////////
22 // A large template to handle regenerating the vertices of a textblob with as fe w branches as
23 // possible
24 template <bool regenPos, bool regenCol, bool regenTexCoords>
25 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS tride,
26 bool useDistanceFields, SkScalar transX, SkScalar tra nsY,
27 GrColor color) {
28 int width, height, u0, v0, u1, v1;
29 if (regenTexCoords) {
robertphillips 2015/11/23 18:42:52 mv width & height in here ?
30 SkASSERT(glyph);
31 width = glyph->fBounds.width();
32 height = glyph->fBounds.height();
33
34 if (useDistanceFields) {
35 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
36 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
37 u1 = u0 + width - 2 * SK_DistanceFieldInset;
38 v1 = v0 + height - 2 * SK_DistanceFieldInset;
39 } else {
40 u0 = glyph->fAtlasLocation.fX;
41 v0 = glyph->fAtlasLocation.fY;
42 u1 = u0 + width;
43 v1 = v0 + height;
44 }
45 }
46
robertphillips 2015/11/23 18:42:52 won'd -> won't ?
47 // This is a bit wonky, but sometimes we have LCD text, in which case we won 'd have color
48 // vertices, hence vertexStride - sizeof(SkIPoint16)
49 intptr_t colorOffset = sizeof(SkPoint);
50 intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
51
52 // V0
53 if (regenPos) {
54 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
55 point->fX += transX;
56 point->fY += transY;
57 }
58
59 if (regenCol) {
60 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
61 *vcolor = color;
62 }
63
64 if (regenTexCoords) {
65 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
66 textureCoords->set(u0, v0);
67 }
68 vertex += vertexStride;
69
70 // V1
71 if (regenPos) {
72 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
73 point->fX += transX;
74 point->fY += transY;
75 }
76
77 if (regenCol) {
78 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
79 *vcolor = color;
80 }
81
82 if (regenTexCoords) {
83 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
84 textureCoords->set(u0, v1);
85 }
86 vertex += vertexStride;
87
88 // V2
89 if (regenPos) {
90 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
91 point->fX += transX;
92 point->fY += transY;
93 }
94
95 if (regenCol) {
96 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
97 *vcolor = color;
98 }
99
100 if (regenTexCoords) {
101 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
102 textureCoords->set(u1, v1);
103 }
104 vertex += vertexStride;
105
106 // V3
107 if (regenPos) {
108 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
109 point->fX += transX;
110 point->fY += transY;
111 }
112
113 if (regenCol) {
114 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
115 *vcolor = color;
116 }
117
118 if (regenTexCoords) {
119 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
120 textureCoords->set(u1, v0);
121 }
122 }
123
124 typedef GrAtlasTextBlob Blob;
125 typedef Blob::Run Run;
126 typedef Run::SubRunInfo TextInfo;
127
128 template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
robertphillips 2015/11/23 18:42:52 That's a lot of parameters ...
129 void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Blob* blo b, Run* run,
130 TextInfo* info, SkGlyphCache** cache,
131 SkTypeface** typeface, GrFontScaler** scaler,
132 const SkDescriptor** desc, const GrGeometryProc essor* gp,
133 int glyphCount, size_t vertexStride,
134 GrColor color, SkScalar transX, SkScalar transY ) {
135 GrBatchTextStrike* strike = nullptr;
136 if (regenTexCoords) {
137 info->fBulkUseToken.reset();
138
139 // We can reuse if we have a valid strike and our descriptors / typeface are the
140 // same. The override descriptor is only for the non distance field tex t within
141 // a run
142 const SkDescriptor* newDesc = (run->fOverrideDescriptor && !this->usesDi stanceFields()) ?
143 run->fOverrideDescriptor->getDesc() :
144 run->fDescriptor.getDesc();
145 if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) ||
146 !((*desc)->equals(*newDesc))) {
147 if (*cache) {
148 SkGlyphCache::AttachCache(*cache);
149 }
150 *desc = newDesc;
151 *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc);
152 *scaler = GrTextContext::GetGrFontScaler(*cache);
153 strike = info->fStrike;
154 *typeface = run->fTypeface;
155 }
156
157 if (regenGlyphs) {
158 strike = fFontCache->getStrike(*scaler);
159 } else {
160 strike = info->fStrike;
161 }
162 }
163
164 bool brokenRun = false;
165 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
166 GrGlyph* glyph = nullptr;
167 if (regenTexCoords) {
168 size_t glyphOffset = glyphIdx + info->fGlyphStartIndex;
169
170 glyph = blob->fGlyphs[glyphOffset];
171 GrGlyph::PackedID id = glyph->fPackedID;
172 const SkGlyph& skGlyph = (*scaler)->grToSkGlyph(id);
173 if (regenGlyphs) {
174 // Get the id from the old glyph, and use the new strike to look up
175 // the glyph.
176 blob->fGlyphs[glyphOffset] = strike->getGlyph(skGlyph, id, this- >maskFormat(),
177 *scaler);
178 }
179 glyph = blob->fGlyphs[glyphOffset];
180 SkASSERT(glyph);
181 SkASSERT(id == glyph->fPackedID);
182 // We want to be able to assert this but cannot for testing purposes .
183 // once skbug:4143 has landed we can revist this assert
184 //SkASSERT(glyph->fMaskFormat == this->maskFormat());
185
186 if (!fFontCache->hasGlyph(glyph) &&
187 !strike->addGlyphToAtlas(target, glyph, *scaler, skGlyph, this-> maskFormat())) {
188 this->flush(target, flushInfo);
189 target->initDraw(gp, this->pipeline());
190 brokenRun = glyphIdx > 0;
191
192 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
193 glyph,
194 *scaler,
195 skGlyph,
196 this->maskFo rmat());
197 SkASSERT(success);
198 }
199 fFontCache->addGlyphToBulkAndSetUseToken(&info->fBulkUseToken, glyph ,
200 target->currentToken());
201 }
202
203 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
204 vertex += info->fVertexStartIndex;
205 vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph;
206 regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertex Stride,
207 this->usesDistanceFie lds(), transX,
208 transY, color);
209 flushInfo->fGlyphsToFlush++;
210 }
211
212 // We my have changed the color so update it here
213 run->fColor = color;
214 if (regenTexCoords) {
215 if (regenGlyphs) {
216 info->fStrike.reset(SkRef(strike));
217 }
218 info->fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGenerati on :
219 fFontCache->atlasGeneration(this->m askFormat());
220 }
221 }
222 //////////////////////////////////////////////////////////////////////////////// ///////////////////
223
21 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { 224 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
22 unsigned r = SkColorGetR(c); 225 unsigned r = SkColorGetR(c);
23 unsigned g = SkColorGetG(c); 226 unsigned g = SkColorGetG(c);
24 unsigned b = SkColorGetB(c); 227 unsigned b = SkColorGetB(c);
25 return GrColorPackRGBA(r, g, b, 0xff); 228 return GrColorPackRGBA(r, g, b, 0xff);
26 } 229 }
27 230
28 static const int kDistanceAdjustLumShift = 5; 231 static const int kDistanceAdjustLumShift = 5;
29 232
30 SkString GrAtlasTextBatch::dumpInfo() const { 233 SkString GrAtlasTextBatch::dumpInfo() const {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 } 277 }
75 opt.getOverrideColorIfSet(&fGeoData[0].fColor); 278 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
76 279
77 // setup batch properties 280 // setup batch properties
78 fBatch.fColorIgnored = !opt.readsColor(); 281 fBatch.fColorIgnored = !opt.readsColor();
79 fBatch.fColor = fGeoData[0].fColor; 282 fBatch.fColor = fGeoData[0].fColor;
80 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); 283 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
81 fBatch.fCoverageIgnored = !opt.readsCoverage(); 284 fBatch.fCoverageIgnored = !opt.readsCoverage();
82 } 285 }
83 286
287 enum RegenMask {
288 kNoRegen = 0x0,
289 kRegenPos = 0x1,
290 kRegenCol = 0x2,
291 kRegenTex = 0x4,
292 kRegenGlyph = 0x8 | kRegenTex, // we have to regenerate the texture coords w hen we regen glyphs
293
294 // combinations
295 kRegenPosCol = kRegenPos | kRegenCol,
296 kRegenPosTex = kRegenPos | kRegenTex,
297 kRegenPosTexGlyph = kRegenPos | kRegenGlyph,
298 kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex,
299 kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph,
300 kRegenColTex = kRegenCol | kRegenTex,
301 kRegenColTexGlyph = kRegenCol | kRegenGlyph,
302 };
303
304 #define REGEN_ARGS target, &flushInfo, blob, &run, &info, &cache, &typeface, &sc aler, &desc, gp, \
305 glyphCount, vertexStride, args.fColor, args.fTransX, args.fTr ansY
306
84 void GrAtlasTextBatch::onPrepareDraws(Target* target) { 307 void GrAtlasTextBatch::onPrepareDraws(Target* target) {
85 // if we have RGB, then we won't have any SkShaders so no need to use a loca lmatrix. 308 // if we have RGB, then we won't have any SkShaders so no need to use a loca lmatrix.
86 // TODO actually only invert if we don't have RGBA 309 // TODO actually only invert if we don't have RGBA
87 SkMatrix localMatrix; 310 SkMatrix localMatrix;
88 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) { 311 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
89 SkDebugf("Cannot invert viewmatrix\n"); 312 SkDebugf("Cannot invert viewmatrix\n");
90 return; 313 return;
91 } 314 }
92 315
93 GrTexture* texture = fFontCache->getTexture(this->maskFormat()); 316 GrTexture* texture = fFontCache->getTexture(this->maskFormat());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 GrFontScaler* scaler = nullptr; 369 GrFontScaler* scaler = nullptr;
147 SkTypeface* typeface = nullptr; 370 SkTypeface* typeface = nullptr;
148 371
149 for (int i = 0; i < fGeoCount; i++) { 372 for (int i = 0; i < fGeoCount; i++) {
150 Geometry& args = fGeoData[i]; 373 Geometry& args = fGeoData[i];
151 Blob* blob = args.fBlob; 374 Blob* blob = args.fBlob;
152 Run& run = blob->fRuns[args.fRun]; 375 Run& run = blob->fRuns[args.fRun];
153 TextInfo& info = run.fSubRunInfo[args.fSubRun]; 376 TextInfo& info = run.fSubRunInfo[args.fSubRun];
154 377
155 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat); 378 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat);
379
380 // Because the GrBatchFontCache may evict the strike a blob depends on u sing for
381 // generating its texture coords, we have to track whether or not the st rike has
382 // been abandoned. If it hasn't been abandoned, then we can use the GrG lyph*s as is
383 // otherwise we have to get the new strike, and use that to get the corr ect glyphs.
384 // Because we do not have the packed ids, and thus can't look up our gly phs in the
385 // new strike, we instead keep our ref to the old strike and use the pac ked ids from
386 // it. These ids will still be valid as long as we hold the ref. When we are done
387 // updating our cache of the GrGlyph*s, we drop our ref on the old strik e
388 bool regenerateGlyphs = info.fStrike->isAbandoned();
156 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen || 389 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen ||
157 info.fStrike->isAbandoned(); 390 regenerateGlyphs;
158 bool regenerateColors; 391 bool regenerateColors;
159 if (usesDistanceFields) { 392 if (usesDistanceFields) {
160 regenerateColors = !isLCD && run.fColor != args.fColor; 393 regenerateColors = !isLCD && run.fColor != args.fColor;
161 } else { 394 } else {
162 regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor != a rgs.fColor; 395 regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor != a rgs.fColor;
163 } 396 }
164 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f; 397 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f;
165 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 398 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
166 399
167 // We regenerate both texture coords and colors in the blob itself, and update the 400 uint32_t regenMaskBits = kNoRegen;
168 // atlas generation. If we don't end up purging any unused plots, we ca n avoid 401 regenMaskBits |= regeneratePositions ? kRegenPos : 0;
169 // regenerating the coords. We could take a finer grained approach to u pdating texture 402 regenMaskBits |= regenerateColors ? kRegenCol : 0;
170 // coords but its not clear if the extra bookkeeping would offset any ga ins. 403 regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0;
171 // To avoid looping over the glyphs twice, we do one loop and conditiona lly update color 404 regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0;
172 // or coords as needed. One final note, if we have to break a run for a n atlas eviction 405 RegenMask regenMask = (RegenMask)regenMaskBits;
173 // then we can't really trust the atlas has all of the correct data. At las evictions
174 // should be pretty rare, so we just always regenerate in those cases
175 if (regenerateTextureCoords || regenerateColors || regeneratePositions) {
176 // first regenerate texture coordinates / colors if need be
177 bool brokenRun = false;
178 406
robertphillips 2015/11/23 18:42:52 So we go from Booleans to a mask so we can go thro
179 // Because the GrBatchFontCache may evict the strike a blob depends on using for 407 switch (regenMask) {
180 // generating its texture coords, we have to track whether or not th e strike has 408 case kRegenPos: this->regenBlob<true, false, false, false>(REGEN_ARG S); break;
181 // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is 409 case kRegenCol: this->regenBlob<false, true, false, false>(REGEN_ARG S); break;
182 // otherwise we have to get the new strike, and use that to get the correct glyphs. 410 case kRegenTex: this->regenBlob<false, false, true, false>(REGEN_ARG S); break;
183 // Because we do not have the packed ids, and thus can't look up our glyphs in the 411 case kRegenGlyph: this->regenBlob<false, false, true, true>(REGEN_AR GS); break;
184 // new strike, we instead keep our ref to the old strike and use the packed ids from
185 // it. These ids will still be valid as long as we hold the ref. W hen we are done
186 // updating our cache of the GrGlyph*s, we drop our ref on the old s trike
187 bool regenerateGlyphs = false;
188 GrBatchTextStrike* strike = nullptr;
189 if (regenerateTextureCoords) {
190 info.fBulkUseToken.reset();
191 412
192 // We can reuse if we have a valid strike and our descriptors / typeface are the 413 // combinations
193 // same. The override descriptor is only for the non distance f ield text within 414 case kRegenPosCol: this->regenBlob<true, true, false, false>(REGEN_A RGS); break;
194 // a run 415 case kRegenPosTex: this->regenBlob<true, false, true, false>(REGEN_A RGS); break;
195 const SkDescriptor* newDesc = (run.fOverrideDescriptor && !usesD istanceFields) ? 416 case kRegenPosTexGlyph: this->regenBlob<true, false, true, true>(REG EN_ARGS); break;
196 run.fOverrideDescriptor->getDesc() : 417 case kRegenPosColTex: this->regenBlob<true, true, true, false>(REGEN _ARGS); break;
197 run.fDescriptor.getDesc(); 418 case kRegenPosColTexGlyph: this->regenBlob<true, true, true, true>(R EGEN_ARGS); break;
198 if (!cache || !SkTypeface::Equal(typeface, run.fTypeface) || 419 case kRegenColTex: this->regenBlob<false, true, true, false>(REGEN_A RGS); break;
199 !(desc->equals(*newDesc))) { 420 case kRegenColTexGlyph: this->regenBlob<false, true, true, true>(REG EN_ARGS); break;
200 if (cache) { 421 case kNoRegen:
201 SkGlyphCache::AttachCache(cache); 422 flushInfo.fGlyphsToFlush += glyphCount;
202 }
203 desc = newDesc;
204 cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
205 scaler = GrTextContext::GetGrFontScaler(cache);
206 strike = info.fStrike;
207 typeface = run.fTypeface;
208 }
209 423
210 if (info.fStrike->isAbandoned()) { 424 // set use tokens for all of the glyphs in our subrun. This is only valid if we
211 regenerateGlyphs = true; 425 // have a valid atlas generation
212 strike = fFontCache->getStrike(scaler); 426 fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentT oken(), maskFormat);
213 } else { 427 break;
214 strike = info.fStrike;
215 }
216 }
217
218 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
219 if (regenerateTextureCoords) {
220 size_t glyphOffset = glyphIdx + info.fGlyphStartIndex;
221
222 GrGlyph* glyph = blob->fGlyphs[glyphOffset];
223 GrGlyph::PackedID id = glyph->fPackedID;
224 const SkGlyph& skGlyph = scaler->grToSkGlyph(id);
225 if (regenerateGlyphs) {
226 // Get the id from the old glyph, and use the new strike to lookup
227 // the glyph.
228 blob->fGlyphs[glyphOffset] = strike->getGlyph(skGlyph, i d, maskFormat,
229 scaler);
230 }
231 glyph = blob->fGlyphs[glyphOffset];
232 SkASSERT(glyph);
233 SkASSERT(id == glyph->fPackedID);
234 // We want to be able to assert this but cannot for testing purposes.
235 // once skbug:4143 has landed we can revist this assert
236 //SkASSERT(glyph->fMaskFormat == this->maskFormat());
237
238 if (!fFontCache->hasGlyph(glyph) &&
239 !strike->addGlyphToAtlas(target, glyph, scaler, skGlyph, maskFormat)) {
240 this->flush(target, &flushInfo);
241 target->initDraw(gp, this->pipeline());
242 brokenRun = glyphIdx > 0;
243
244 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(targ et,
245 glyp h,
246 scal er,
247 skGl yph,
248 mask Format);
249 SkASSERT(success);
250 }
251 fFontCache->addGlyphToBulkAndSetUseToken(&info.fBulkUseToken , glyph,
252 target->currentToke n());
253
254 // Texture coords are the last vertex attribute so we get a pointer to the
255 // first one and then map with stride in regenerateTextureCo ords
256 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices );
257 vertex += info.fVertexStartIndex;
258 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
259 vertex += vertexStride - sizeof(SkIPoint16);
260
261 this->regenerateTextureCoords(glyph, vertex, vertexStride);
262 }
263
264 if (regenerateColors) {
265 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices );
266 vertex += info.fVertexStartIndex;
267 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + size of(SkPoint);
268 this->regenerateColors(vertex, vertexStride, args.fColor);
269 }
270
271 if (regeneratePositions) {
272 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices );
273 vertex += info.fVertexStartIndex;
274 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
275 SkScalar transX = args.fTransX;
276 SkScalar transY = args.fTransY;
277 this->regeneratePositions(vertex, vertexStride, transX, tran sY);
278 }
279 flushInfo.fGlyphsToFlush++;
280 }
281
282 // We my have changed the color so update it here
283 run.fColor = args.fColor;
284 if (regenerateTextureCoords) {
285 if (regenerateGlyphs) {
286 info.fStrike.reset(SkRef(strike));
287 }
288 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasG eneration :
289 fFontCache->atlasGeneration( maskFormat);
290 }
291 } else {
292 flushInfo.fGlyphsToFlush += glyphCount;
293
294 // set use tokens for all of the glyphs in our subrun. This is only valid if we
295 // have a valid atlas generation
296 fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentToken (), maskFormat);
297 } 428 }
298 429
299 // now copy all vertices 430 // now copy all vertices
300 size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex; 431 size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex;
301 memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCount); 432 memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCount);
302 433
303 currVertex += byteCount; 434 currVertex += byteCount;
304 } 435 }
436
305 // Make sure to attach the last cache if applicable 437 // Make sure to attach the last cache if applicable
306 if (cache) { 438 if (cache) {
307 SkGlyphCache::AttachCache(cache); 439 SkGlyphCache::AttachCache(cache);
308 } 440 }
309 this->flush(target, &flushInfo); 441 this->flush(target, &flushInfo);
310 } 442 }
311 443
312 void GrAtlasTextBatch::regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex,
313 size_t vertexStride) {
314 int width = glyph->fBounds.width();
315 int height = glyph->fBounds.height();
316
317 int u0, v0, u1, v1;
318 if (this->usesDistanceFields()) {
319 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
320 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
321 u1 = u0 + width - 2 * SK_DistanceFieldInset;
322 v1 = v0 + height - 2 * SK_DistanceFieldInset;
323 } else {
324 u0 = glyph->fAtlasLocation.fX;
325 v0 = glyph->fAtlasLocation.fY;
326 u1 = u0 + width;
327 v1 = v0 + height;
328 }
329
330 SkIPoint16* textureCoords;
331 // V0
332 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
333 textureCoords->set(u0, v0);
334 vertex += vertexStride;
335
336 // V1
337 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
338 textureCoords->set(u0, v1);
339 vertex += vertexStride;
340
341 // V2
342 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
343 textureCoords->set(u1, v1);
344 vertex += vertexStride;
345
346 // V3
347 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
348 textureCoords->set(u1, v0);
349 }
350
351 void GrAtlasTextBatch::regenerateColors(intptr_t vertex, size_t vertexStride, Gr Color color) {
352 for (int i = 0; i < kVerticesPerGlyph; i++) {
353 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
354 *vcolor = color;
355 vertex += vertexStride;
356 }
357 }
358
359 void GrAtlasTextBatch::regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar transX,
360 SkScalar transY) {
361 for (int i = 0; i < kVerticesPerGlyph; i++) {
362 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
363 point->fX += transX;
364 point->fY += transY;
365 vertex += vertexStride;
366 }
367 }
368
369 void GrAtlasTextBatch::flush(GrVertexBatch::Target* target, FlushInfo* flushInfo ) { 444 void GrAtlasTextBatch::flush(GrVertexBatch::Target* target, FlushInfo* flushInfo ) {
370 GrVertices vertices; 445 GrVertices vertices;
371 int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads(); 446 int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads();
372 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, 447 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
373 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, 448 flushInfo->fIndexBuffer, flushInfo->fVertexOffset,
374 kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyp hsToFlush, 449 kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyp hsToFlush,
375 maxGlyphsPerDraw); 450 maxGlyphsPerDraw);
376 target->draw(vertices); 451 target->draw(vertices);
377 flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush; 452 flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
378 flushInfo->fGlyphsToFlush = 0; 453 flushInfo->fGlyphsToFlush = 0;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 return GrDistanceFieldA8TextGeoProc::Create(color, 573 return GrDistanceFieldA8TextGeoProc::Create(color,
499 viewMatrix, 574 viewMatrix,
500 texture, 575 texture,
501 params, 576 params,
502 flags, 577 flags,
503 this->usesLocalCoords()); 578 this->usesLocalCoords());
504 #endif 579 #endif
505 } 580 }
506 581
507 } 582 }
OLDNEW
« no previous file with comments | « src/gpu/batches/GrAtlasTextBatch.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698