blob: f4008c947189aaf8de1fe6585a60070a1fb80e89 [file] [log] [blame]
joshualitta751c972015-11-20 13:37:32 -08001/*
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 GrAtlasTextBatch_DEFINED
9#define GrAtlasTextBatch_DEFINED
10
11#include "batches/GrVertexBatch.h"
12
joshualitte8042922015-12-11 06:11:21 -080013#include "text/GrAtlasTextContext.h"
14#include "text/GrDistanceFieldAdjustTable.h"
joshualitta751c972015-11-20 13:37:32 -080015
16class GrAtlasTextBatch : public GrVertexBatch {
17public:
18 DEFINE_BATCH_CLASS_ID
joshualitta751c972015-11-20 13:37:32 -080019
joshualitt3660d532015-12-07 11:32:50 -080020 static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
joshualitta751c972015-11-20 13:37:32 -080021 static const int kIndicesPerGlyph = 6;
22
joshualitta751c972015-11-20 13:37:32 -080023 typedef GrAtlasTextBlob Blob;
24 typedef Blob::Run Run;
25 typedef Run::SubRunInfo TextInfo;
26 struct Geometry {
27 Blob* fBlob;
28 int fRun;
29 int fSubRun;
30 GrColor fColor;
31 SkScalar fTransX;
32 SkScalar fTransY;
33 };
34
35 static GrAtlasTextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount,
36 GrBatchFontCache* fontCache) {
37 GrAtlasTextBatch* batch = new GrAtlasTextBatch;
38
39 batch->fFontCache = fontCache;
40 switch (maskFormat) {
41 case kA8_GrMaskFormat:
42 batch->fMaskType = kGrayscaleCoverageMask_MaskType;
43 break;
44 case kA565_GrMaskFormat:
45 batch->fMaskType = kLCDCoverageMask_MaskType;
46 break;
47 case kARGB_GrMaskFormat:
48 batch->fMaskType = kColorBitmapMask_MaskType;
49 break;
50 }
51 batch->fBatch.fNumGlyphs = glyphCount;
52 batch->fGeoCount = 1;
53 batch->fFilteredColor = 0;
54 batch->fFontCache = fontCache;
55 batch->fUseBGR = false;
56 return batch;
57 }
58
joshualitt1acabf32015-12-10 09:10:10 -080059 static GrAtlasTextBatch* CreateDistanceField(
60 int glyphCount, GrBatchFontCache* fontCache,
61 const GrDistanceFieldAdjustTable* distanceAdjustTable,
62 SkColor filteredColor, bool isLCD,
63 bool useBGR) {
joshualitta751c972015-11-20 13:37:32 -080064 GrAtlasTextBatch* batch = new GrAtlasTextBatch;
65
66 batch->fFontCache = fontCache;
67 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType;
68 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
69 batch->fFilteredColor = filteredColor;
70 batch->fUseBGR = useBGR;
71 batch->fBatch.fNumGlyphs = glyphCount;
72 batch->fGeoCount = 1;
73 return batch;
74 }
75
76 // to avoid even the initial copy of the struct, we have a getter for the first item which
77 // is used to seed the batch with its initial geometry. After seeding, the client should call
78 // init() so the Batch can initialize itself
79 Geometry& geometry() { return fGeoData[0]; }
80
81 void init() {
82 const Geometry& geo = fGeoData[0];
83 fBatch.fColor = geo.fColor;
84 fBatch.fViewMatrix = geo.fBlob->fViewMatrix;
85
86 // We don't yet position distance field text on the cpu, so we have to map the vertex bounds
joshualitt7481e752016-01-22 06:08:48 -080087 // into device space.
88 // We handle vertex bounds differently for distance field text and bitmap text because
89 // the vertex bounds of bitmap text are in device space. If we are flushing multiple runs
90 // from one blob then we are going to pay the price here of mapping the rect for each run.
joshualitta751c972015-11-20 13:37:32 -080091 const Run& run = geo.fBlob->fRuns[geo.fRun];
joshualitt7481e752016-01-22 06:08:48 -080092 SkRect bounds = run.fSubRunInfo[geo.fSubRun].vertexBounds();
joshualitt3660d532015-12-07 11:32:50 -080093 if (run.fSubRunInfo[geo.fSubRun].drawAsDistanceFields()) {
joshualitt7481e752016-01-22 06:08:48 -080094 // Distance field text is positioned with the (X,Y) as part of the glyph position,
95 // and currently the view matrix is applied on the GPU
96 bounds.offset(geo.fBlob->fX - geo.fBlob->fInitialX,
97 geo.fBlob->fY - geo.fBlob->fInitialY);
joshualitta751c972015-11-20 13:37:32 -080098 fBatch.fViewMatrix.mapRect(&bounds);
99 this->setBounds(bounds);
100 } else {
joshualitt7481e752016-01-22 06:08:48 -0800101 // Bitmap text is fully positioned on the CPU, and offset by an (X,Y) translate in
102 // device space.
103 SkMatrix boundsMatrix = geo.fBlob->fInitialViewMatrixInverse;
104
105 boundsMatrix.postTranslate(-geo.fBlob->fInitialX, -geo.fBlob->fInitialY);
106
107 boundsMatrix.postTranslate(geo.fBlob->fX, geo.fBlob->fY);
108
109 boundsMatrix.postConcat(geo.fBlob->fViewMatrix);
110 boundsMatrix.mapRect(&bounds);
111
112 // Due to floating point numerical inaccuracies, we have to round out here
113 SkRect roundedOutBounds;
114 bounds.roundOut(&roundedOutBounds);
115 this->setBounds(roundedOutBounds);
joshualitta751c972015-11-20 13:37:32 -0800116 }
117 }
118
119 const char* name() const override { return "TextBatch"; }
120
121 SkString dumpInfo() const override;
122
ethannicholasff210322015-11-24 12:10:10 -0800123protected:
124 void computePipelineOptimizations(GrInitInvariantOutput* color,
125 GrInitInvariantOutput* coverage,
126 GrBatchToXPOverrides* overrides) const override;
127
128
joshualitta751c972015-11-20 13:37:32 -0800129private:
ethannicholasff210322015-11-24 12:10:10 -0800130 void initBatchTracker(const GrXPOverridesForBatch& overrides) override;
joshualitta751c972015-11-20 13:37:32 -0800131
132 struct FlushInfo {
133 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
134 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
135 int fGlyphsToFlush;
136 int fVertexOffset;
137 };
138
joshualitt144c3c82015-11-30 12:30:13 -0800139 void onPrepareDraws(Target* target) const override;
joshualitta751c972015-11-20 13:37:32 -0800140
141 GrAtlasTextBatch() : INHERITED(ClassID()) {} // initialized in factory functions.
142
143 ~GrAtlasTextBatch() {
144 for (int i = 0; i < fGeoCount; i++) {
145 fGeoData[i].fBlob->unref();
146 }
147 }
148
149 GrMaskFormat maskFormat() const {
150 switch (fMaskType) {
151 case kLCDCoverageMask_MaskType:
152 return kA565_GrMaskFormat;
153 case kColorBitmapMask_MaskType:
154 return kARGB_GrMaskFormat;
155 case kGrayscaleCoverageMask_MaskType:
156 case kGrayscaleDistanceField_MaskType:
157 case kLCDDistanceField_MaskType:
158 return kA8_GrMaskFormat;
159 }
160 return kA8_GrMaskFormat; // suppress warning
161 }
162
163 bool usesDistanceFields() const {
164 return kGrayscaleDistanceField_MaskType == fMaskType ||
165 kLCDDistanceField_MaskType == fMaskType;
166 }
167
168 bool isLCD() const {
169 return kLCDCoverageMask_MaskType == fMaskType ||
170 kLCDDistanceField_MaskType == fMaskType;
171 }
172
joshualitt60ce86d2015-11-23 13:08:22 -0800173 template <bool regenTexCoords, bool regenPos, bool regenCol, bool regenGlyphs>
174 inline void regenBlob(Target* target, FlushInfo* flushInfo, Blob* blob, Run* run,
175 TextInfo* info, SkGlyphCache** cache,
176 SkTypeface** typeface, GrFontScaler** scaler, const SkDescriptor** desc,
177 const GrGeometryProcessor* gp, int glyphCount, size_t vertexStride,
joshualitt144c3c82015-11-30 12:30:13 -0800178 GrColor color, SkScalar transX, SkScalar transY) const;
joshualitta751c972015-11-20 13:37:32 -0800179
joshualitt144c3c82015-11-30 12:30:13 -0800180 inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const;
joshualitta751c972015-11-20 13:37:32 -0800181
182 GrColor color() const { return fBatch.fColor; }
183 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
184 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
185 int numGlyphs() const { return fBatch.fNumGlyphs; }
186
187 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override;
188
189 // TODO just use class params
190 // TODO trying to figure out why lcd is so whack
191 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor,
joshualitt144c3c82015-11-30 12:30:13 -0800192 GrColor color, GrTexture* texture) const;
joshualitta751c972015-11-20 13:37:32 -0800193
194 struct BatchTracker {
195 GrColor fColor;
196 SkMatrix fViewMatrix;
197 bool fUsesLocalCoords;
198 bool fColorIgnored;
199 bool fCoverageIgnored;
200 int fNumGlyphs;
201 };
202
203 BatchTracker fBatch;
204 // The minimum number of Geometry we will try to allocate.
205 enum { kMinGeometryAllocated = 4 };
206 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
207 int fGeoCount;
208
209 enum MaskType {
210 kGrayscaleCoverageMask_MaskType,
211 kLCDCoverageMask_MaskType,
212 kColorBitmapMask_MaskType,
213 kGrayscaleDistanceField_MaskType,
214 kLCDDistanceField_MaskType,
215 } fMaskType;
216 bool fUseBGR; // fold this into the enum?
217
218 GrBatchFontCache* fFontCache;
219
220 // Distance field properties
joshualitt1acabf32015-12-10 09:10:10 -0800221 SkAutoTUnref<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
joshualitta751c972015-11-20 13:37:32 -0800222 SkColor fFilteredColor;
223
224 typedef GrVertexBatch INHERITED;
225};
226
227#endif