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

Side by Side Diff: src/gpu/GrAtlasTextBlob.h

Issue 1521453002: Move all text stuff to its own folder (Closed) Base URL: https://skia.googlesource.com/skia.git@cleanuptext11textutils2
Patch Set: Created 5 years 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 | « gyp/gpu.gypi ('k') | src/gpu/GrAtlasTextBlob.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 2015 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 #ifndef GrAtlasTextBlob_DEFINED
9 #define GrAtlasTextBlob_DEFINED
10
11 #include "GrBatchAtlas.h"
12 #include "GrBatchFontCache.h"
13 #include "GrColor.h"
14 #include "GrMemoryPool.h"
15 #include "SkDescriptor.h"
16 #include "SkMaskFilter.h"
17 #include "SkSurfaceProps.h"
18 #include "SkTInternalLList.h"
19
20 struct GrDistanceFieldAdjustTable;
21 class GrTextContext;
22 class SkDrawFilter;
23 class SkTextBlob;
24 class SkTextBlobRunIterator;
25
26 // With this flag enabled, the GrAtlasTextContext will, as a sanity check, regen erate every blob
27 // that comes in to verify the integrity of its cache
28 //#define CACHE_SANITY_CHECK // VERY SLOW
29
30 /*
31 * A GrAtlasTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
32 * on the GPU. These are initially created with valid positions and colors, but invalid
33 * texture coordinates. The GrAtlasTextBlob itself has a few Blob-wide properti es, and also
34 * consists of a number of runs. Runs inside a blob are flushed individually so they can be
35 * reordered.
36 *
37 * The only thing(aside from a memcopy) required to flush a GrAtlasTextBlob is t o ensure that
38 * the GrAtlas will not evict anything the Blob needs.
39 *
40 * Note: This struct should really be named GrCachedAtasTextBlob, but that is to o verbose.
41 *
42 * *WARNING* If you add new fields to this struct, then you may need to to updat e AssertEqual
43 */
44 class GrAtlasTextBlob : public SkNVRefCnt<GrAtlasTextBlob> {
45 public:
46 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrAtlasTextBlob);
47
48 /*
49 * Each Run inside of the blob can have its texture coordinates regenerated if required.
50 * To determine if regeneration is necessary, fAtlasGeneration is used. If there have been
51 * any evictions inside of the atlas, then we will simply regenerate Runs. We could track
52 * this at a more fine grained level, but its not clear if this is worth it, as evictions
53 * should be fairly rare.
54 *
55 * One additional point, each run can contain glyphs with any of the three m ask formats.
56 * We call these SubRuns. Because a subrun must be a contiguous range, we h ave to create
57 * a new subrun each time the mask format changes in a run. In theory, a ru n can have as
58 * many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8. In
59 * practice, the vast majority of runs have only a single subrun.
60 *
61 * Finally, for runs where the entire thing is too large for the GrAtlasText Context to
62 * handle, we have a bit to mark the run as flusahable via rendering as path s. It is worth
63 * pointing. It would be a bit expensive to figure out ahead of time whether or not a run
64 * can flush in this manner, so we always allocate vertices for the run, reg ardless of
65 * whether or not it is too large. The benefit of this strategy is that we can always reuse
66 * a blob allocation regardless of viewmatrix changes. We could store posit ions for these
67 * glyphs. However, its not clear if this is a win because we'd still have to either go the
68 * glyph cache to get the path at flush time, or hold onto the path in the c ache, which
69 * would greatly increase the memory of these cached items.
70 */
71 struct Run {
72 Run()
73 : fInitialized(false)
74 , fDrawAsPaths(false) {
75 fVertexBounds.setLargestInverted();
76 // To ensure we always have one subrun, we push back a fresh run her e
77 fSubRunInfo.push_back();
78 }
79 struct SubRunInfo {
80 SubRunInfo()
81 : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration)
82 , fVertexStartIndex(0)
83 , fVertexEndIndex(0)
84 , fGlyphStartIndex(0)
85 , fGlyphEndIndex(0)
86 , fColor(GrColor_ILLEGAL)
87 , fMaskFormat(kA8_GrMaskFormat)
88 , fDrawAsDistanceFields(false)
89 , fUseLCDText(false) {}
90 SubRunInfo(const SubRunInfo& that)
91 : fBulkUseToken(that.fBulkUseToken)
92 , fStrike(SkSafeRef(that.fStrike.get()))
93 , fAtlasGeneration(that.fAtlasGeneration)
94 , fVertexStartIndex(that.fVertexStartIndex)
95 , fVertexEndIndex(that.fVertexEndIndex)
96 , fGlyphStartIndex(that.fGlyphStartIndex)
97 , fGlyphEndIndex(that.fGlyphEndIndex)
98 , fColor(that.fColor)
99 , fMaskFormat(that.fMaskFormat)
100 , fDrawAsDistanceFields(that.fDrawAsDistanceFields)
101 , fUseLCDText(that.fUseLCDText) {
102 }
103
104 // TODO when this object is more internal, drop the privacy
105 void resetBulkUseToken() { fBulkUseToken.reset(); }
106 GrBatchAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUse Token; }
107 void setStrike(GrBatchTextStrike* strike) { fStrike.reset(SkRef(stri ke)); }
108 GrBatchTextStrike* strike() const { return fStrike.get(); }
109
110 void setAtlasGeneration(uint64_t atlasGeneration) { fAtlasGeneration = atlasGeneration;}
111 uint64_t atlasGeneration() const { return fAtlasGeneration; }
112
113 size_t byteCount() const { return fVertexEndIndex - fVertexStartInde x; }
114 size_t vertexStartIndex() const { return fVertexStartIndex; }
115 size_t vertexEndIndex() const { return fVertexEndIndex; }
116 void appendVertices(size_t vertexStride) {
117 fVertexEndIndex += vertexStride * kVerticesPerGlyph;
118 }
119
120 uint32_t glyphCount() const { return fGlyphEndIndex - fGlyphStartInd ex; }
121 uint32_t glyphStartIndex() const { return fGlyphStartIndex; }
122 uint32_t glyphEndIndex() const { return fGlyphEndIndex; }
123 void glyphAppended() { fGlyphEndIndex++; }
124 void setColor(GrColor color) { fColor = color; }
125 GrColor color() const { return fColor; }
126 void setMaskFormat(GrMaskFormat format) { fMaskFormat = format; }
127 GrMaskFormat maskFormat() const { return fMaskFormat; }
128
129 void setAsSuccessor(const SubRunInfo& prev) {
130 fGlyphStartIndex = prev.glyphEndIndex();
131 fGlyphEndIndex = prev.glyphEndIndex();
132
133 fVertexStartIndex = prev.vertexEndIndex();
134 fVertexEndIndex = prev.vertexEndIndex();
135 }
136
137 // df properties
138 void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; }
139 bool hasUseLCDText() const { return fUseLCDText; }
140 void setDrawAsDistanceFields() { fDrawAsDistanceFields = true; }
141 bool drawAsDistanceFields() const { return fDrawAsDistanceFields; }
142
143 private:
144 GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken;
145 SkAutoTUnref<GrBatchTextStrike> fStrike;
146 uint64_t fAtlasGeneration;
147 size_t fVertexStartIndex;
148 size_t fVertexEndIndex;
149 uint32_t fGlyphStartIndex;
150 uint32_t fGlyphEndIndex;
151 GrColor fColor;
152 GrMaskFormat fMaskFormat;
153 bool fDrawAsDistanceFields; // df property
154 bool fUseLCDText; // df property
155 };
156
157 SubRunInfo& push_back() {
158 // Forward glyph / vertex information to seed the new sub run
159 SubRunInfo& newSubRun = fSubRunInfo.push_back();
160 const SubRunInfo& prevSubRun = fSubRunInfo.fromBack(1);
161
162 newSubRun.setAsSuccessor(prevSubRun);
163 return newSubRun;
164 }
165 static const int kMinSubRuns = 1;
166 SkAutoTUnref<SkTypeface> fTypeface;
167 SkRect fVertexBounds;
168 SkSTArray<kMinSubRuns, SubRunInfo> fSubRunInfo;
169 SkAutoDescriptor fDescriptor;
170
171 // Distance field text cannot draw coloremoji, and so has to fall back. However,
172 // though the distance field text and the coloremoji may share the same run, they
173 // will have different descriptors. If fOverrideDescriptor is non-nullp tr, then it
174 // will be used in place of the run's descriptor to regen texture coords
175 SkAutoTDelete<SkAutoDescriptor> fOverrideDescriptor; // df properties
176 bool fInitialized;
177 bool fDrawAsPaths;
178 };
179
180 struct BigGlyph {
181 BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, b ool applyVM)
182 : fPath(path)
183 , fVx(vx)
184 , fVy(vy)
185 , fScale(scale)
186 , fApplyVM(applyVM) {}
187 SkPath fPath;
188 SkScalar fVx;
189 SkScalar fVy;
190 SkScalar fScale;
191 bool fApplyVM;
192 };
193
194 struct Key {
195 Key() {
196 sk_bzero(this, sizeof(Key));
197 }
198 uint32_t fUniqueID;
199 // Color may affect the gamma of the mask we generate, but in a fairly l imited way.
200 // Each color is assigned to on of a fixed number of buckets based on it s
201 // luminance. For each luminance bucket there is a "canonical color" tha t
202 // represents the bucket. This functionality is currently only supporte d for A8
203 SkColor fCanonicalColor;
204 SkPaint::Style fStyle;
205 SkPixelGeometry fPixelGeometry;
206 bool fHasBlur;
207
208 bool operator==(const Key& other) const {
209 return 0 == memcmp(this, &other, sizeof(Key));
210 }
211 };
212
213 struct StrokeInfo {
214 SkScalar fFrameWidth;
215 SkScalar fMiterLimit;
216 SkPaint::Join fJoin;
217 };
218
219 enum TextType {
220 kHasDistanceField_TextType = 0x1,
221 kHasBitmap_TextType = 0x2,
222 };
223
224 // all glyph / vertex offsets are into these pools.
225 unsigned char* fVertices;
226 GrGlyph** fGlyphs;
227 Run* fRuns;
228 GrMemoryPool* fPool;
229 SkMaskFilter::BlurRec fBlurRec;
230 StrokeInfo fStrokeInfo;
231 SkTArray<BigGlyph> fBigGlyphs;
232 Key fKey;
233 SkMatrix fViewMatrix;
234 GrColor fPaintColor;
235 SkScalar fX;
236 SkScalar fY;
237
238 // We can reuse distance field text, but only if the new viewmatrix would no t result in
239 // a mip change. Because there can be multiple runs in a blob, we track the overall
240 // maximum minimum scale, and minimum maximum scale, we can support before w e need to regen
241 SkScalar fMaxMinScale;
242 SkScalar fMinMaxScale;
243 int fRunCount;
244 uint8_t fTextType;
245
246 GrAtlasTextBlob()
247 : fMaxMinScale(-SK_ScalarMax)
248 , fMinMaxScale(SK_ScalarMax)
249 , fTextType(0) {}
250
251 ~GrAtlasTextBlob() {
252 for (int i = 0; i < fRunCount; i++) {
253 fRuns[i].~Run();
254 }
255 }
256
257 static const Key& GetKey(const GrAtlasTextBlob& blob) {
258 return blob.fKey;
259 }
260
261 static uint32_t Hash(const Key& key) {
262 return SkChecksum::Murmur3(&key, sizeof(Key));
263 }
264
265 void operator delete(void* p) {
266 GrAtlasTextBlob* blob = reinterpret_cast<GrAtlasTextBlob*>(p);
267 blob->fPool->release(p);
268 }
269 void* operator new(size_t) {
270 SkFAIL("All blobs are created by placement new.");
271 return sk_malloc_throw(0);
272 }
273
274 void* operator new(size_t, void* p) { return p; }
275 void operator delete(void* target, void* placement) {
276 ::operator delete(target, placement);
277 }
278
279 bool hasDistanceField() const { return SkToBool(fTextType & kHasDistanceFiel d_TextType); }
280 bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
281 void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
282 void setHasBitmap() { fTextType |= kHasBitmap_TextType; }
283
284 void push_back_run(int currRun) {
285 SkASSERT(currRun < fRunCount);
286 if (currRun > 0) {
287 Run::SubRunInfo& newRun = fRuns[currRun].fSubRunInfo.back();
288 Run::SubRunInfo& lastRun = fRuns[currRun - 1].fSubRunInfo.back();
289 newRun.setAsSuccessor(lastRun);
290 }
291 }
292
293 // Appends a glyph to the blob. If the glyph is too large, the glyph will b e appended
294 // as a path.
295 void appendGlyph(int runIndex,
296 const SkRect& positions,
297 GrColor color,
298 GrBatchTextStrike* strike,
299 GrGlyph* glyph,
300 GrFontScaler* scaler, const SkGlyph& skGlyph,
301 SkScalar x, SkScalar y, SkScalar scale, bool applyVM);
302
303 static size_t GetVertexStride(GrMaskFormat maskFormat) {
304 switch (maskFormat) {
305 case kA8_GrMaskFormat:
306 return kGrayTextVASize;
307 case kARGB_GrMaskFormat:
308 return kColorTextVASize;
309 default:
310 return kLCDTextVASize;
311 }
312 }
313
314 bool mustRegenerate(SkScalar* outTransX, SkScalar* outTransY, const SkPaint& paint,
315 GrColor color, const SkMaskFilter::BlurRec& blurRec,
316 const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
317
318 // flush a GrAtlasTextBlob associated with a SkTextBlob
319 void flushCached(GrContext* context,
320 GrDrawContext* dc,
321 const SkTextBlob* blob,
322 const SkSurfaceProps& props,
323 const GrDistanceFieldAdjustTable* distanceAdjustTable,
324 const SkPaint& skPaint,
325 const GrPaint& grPaint,
326 SkDrawFilter* drawFilter,
327 const GrClip& clip,
328 const SkMatrix& viewMatrix,
329 const SkIRect& clipBounds,
330 SkScalar x, SkScalar y,
331 SkScalar transX, SkScalar transY);
332
333 // flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
334 void flushThrowaway(GrContext* context,
335 GrDrawContext* dc,
336 const SkSurfaceProps& props,
337 const GrDistanceFieldAdjustTable* distanceAdjustTable,
338 const SkPaint& skPaint,
339 const GrPaint& grPaint,
340 const GrClip& clip,
341 const SkIRect& clipBounds);
342
343 // position + local coord
344 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
345 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + si zeof(SkIPoint16);
346 static const size_t kLCDTextVASize = kGrayTextVASize;
347 static const int kVerticesPerGlyph = 4;
348
349 #ifdef CACHE_SANITY_CHECK
350 static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&);
351 size_t fSize;
352 #endif
353
354 // We'd like to inline this and make it private, but there is some test code which calls it.
355 // TODO refactor this
356 GrDrawBatch* createBatch(const Run::SubRunInfo& info,
357 int glyphCount, int run, int subRun,
358 GrColor color, SkScalar transX, SkScalar transY,
359 const SkPaint& skPaint, const SkSurfaceProps& props ,
360 const GrDistanceFieldAdjustTable* distanceAdjustTab le,
361 GrBatchFontCache* cache);
362
363 private:
364 void appendLargeGlyph(GrGlyph* glyph, GrFontScaler* scaler, const SkGlyph& s kGlyph,
365 SkScalar x, SkScalar y, SkScalar scale, bool applyVM);
366
367 inline void flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder,
368 int run, GrColor color,
369 SkScalar transX, SkScalar transY,
370 const SkPaint& skPaint, const SkSurfaceProps& props,
371 const GrDistanceFieldAdjustTable* distanceAdjustTable,
372 GrBatchFontCache* cache);
373
374 void flushBigGlyphs(GrContext* context, GrDrawContext* dc,
375 const GrClip& clip, const SkPaint& skPaint,
376 SkScalar transX, SkScalar transY,
377 const SkIRect& clipBounds);
378
379 void flushRunAsPaths(GrContext* context,
380 GrDrawContext* dc,
381 const SkSurfaceProps& props,
382 const SkTextBlobRunIterator& it,
383 const GrClip& clip, const SkPaint& skPaint,
384 SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
385 const SkIRect& clipBounds, SkScalar x, SkScalar y);
386 };
387
388 #endif
OLDNEW
« no previous file with comments | « gyp/gpu.gypi ('k') | src/gpu/GrAtlasTextBlob.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698