| Index: src/gpu/batches/GrAtlasTextBatch.h | 
| diff --git a/src/gpu/batches/GrAtlasTextBatch.h b/src/gpu/batches/GrAtlasTextBatch.h | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..63dfa30e6bb53076bc89fbd262c97c8ac8c7ad92 | 
| --- /dev/null | 
| +++ b/src/gpu/batches/GrAtlasTextBatch.h | 
| @@ -0,0 +1,227 @@ | 
| +/* | 
| + * Copyright 2015 Google Inc. | 
| + * | 
| + * Use of this source code is governed by a BSD-style license that can be | 
| + * found in the LICENSE file. | 
| + */ | 
| + | 
| +#ifndef GrAtlasTextBatch_DEFINED | 
| +#define GrAtlasTextBatch_DEFINED | 
| + | 
| +#include "batches/GrVertexBatch.h" | 
| + | 
| +#include "GrAtlasTextContext.h" | 
| + | 
| +class GrAtlasTextBatch : public GrVertexBatch { | 
| +public: | 
| +    DEFINE_BATCH_CLASS_ID | 
| +    static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); | 
| + | 
| +    // position + local coord | 
| +    static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); | 
| +    static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16); | 
| +    static const int kVerticesPerGlyph = 4; | 
| +    static const int kIndicesPerGlyph = 6; | 
| + | 
| +    typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable; | 
| +    typedef GrAtlasTextBlob Blob; | 
| +    typedef Blob::Run Run; | 
| +    typedef Run::SubRunInfo TextInfo; | 
| +    struct Geometry { | 
| +        Blob* fBlob; | 
| +        int fRun; | 
| +        int fSubRun; | 
| +        GrColor fColor; | 
| +        SkScalar fTransX; | 
| +        SkScalar fTransY; | 
| +    }; | 
| + | 
| +    static GrAtlasTextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount, | 
| +                                          GrBatchFontCache* fontCache) { | 
| +        GrAtlasTextBatch* batch = new GrAtlasTextBatch; | 
| + | 
| +        batch->fFontCache = fontCache; | 
| +        switch (maskFormat) { | 
| +            case kA8_GrMaskFormat: | 
| +                batch->fMaskType = kGrayscaleCoverageMask_MaskType; | 
| +                break; | 
| +            case kA565_GrMaskFormat: | 
| +                batch->fMaskType = kLCDCoverageMask_MaskType; | 
| +                break; | 
| +            case kARGB_GrMaskFormat: | 
| +                batch->fMaskType = kColorBitmapMask_MaskType; | 
| +                break; | 
| +        } | 
| +        batch->fBatch.fNumGlyphs = glyphCount; | 
| +        batch->fGeoCount = 1; | 
| +        batch->fFilteredColor = 0; | 
| +        batch->fFontCache = fontCache; | 
| +        batch->fUseBGR = false; | 
| +        return batch; | 
| +    } | 
| + | 
| +    static GrAtlasTextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* fontCache, | 
| +                                                 const DistanceAdjustTable* distanceAdjustTable, | 
| +                                                 SkColor filteredColor, bool isLCD, | 
| +                                                 bool useBGR) { | 
| +        GrAtlasTextBatch* batch = new GrAtlasTextBatch; | 
| + | 
| +        batch->fFontCache = fontCache; | 
| +        batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType; | 
| +        batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); | 
| +        batch->fFilteredColor = filteredColor; | 
| +        batch->fUseBGR = useBGR; | 
| +        batch->fBatch.fNumGlyphs = glyphCount; | 
| +        batch->fGeoCount = 1; | 
| +        return batch; | 
| +    } | 
| + | 
| +    // to avoid even the initial copy of the struct, we have a getter for the first item which | 
| +    // is used to seed the batch with its initial geometry.  After seeding, the client should call | 
| +    // init() so the Batch can initialize itself | 
| +    Geometry& geometry() { return fGeoData[0]; } | 
| + | 
| +    void init() { | 
| +        const Geometry& geo = fGeoData[0]; | 
| +        fBatch.fColor = geo.fColor; | 
| +        fBatch.fViewMatrix = geo.fBlob->fViewMatrix; | 
| + | 
| +        // We don't yet position distance field text on the cpu, so we have to map the vertex bounds | 
| +        // into device space | 
| +        const Run& run = geo.fBlob->fRuns[geo.fRun]; | 
| +        if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { | 
| +            SkRect bounds = run.fVertexBounds; | 
| +            fBatch.fViewMatrix.mapRect(&bounds); | 
| +            this->setBounds(bounds); | 
| +        } else { | 
| +            this->setBounds(run.fVertexBounds); | 
| +        } | 
| +    } | 
| + | 
| +    const char* name() const override { return "TextBatch"; } | 
| + | 
| +    SkString dumpInfo() const override; | 
| + | 
| +    void getInvariantOutputColor(GrInitInvariantOutput* out) const override; | 
| + | 
| +    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override; | 
| + | 
| +    static size_t GetVertexStride(GrMaskFormat maskFormat) { | 
| +        switch (maskFormat) { | 
| +            case kA8_GrMaskFormat: | 
| +                return kGrayTextVASize; | 
| +            case kARGB_GrMaskFormat: | 
| +                return kColorTextVASize; | 
| +            default: | 
| +                return kLCDTextVASize; | 
| +        } | 
| +    } | 
| + | 
| +    static size_t GetVertexStrideDf(GrMaskFormat maskFormat, bool useLCDText) { | 
| +        SkASSERT(maskFormat == kA8_GrMaskFormat); | 
| +        if (useLCDText) { | 
| +            return kLCDTextVASize; | 
| +        } else { | 
| +            return kGrayTextVASize; | 
| +        } | 
| +    } | 
| + | 
| +private: | 
| +    void initBatchTracker(const GrPipelineOptimizations& opt) override; | 
| + | 
| +    struct FlushInfo { | 
| +        SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; | 
| +        SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; | 
| +        int fGlyphsToFlush; | 
| +        int fVertexOffset; | 
| +    }; | 
| + | 
| +    void onPrepareDraws(Target* target) override; | 
| + | 
| +    GrAtlasTextBatch() : INHERITED(ClassID()) {} // initialized in factory functions. | 
| + | 
| +    ~GrAtlasTextBatch() { | 
| +        for (int i = 0; i < fGeoCount; i++) { | 
| +            fGeoData[i].fBlob->unref(); | 
| +        } | 
| +    } | 
| + | 
| +    GrMaskFormat maskFormat() const { | 
| +        switch (fMaskType) { | 
| +            case kLCDCoverageMask_MaskType: | 
| +                return kA565_GrMaskFormat; | 
| +            case kColorBitmapMask_MaskType: | 
| +                return kARGB_GrMaskFormat; | 
| +            case kGrayscaleCoverageMask_MaskType: | 
| +            case kGrayscaleDistanceField_MaskType: | 
| +            case kLCDDistanceField_MaskType: | 
| +                return kA8_GrMaskFormat; | 
| +        } | 
| +        return kA8_GrMaskFormat; // suppress warning | 
| +    } | 
| + | 
| +    bool usesDistanceFields() const { | 
| +        return kGrayscaleDistanceField_MaskType == fMaskType || | 
| +               kLCDDistanceField_MaskType == fMaskType; | 
| +    } | 
| + | 
| +    bool isLCD() const { | 
| +        return kLCDCoverageMask_MaskType == fMaskType || | 
| +               kLCDDistanceField_MaskType == fMaskType; | 
| +    } | 
| + | 
| +    inline void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexStride); | 
| + | 
| +    inline void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color); | 
| + | 
| +    inline void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar transX, | 
| +                                    SkScalar transY); | 
| + | 
| +    inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo); | 
| + | 
| +    GrColor color() const { return fBatch.fColor; } | 
| +    const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } | 
| +    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 
| +    int numGlyphs() const { return fBatch.fNumGlyphs; } | 
| + | 
| +    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override; | 
| + | 
| +    // TODO just use class params | 
| +    // TODO trying to figure out why lcd is so whack | 
| +    GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor, | 
| +                                          GrColor color, GrTexture* texture); | 
| + | 
| +    struct BatchTracker { | 
| +        GrColor fColor; | 
| +        SkMatrix fViewMatrix; | 
| +        bool fUsesLocalCoords; | 
| +        bool fColorIgnored; | 
| +        bool fCoverageIgnored; | 
| +        int fNumGlyphs; | 
| +    }; | 
| + | 
| +    BatchTracker fBatch; | 
| +    // The minimum number of Geometry we will try to allocate. | 
| +    enum { kMinGeometryAllocated = 4 }; | 
| +    SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; | 
| +    int fGeoCount; | 
| + | 
| +    enum MaskType { | 
| +        kGrayscaleCoverageMask_MaskType, | 
| +        kLCDCoverageMask_MaskType, | 
| +        kColorBitmapMask_MaskType, | 
| +        kGrayscaleDistanceField_MaskType, | 
| +        kLCDDistanceField_MaskType, | 
| +    } fMaskType; | 
| +    bool fUseBGR; // fold this into the enum? | 
| + | 
| +    GrBatchFontCache* fFontCache; | 
| + | 
| +    // Distance field properties | 
| +    SkAutoTUnref<const DistanceAdjustTable> fDistanceAdjustTable; | 
| +    SkColor fFilteredColor; | 
| + | 
| +    typedef GrVertexBatch INHERITED; | 
| +}; | 
| + | 
| +#endif | 
|  |