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