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 GrAtlasTextBatch_DEFINED
9 #define GrAtlasTextBatch_DEFINED
10 
11 #include "batches/GrVertexBatch.h"
12 
13 #include "text/GrAtlasTextContext.h"
14 #include "text/GrDistanceFieldAdjustTable.h"
15 
16 class GrAtlasTextBatch : public GrVertexBatch {
17 public:
18     DEFINE_BATCH_CLASS_ID
19 
20     static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
21     static const int kIndicesPerGlyph = 6;
22 
23     typedef GrAtlasTextBlob Blob;
24     struct Geometry {
25         SkMatrix fViewMatrix;
26         Blob* fBlob;
27         SkScalar fX;
28         SkScalar fY;
29         int fRun;
30         int fSubRun;
31         GrColor fColor;
32     };
33 
CreateBitmap(GrMaskFormat maskFormat,int glyphCount,GrBatchFontCache * fontCache)34     static GrAtlasTextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount,
35                                           GrBatchFontCache* fontCache) {
36         GrAtlasTextBatch* batch = new GrAtlasTextBatch;
37 
38         batch->fFontCache = fontCache;
39         switch (maskFormat) {
40             case kA8_GrMaskFormat:
41                 batch->fMaskType = kGrayscaleCoverageMask_MaskType;
42                 break;
43             case kA565_GrMaskFormat:
44                 batch->fMaskType = kLCDCoverageMask_MaskType;
45                 break;
46             case kARGB_GrMaskFormat:
47                 batch->fMaskType = kColorBitmapMask_MaskType;
48                 break;
49         }
50         batch->fBatch.fNumGlyphs = glyphCount;
51         batch->fGeoCount = 1;
52         batch->fFilteredColor = 0;
53         batch->fFontCache = fontCache;
54         batch->fUseBGR = false;
55         return batch;
56     }
57 
CreateDistanceField(int glyphCount,GrBatchFontCache * fontCache,const GrDistanceFieldAdjustTable * distanceAdjustTable,SkColor filteredColor,bool isLCD,bool useBGR)58     static GrAtlasTextBatch* CreateDistanceField(
59                                               int glyphCount, GrBatchFontCache* fontCache,
60                                               const GrDistanceFieldAdjustTable* distanceAdjustTable,
61                                               SkColor filteredColor, bool isLCD,
62                                               bool useBGR) {
63         GrAtlasTextBatch* batch = new GrAtlasTextBatch;
64 
65         batch->fFontCache = fontCache;
66         batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType;
67         batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
68         batch->fFilteredColor = filteredColor;
69         batch->fUseBGR = useBGR;
70         batch->fBatch.fNumGlyphs = glyphCount;
71         batch->fGeoCount = 1;
72         return batch;
73     }
74 
75     // to avoid even the initial copy of the struct, we have a getter for the first item which
76     // is used to seed the batch with its initial geometry.  After seeding, the client should call
77     // init() so the Batch can initialize itself
geometry()78     Geometry& geometry() { return fGeoData[0]; }
79 
init()80     void init() {
81         const Geometry& geo = fGeoData[0];
82         fBatch.fColor = geo.fColor;
83 
84         geo.fBlob->computeSubRunBounds(&fBounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
85                                        geo.fY);
86     }
87 
name()88     const char* name() const override { return "TextBatch"; }
89 
90     SkString dumpInfo() const override;
91 
92 protected:
93     void computePipelineOptimizations(GrInitInvariantOutput* color,
94                                       GrInitInvariantOutput* coverage,
95                                       GrBatchToXPOverrides* overrides) const override;
96 
97 
98 private:
99     void initBatchTracker(const GrXPOverridesForBatch& overrides) override;
100 
101     struct FlushInfo {
102         SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
103         SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
104         int fGlyphsToFlush;
105         int fVertexOffset;
106     };
107 
108     void onPrepareDraws(Target* target) const override;
109 
GrAtlasTextBatch()110     GrAtlasTextBatch() : INHERITED(ClassID()) {} // initialized in factory functions.
111 
~GrAtlasTextBatch()112     ~GrAtlasTextBatch() {
113         for (int i = 0; i < fGeoCount; i++) {
114             fGeoData[i].fBlob->unref();
115         }
116     }
117 
maskFormat()118     GrMaskFormat maskFormat() const {
119         switch (fMaskType) {
120             case kLCDCoverageMask_MaskType:
121                 return kA565_GrMaskFormat;
122             case kColorBitmapMask_MaskType:
123                 return kARGB_GrMaskFormat;
124             case kGrayscaleCoverageMask_MaskType:
125             case kGrayscaleDistanceField_MaskType:
126             case kLCDDistanceField_MaskType:
127                 return kA8_GrMaskFormat;
128         }
129         return kA8_GrMaskFormat; // suppress warning
130     }
131 
usesDistanceFields()132     bool usesDistanceFields() const {
133         return kGrayscaleDistanceField_MaskType == fMaskType ||
134                kLCDDistanceField_MaskType == fMaskType;
135     }
136 
isLCD()137     bool isLCD() const {
138         return kLCDCoverageMask_MaskType == fMaskType ||
139                kLCDDistanceField_MaskType == fMaskType;
140     }
141 
142     inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const;
143 
color()144     GrColor color() const { return fBatch.fColor; }
viewMatrix()145     const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
usesLocalCoords()146     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
numGlyphs()147     int numGlyphs() const { return fBatch.fNumGlyphs; }
148 
149     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override;
150 
151     // TODO just use class params
152     // TODO trying to figure out why lcd is so whack
153     GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor,
154                                           GrColor color, GrTexture* texture) const;
155 
156     struct BatchTracker {
157         GrColor fColor;
158         bool fUsesLocalCoords;
159         bool fColorIgnored;
160         bool fCoverageIgnored;
161         int fNumGlyphs;
162     };
163 
164     BatchTracker fBatch;
165     // The minimum number of Geometry we will try to allocate.
166     enum { kMinGeometryAllocated = 4 };
167     SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
168     int fGeoCount;
169 
170     enum MaskType {
171         kGrayscaleCoverageMask_MaskType,
172         kLCDCoverageMask_MaskType,
173         kColorBitmapMask_MaskType,
174         kGrayscaleDistanceField_MaskType,
175         kLCDDistanceField_MaskType,
176     } fMaskType;
177     bool fUseBGR; // fold this into the enum?
178 
179     GrBatchFontCache* fFontCache;
180 
181     // Distance field properties
182     SkAutoTUnref<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
183     SkColor fFilteredColor;
184 
185     friend class GrBlobRegenHelper; // Needs to trigger flushes
186 
187     typedef GrVertexBatch INHERITED;
188 };
189 
190 /*
191  * A simple helper class to abstract the interface GrAtlasTextBlob needs to regenerate itself.
192  * It'd be nicer if this was nested, but we need to forward declare it in GrAtlasTextBlob.h
193  */
194 class GrBlobRegenHelper {
195 public:
GrBlobRegenHelper(const GrAtlasTextBatch * batch,GrVertexBatch::Target * target,GrAtlasTextBatch::FlushInfo * flushInfo,const GrGeometryProcessor * gp)196     GrBlobRegenHelper(const GrAtlasTextBatch* batch,
197                       GrVertexBatch::Target* target,
198                       GrAtlasTextBatch::FlushInfo* flushInfo,
199                       const GrGeometryProcessor* gp)
200         : fBatch(batch)
201         , fTarget(target)
202         , fFlushInfo(flushInfo)
203         , fGP(gp) {}
204 
205     void flush();
206 
207     void incGlyphCount(int glyphCount = 1) {
208         fFlushInfo->fGlyphsToFlush += glyphCount;
209     }
210 
211 private:
212     const GrAtlasTextBatch* fBatch;
213     GrVertexBatch::Target* fTarget;
214     GrAtlasTextBatch::FlushInfo* fFlushInfo;
215     const GrGeometryProcessor* fGP;
216 };
217 
218 #endif
219