blob: 5997d4916781cd56abe2093d6d997fe62d3f3b20 [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
13#include "GrAtlasTextContext.h"
14
15class GrAtlasTextBatch : public GrVertexBatch {
16public:
17 DEFINE_BATCH_CLASS_ID
18 static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
19
20 // position + local coord
21 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
22 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
23 static const int kVerticesPerGlyph = 4;
24 static const int kIndicesPerGlyph = 6;
25
26 typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable;
27 typedef GrAtlasTextBlob Blob;
28 typedef Blob::Run Run;
29 typedef Run::SubRunInfo TextInfo;
30 struct Geometry {
31 Blob* fBlob;
32 int fRun;
33 int fSubRun;
34 GrColor fColor;
35 SkScalar fTransX;
36 SkScalar fTransY;
37 };
38
39 static GrAtlasTextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount,
40 GrBatchFontCache* fontCache) {
41 GrAtlasTextBatch* batch = new GrAtlasTextBatch;
42
43 batch->fFontCache = fontCache;
44 switch (maskFormat) {
45 case kA8_GrMaskFormat:
46 batch->fMaskType = kGrayscaleCoverageMask_MaskType;
47 break;
48 case kA565_GrMaskFormat:
49 batch->fMaskType = kLCDCoverageMask_MaskType;
50 break;
51 case kARGB_GrMaskFormat:
52 batch->fMaskType = kColorBitmapMask_MaskType;
53 break;
54 }
55 batch->fBatch.fNumGlyphs = glyphCount;
56 batch->fGeoCount = 1;
57 batch->fFilteredColor = 0;
58 batch->fFontCache = fontCache;
59 batch->fUseBGR = false;
60 return batch;
61 }
62
63 static GrAtlasTextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* fontCache,
64 const DistanceAdjustTable* distanceAdjustTable,
65 SkColor filteredColor, bool isLCD,
66 bool useBGR) {
67 GrAtlasTextBatch* batch = new GrAtlasTextBatch;
68
69 batch->fFontCache = fontCache;
70 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType;
71 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
72 batch->fFilteredColor = filteredColor;
73 batch->fUseBGR = useBGR;
74 batch->fBatch.fNumGlyphs = glyphCount;
75 batch->fGeoCount = 1;
76 return batch;
77 }
78
79 // to avoid even the initial copy of the struct, we have a getter for the first item which
80 // is used to seed the batch with its initial geometry. After seeding, the client should call
81 // init() so the Batch can initialize itself
82 Geometry& geometry() { return fGeoData[0]; }
83
84 void init() {
85 const Geometry& geo = fGeoData[0];
86 fBatch.fColor = geo.fColor;
87 fBatch.fViewMatrix = geo.fBlob->fViewMatrix;
88
89 // We don't yet position distance field text on the cpu, so we have to map the vertex bounds
90 // into device space
91 const Run& run = geo.fBlob->fRuns[geo.fRun];
92 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) {
93 SkRect bounds = run.fVertexBounds;
94 fBatch.fViewMatrix.mapRect(&bounds);
95 this->setBounds(bounds);
96 } else {
97 this->setBounds(run.fVertexBounds);
98 }
99 }
100
101 const char* name() const override { return "TextBatch"; }
102
103 SkString dumpInfo() const override;
104
105 void getInvariantOutputColor(GrInitInvariantOutput* out) const override;
106
107 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override;
108
109 static size_t GetVertexStride(GrMaskFormat maskFormat) {
110 switch (maskFormat) {
111 case kA8_GrMaskFormat:
112 return kGrayTextVASize;
113 case kARGB_GrMaskFormat:
114 return kColorTextVASize;
115 default:
116 return kLCDTextVASize;
117 }
118 }
119
120 static size_t GetVertexStrideDf(GrMaskFormat maskFormat, bool useLCDText) {
121 SkASSERT(maskFormat == kA8_GrMaskFormat);
122 if (useLCDText) {
123 return kLCDTextVASize;
124 } else {
125 return kGrayTextVASize;
126 }
127 }
128
129private:
130 void initBatchTracker(const GrPipelineOptimizations& opt) override;
131
132 struct FlushInfo {
133 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
134 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
135 int fGlyphsToFlush;
136 int fVertexOffset;
137 };
138
139 void onPrepareDraws(Target* target) override;
140
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,
178 GrColor color, SkScalar transX, SkScalar transY);
joshualitta751c972015-11-20 13:37:32 -0800179
180 inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo);
181
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,
192 GrColor color, GrTexture* texture);
193
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
221 SkAutoTUnref<const DistanceAdjustTable> fDistanceAdjustTable;
222 SkColor fFilteredColor;
223
224 typedef GrVertexBatch INHERITED;
225};
226
227#endif