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 |