blob: 01c5615d50e1aca60f69d80d55ab37d0de01ef59 [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
joshualittae473fd2016-01-20 12:35:22 -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];
joshualittae473fd2016-01-20 12:35:22 -080092 SkRect bounds = run.fSubRunInfo[geo.fSubRun].vertexBounds();
joshualitt3660d532015-12-07 11:32:50 -080093 if (run.fSubRunInfo[geo.fSubRun].drawAsDistanceFields()) {
joshualittae473fd2016-01-20 12:35:22 -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 {
joshualittae473fd2016-01-20 12:35:22 -0800101 // Bitmap text is fully positioned on the CPU
102 SkMatrix boundsMatrix;
103 bounds.offset(-geo.fBlob->fInitialX, -geo.fBlob->fInitialY);
104 boundsMatrix.setConcat(fBatch.fViewMatrix, geo.fBlob->fInitialViewMatrixInverse);
105 boundsMatrix.mapRect(&bounds);
106
107 // Due to floating point numerical inaccuracies, we have to round out here
108 SkRect roundedOutBounds;
109 bounds.roundOut(&roundedOutBounds);
110 roundedOutBounds.offset(geo.fBlob->fX, geo.fBlob->fY);
111 this->setBounds(roundedOutBounds);
joshualitta751c972015-11-20 13:37:32 -0800112 }
113 }
114
115 const char* name() const override { return "TextBatch"; }
116
117 SkString dumpInfo() const override;
118
ethannicholasff210322015-11-24 12:10:10 -0800119protected:
120 void computePipelineOptimizations(GrInitInvariantOutput* color,
121 GrInitInvariantOutput* coverage,
122 GrBatchToXPOverrides* overrides) const override;
123
124
joshualitta751c972015-11-20 13:37:32 -0800125private:
ethannicholasff210322015-11-24 12:10:10 -0800126 void initBatchTracker(const GrXPOverridesForBatch& overrides) override;
joshualitta751c972015-11-20 13:37:32 -0800127
128 struct FlushInfo {
129 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
130 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
131 int fGlyphsToFlush;
132 int fVertexOffset;
133 };
134
joshualitt144c3c82015-11-30 12:30:13 -0800135 void onPrepareDraws(Target* target) const override;
joshualitta751c972015-11-20 13:37:32 -0800136
137 GrAtlasTextBatch() : INHERITED(ClassID()) {} // initialized in factory functions.
138
139 ~GrAtlasTextBatch() {
140 for (int i = 0; i < fGeoCount; i++) {
141 fGeoData[i].fBlob->unref();
142 }
143 }
144
145 GrMaskFormat maskFormat() const {
146 switch (fMaskType) {
147 case kLCDCoverageMask_MaskType:
148 return kA565_GrMaskFormat;
149 case kColorBitmapMask_MaskType:
150 return kARGB_GrMaskFormat;
151 case kGrayscaleCoverageMask_MaskType:
152 case kGrayscaleDistanceField_MaskType:
153 case kLCDDistanceField_MaskType:
154 return kA8_GrMaskFormat;
155 }
156 return kA8_GrMaskFormat; // suppress warning
157 }
158
159 bool usesDistanceFields() const {
160 return kGrayscaleDistanceField_MaskType == fMaskType ||
161 kLCDDistanceField_MaskType == fMaskType;
162 }
163
164 bool isLCD() const {
165 return kLCDCoverageMask_MaskType == fMaskType ||
166 kLCDDistanceField_MaskType == fMaskType;
167 }
168
joshualitt60ce86d2015-11-23 13:08:22 -0800169 template <bool regenTexCoords, bool regenPos, bool regenCol, bool regenGlyphs>
170 inline void regenBlob(Target* target, FlushInfo* flushInfo, Blob* blob, Run* run,
171 TextInfo* info, SkGlyphCache** cache,
172 SkTypeface** typeface, GrFontScaler** scaler, const SkDescriptor** desc,
173 const GrGeometryProcessor* gp, int glyphCount, size_t vertexStride,
joshualitt144c3c82015-11-30 12:30:13 -0800174 GrColor color, SkScalar transX, SkScalar transY) const;
joshualitta751c972015-11-20 13:37:32 -0800175
joshualitt144c3c82015-11-30 12:30:13 -0800176 inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const;
joshualitta751c972015-11-20 13:37:32 -0800177
178 GrColor color() const { return fBatch.fColor; }
179 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
180 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
181 int numGlyphs() const { return fBatch.fNumGlyphs; }
182
183 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override;
184
185 // TODO just use class params
186 // TODO trying to figure out why lcd is so whack
187 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor,
joshualitt144c3c82015-11-30 12:30:13 -0800188 GrColor color, GrTexture* texture) const;
joshualitta751c972015-11-20 13:37:32 -0800189
190 struct BatchTracker {
191 GrColor fColor;
192 SkMatrix fViewMatrix;
193 bool fUsesLocalCoords;
194 bool fColorIgnored;
195 bool fCoverageIgnored;
196 int fNumGlyphs;
197 };
198
199 BatchTracker fBatch;
200 // The minimum number of Geometry we will try to allocate.
201 enum { kMinGeometryAllocated = 4 };
202 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
203 int fGeoCount;
204
205 enum MaskType {
206 kGrayscaleCoverageMask_MaskType,
207 kLCDCoverageMask_MaskType,
208 kColorBitmapMask_MaskType,
209 kGrayscaleDistanceField_MaskType,
210 kLCDDistanceField_MaskType,
211 } fMaskType;
212 bool fUseBGR; // fold this into the enum?
213
214 GrBatchFontCache* fFontCache;
215
216 // Distance field properties
joshualitt1acabf32015-12-10 09:10:10 -0800217 SkAutoTUnref<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
joshualitta751c972015-11-20 13:37:32 -0800218 SkColor fFilteredColor;
219
220 typedef GrVertexBatch INHERITED;
221};
222
223#endif