Home | History | Annotate | Download | only in batches
      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 
     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 
     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
     78     Geometry& geometry() { return fGeoData[0]; }
     79 
     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 
     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 
    110     GrAtlasTextBatch() : INHERITED(ClassID()) {} // initialized in factory functions.
    111 
    112     ~GrAtlasTextBatch() {
    113         for (int i = 0; i < fGeoCount; i++) {
    114             fGeoData[i].fBlob->unref();
    115         }
    116     }
    117 
    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 
    132     bool usesDistanceFields() const {
    133         return kGrayscaleDistanceField_MaskType == fMaskType ||
    134                kLCDDistanceField_MaskType == fMaskType;
    135     }
    136 
    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 
    144     GrColor color() const { return fBatch.fColor; }
    145     const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
    146     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
    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:
    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