| 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
|
|
|