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

Side by Side Diff: src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp

Issue 1698503002: Remove last bit of privacy violation for GrAtlasTextBlob (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase + nits Created 4 years, 10 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/text/GrAtlasTextBlob.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
(Empty)
1 /*
2 * Copyright 2016 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 "GrAtlasTextBlob.h"
9
10 #include "GrBatchFlushState.h"
11
12 #include "SkDistanceFieldGen.h"
13 #include "SkGlyphCache.h"
14
15 #include "batches/GrAtlasTextBatch.h"
16
17 //////////////////////////////////////////////////////////////////////////////// ////////////////////
18 // A large template to handle regenerating the vertices of a textblob with as fe w branches as
19 // possible
20 template <bool regenPos, bool regenCol, bool regenTexCoords>
21 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS tride,
22 bool useDistanceFields, SkScalar transX, SkScalar tra nsY,
23 GrColor color) {
24 int u0, v0, u1, v1;
25 if (regenTexCoords) {
26 SkASSERT(glyph);
27 int width = glyph->fBounds.width();
28 int height = glyph->fBounds.height();
29
30 if (useDistanceFields) {
31 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
32 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
33 u1 = u0 + width - 2 * SK_DistanceFieldInset;
34 v1 = v0 + height - 2 * SK_DistanceFieldInset;
35 } else {
36 u0 = glyph->fAtlasLocation.fX;
37 v0 = glyph->fAtlasLocation.fY;
38 u1 = u0 + width;
39 v1 = v0 + height;
40 }
41 }
42
43 // This is a bit wonky, but sometimes we have LCD text, in which case we won 't have color
44 // vertices, hence vertexStride - sizeof(SkIPoint16)
45 intptr_t colorOffset = sizeof(SkPoint);
46 intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
47
48 // V0
49 if (regenPos) {
50 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
51 point->fX += transX;
52 point->fY += transY;
53 }
54
55 if (regenCol) {
56 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
57 *vcolor = color;
58 }
59
60 if (regenTexCoords) {
61 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
62 textureCoords->set(u0, v0);
63 }
64 vertex += vertexStride;
65
66 // V1
67 if (regenPos) {
68 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
69 point->fX += transX;
70 point->fY += transY;
71 }
72
73 if (regenCol) {
74 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
75 *vcolor = color;
76 }
77
78 if (regenTexCoords) {
79 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
80 textureCoords->set(u0, v1);
81 }
82 vertex += vertexStride;
83
84 // V2
85 if (regenPos) {
86 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
87 point->fX += transX;
88 point->fY += transY;
89 }
90
91 if (regenCol) {
92 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
93 *vcolor = color;
94 }
95
96 if (regenTexCoords) {
97 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
98 textureCoords->set(u1, v1);
99 }
100 vertex += vertexStride;
101
102 // V3
103 if (regenPos) {
104 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
105 point->fX += transX;
106 point->fY += transY;
107 }
108
109 if (regenCol) {
110 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
111 *vcolor = color;
112 }
113
114 if (regenTexCoords) {
115 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo ordOffset);
116 textureCoords->set(u1, v0);
117 }
118 }
119
120 template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
121 void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
122 GrBatchFontCache* fontCache,
123 GrBlobRegenHelper *helper,
124 Run* run,
125 Run::SubRunInfo* info, SkGlyphCache** cache,
126 SkTypeface** typeface, GrFontScaler** scaler,
127 const SkDescriptor** desc,
128 int glyphCount, size_t vertexStride,
129 GrColor color, SkScalar transX,
130 SkScalar transY) const {
131 static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along reg enGlyphs");
132 GrBatchTextStrike* strike = nullptr;
133 if (regenTexCoords) {
134 info->resetBulkUseToken();
135
136 // We can reuse if we have a valid strike and our descriptors / typeface are the
137 // same. The override descriptor is only for the non distance field tex t within
138 // a run
139 const SkDescriptor* newDesc = (run->fOverrideDescriptor && !info->drawAs DistanceFields()) ?
140 run->fOverrideDescriptor->getDesc() :
141 run->fDescriptor.getDesc();
142 if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) ||
143 !((*desc)->equals(*newDesc))) {
144 if (*cache) {
145 SkGlyphCache::AttachCache(*cache);
146 }
147 *desc = newDesc;
148 *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc);
149 *scaler = GrTextContext::GetGrFontScaler(*cache);
150 *typeface = run->fTypeface;
151 }
152
153 if (regenGlyphs) {
154 strike = fontCache->getStrike(*scaler);
155 } else {
156 strike = info->strike();
157 }
158 }
159
160 bool brokenRun = false;
161 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
162 GrGlyph* glyph = nullptr;
163 if (regenTexCoords) {
164 size_t glyphOffset = glyphIdx + info->glyphStartIndex();
165
166 if (regenGlyphs) {
167 // Get the id from the old glyph, and use the new strike to look up
168 // the glyph.
169 GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID;
170 fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), *scaler);
171 SkASSERT(id == fGlyphs[glyphOffset]->fPackedID);
172 }
173 glyph = fGlyphs[glyphOffset];
174 SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat());
175
176 if (!fontCache->hasGlyph(glyph) &&
177 !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskForma t())) {
178 helper->flush();
179 brokenRun = glyphIdx > 0;
180
181 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
182 glyph,
183 *scaler,
184 info->maskFo rmat());
185 SkASSERT(success);
186 }
187 fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph,
188 target->currentToken());
189 }
190
191 intptr_t vertex = reinterpret_cast<intptr_t>(fVertices);
192 vertex += info->vertexStartIndex();
193 vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph;
194 regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertex Stride,
195 info->drawAsDistanceF ields(), transX,
196 transY, color);
197 helper->incGlyphCount();
198 }
199
200 // We may have changed the color so update it here
201 info->setColor(color);
202 if (regenTexCoords) {
203 if (regenGlyphs) {
204 info->setStrike(strike);
205 }
206 info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGenerati on :
207 fontCache->atlasGeneration(info->maskFormat())) ;
208 }
209 }
210
211 enum RegenMask {
212 kNoRegen = 0x0,
213 kRegenPos = 0x1,
214 kRegenCol = 0x2,
215 kRegenTex = 0x4,
216 kRegenGlyph = 0x8 | kRegenTex, // we have to regenerate the texture coords w hen we regen glyphs
217
218 // combinations
219 kRegenPosCol = kRegenPos | kRegenCol,
220 kRegenPosTex = kRegenPos | kRegenTex,
221 kRegenPosTexGlyph = kRegenPos | kRegenGlyph,
222 kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex,
223 kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph,
224 kRegenColTex = kRegenCol | kRegenTex,
225 kRegenColTexGlyph = kRegenCol | kRegenGlyph,
226 };
227
228 #define REGEN_ARGS target, fontCache, helper, &run, &info, cache, typeface, scal er, desc, \
229 *glyphCount, vertexStride, color, transX, transY
230
231 void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
232 GrBatchFontCache* fontCache,
233 GrBlobRegenHelper *helper,
234 int runIndex, int subRunIndex, SkGlyphCache** cache,
235 SkTypeface** typeface, GrFontScaler** scaler,
236 const SkDescriptor** desc, size_t vertexStrid e,
237 GrColor color, SkScalar transX,
238 SkScalar transY,
239 void** vertices, size_t* byteCount, int* glyp hCount) {
240 Run& run = fRuns[runIndex];
241 Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex];
242
243 uint64_t currentAtlasGen = fontCache->atlasGeneration(info.maskFormat());
244
245 // Because the GrBatchFontCache may evict the strike a blob depends on using for
246 // generating its texture coords, we have to track whether or not the strike has
247 // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph *s as is
248 // otherwise we have to get the new strike, and use that to get the correct glyphs.
249 // Because we do not have the packed ids, and thus can't look up our glyphs in the
250 // new strike, we instead keep our ref to the old strike and use the packed ids from
251 // it. These ids will still be valid as long as we hold the ref. When we a re done
252 // updating our cache of the GrGlyph*s, we drop our ref on the old strike
253 bool regenerateGlyphs = info.strike()->isAbandoned();
254 bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen ||
255 regenerateGlyphs;
256 bool regenerateColors = kARGB_GrMaskFormat != info.maskFormat() &&
257 info.color() != color;
258 bool regeneratePositions = transX != 0.f || transY != 0.f;
259 *glyphCount = info.glyphCount();
260
261 uint32_t regenMaskBits = kNoRegen;
262 regenMaskBits |= regeneratePositions ? kRegenPos : 0;
263 regenMaskBits |= regenerateColors ? kRegenCol : 0;
264 regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0;
265 regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0;
266 RegenMask regenMask = (RegenMask)regenMaskBits;
267
268 switch (regenMask) {
269 case kRegenPos: this->regenInBatch<true, false, false, false>(REGEN_ARGS ); break;
270 case kRegenCol: this->regenInBatch<false, true, false, false>(REGEN_ARGS ); break;
271 case kRegenTex: this->regenInBatch<false, false, true, false>(REGEN_ARGS ); break;
272 case kRegenGlyph: this->regenInBatch<false, false, true, true>(REGEN_ARG S); break;
273
274 // combinations
275 case kRegenPosCol: this->regenInBatch<true, true, false, false>(REGEN_AR GS); break;
276 case kRegenPosTex: this->regenInBatch<true, false, true, false>(REGEN_AR GS); break;
277 case kRegenPosTexGlyph: this->regenInBatch<true, false, true, true>(REGE N_ARGS); break;
278 case kRegenPosColTex: this->regenInBatch<true, true, true, false>(REGEN_ ARGS); break;
279 case kRegenPosColTexGlyph: this->regenInBatch<true, true, true, true>(RE GEN_ARGS); break;
280 case kRegenColTex: this->regenInBatch<false, true, true, false>(REGEN_AR GS); break;
281 case kRegenColTexGlyph: this->regenInBatch<false, true, true, true>(REGE N_ARGS); break;
282 case kNoRegen:
283 helper->incGlyphCount(*glyphCount);
284
285 // set use tokens for all of the glyphs in our subrun. This is only valid if we
286 // have a valid atlas generation
287 fontCache->setUseTokenBulk(*info.bulkUseToken(), target->currentToke n(),
288 info.maskFormat());
289 break;
290 }
291
292 *byteCount = info.byteCount();
293 *vertices = fVertices + info.vertexStartIndex();
294 }
OLDNEW
« no previous file with comments | « src/gpu/text/GrAtlasTextBlob.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698