blob: e0a4ed013526fa44f3b634b7d168e017e9b2da33 [file] [log] [blame]
joshualitta751c972015-11-20 13:37:32 -08001/*
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
Brian Salomon344ec422016-12-15 10:58:41 -05008#ifndef GrAtlasTextOp_DEFINED
9#define GrAtlasTextOp_DEFINED
joshualitta751c972015-11-20 13:37:32 -080010
Brian Salomon89527432016-12-16 09:52:16 -050011#include "ops/GrMeshDrawOp.h"
joshualitta751c972015-11-20 13:37:32 -080012
joshualitte8042922015-12-11 06:11:21 -080013#include "text/GrAtlasTextContext.h"
14#include "text/GrDistanceFieldAdjustTable.h"
joshualitta751c972015-11-20 13:37:32 -080015
Brian Salomond3ccb0a2017-04-03 10:38:00 -040016class GrAtlasTextOp final : public GrLegacyMeshDrawOp {
joshualitta751c972015-11-20 13:37:32 -080017public:
Brian Salomon25a88092016-12-01 09:36:50 -050018 DEFINE_OP_CLASS_ID
joshualitta751c972015-11-20 13:37:32 -080019
Brian Salomonf8334782017-01-03 09:42:58 -050020 ~GrAtlasTextOp() override {
21 for (int i = 0; i < fGeoCount; i++) {
22 fGeoData[i].fBlob->unref();
23 }
24 }
25
joshualitt3660d532015-12-07 11:32:50 -080026 static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
joshualitta751c972015-11-20 13:37:32 -080027 static const int kIndicesPerGlyph = 6;
28
joshualitta751c972015-11-20 13:37:32 -080029 typedef GrAtlasTextBlob Blob;
joshualitta751c972015-11-20 13:37:32 -080030 struct Geometry {
joshualitt8e0ef292016-02-19 14:13:03 -080031 SkMatrix fViewMatrix;
joshualitta751c972015-11-20 13:37:32 -080032 Blob* fBlob;
joshualitt8e0ef292016-02-19 14:13:03 -080033 SkScalar fX;
34 SkScalar fY;
joshualitta751c972015-11-20 13:37:32 -080035 int fRun;
36 int fSubRun;
37 GrColor fColor;
joshualitta751c972015-11-20 13:37:32 -080038 };
39
Brian Salomonf8334782017-01-03 09:42:58 -050040 static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrMaskFormat maskFormat, int glyphCount,
41 GrAtlasGlyphCache* fontCache) {
42 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp);
joshualitta751c972015-11-20 13:37:32 -080043
Brian Salomon344ec422016-12-15 10:58:41 -050044 op->fFontCache = fontCache;
joshualitta751c972015-11-20 13:37:32 -080045 switch (maskFormat) {
46 case kA8_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050047 op->fMaskType = kGrayscaleCoverageMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080048 break;
49 case kA565_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050050 op->fMaskType = kLCDCoverageMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080051 break;
52 case kARGB_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050053 op->fMaskType = kColorBitmapMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080054 break;
55 }
Brian Salomon344ec422016-12-15 10:58:41 -050056 op->fNumGlyphs = glyphCount;
57 op->fGeoCount = 1;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -040058 op->fLuminanceColor = 0;
Brian Salomon344ec422016-12-15 10:58:41 -050059 op->fFontCache = fontCache;
60 op->fUseBGR = false;
61 return op;
joshualitta751c972015-11-20 13:37:32 -080062 }
63
Brian Salomonf8334782017-01-03 09:42:58 -050064 static std::unique_ptr<GrAtlasTextOp> MakeDistanceField(
Brian Salomonf856fd12016-12-16 14:24:34 -050065 int glyphCount, GrAtlasGlyphCache* fontCache,
Brian Salomon344ec422016-12-15 10:58:41 -050066 const GrDistanceFieldAdjustTable* distanceAdjustTable,
Jim Van Verthbc2cdd12017-06-08 11:14:35 -040067 bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR) {
Brian Salomonf8334782017-01-03 09:42:58 -050068 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp);
joshualitta751c972015-11-20 13:37:32 -080069
Brian Salomon344ec422016-12-15 10:58:41 -050070 op->fFontCache = fontCache;
71 op->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistanceField_MaskType;
72 op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
73 op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -040074 op->fLuminanceColor = luminanceColor;
Brian Salomon344ec422016-12-15 10:58:41 -050075 op->fUseBGR = useBGR;
76 op->fNumGlyphs = glyphCount;
77 op->fGeoCount = 1;
78 return op;
joshualitta751c972015-11-20 13:37:32 -080079 }
80
Brian Salomon344ec422016-12-15 10:58:41 -050081 // To avoid even the initial copy of the struct, we have a getter for the first item which
82 // is used to seed the op with its initial geometry. After seeding, the client should call
83 // init() so the op can initialize itself
joshualitta751c972015-11-20 13:37:32 -080084 Geometry& geometry() { return fGeoData[0]; }
85
86 void init() {
87 const Geometry& geo = fGeoData[0];
Brian Salomon344ec422016-12-15 10:58:41 -050088 fColor = geo.fColor;
bsalomon88cf17d2016-07-08 06:40:56 -070089 SkRect bounds;
90 geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
joshualitt8e0ef292016-02-19 14:13:03 -080091 geo.fY);
bsalomon88cf17d2016-07-08 06:40:56 -070092 // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
93 // we treat this as a set of non-AA rects rendered with a texture.
94 this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
joshualitta751c972015-11-20 13:37:32 -080095 }
96
Brian Salomon344ec422016-12-15 10:58:41 -050097 const char* name() const override { return "AtlasTextOp"; }
joshualitta751c972015-11-20 13:37:32 -080098
99 SkString dumpInfo() const override;
100
joshualitta751c972015-11-20 13:37:32 -0800101private:
Brian Salomona811b122017-03-30 08:21:32 -0400102 void getProcessorAnalysisInputs(GrProcessorAnalysisColor*,
103 GrProcessorAnalysisCoverage*) const override;
Brian Salomone7d30482017-03-29 12:09:15 -0400104 void applyPipelineOptimizations(const PipelineOptimizations&) override;
joshualitta751c972015-11-20 13:37:32 -0800105
106 struct FlushInfo {
Brian Salomon344ec422016-12-15 10:58:41 -0500107 sk_sp<const GrBuffer> fVertexBuffer;
108 sk_sp<const GrBuffer> fIndexBuffer;
Hal Canary144caf52016-11-07 17:57:18 -0500109 sk_sp<GrGeometryProcessor> fGeometryProcessor;
Brian Salomon344ec422016-12-15 10:58:41 -0500110 int fGlyphsToFlush;
111 int fVertexOffset;
joshualitta751c972015-11-20 13:37:32 -0800112 };
113
joshualitt144c3c82015-11-30 12:30:13 -0800114 void onPrepareDraws(Target* target) const override;
joshualitta751c972015-11-20 13:37:32 -0800115
Brian Salomon344ec422016-12-15 10:58:41 -0500116 GrAtlasTextOp() : INHERITED(ClassID()) {} // initialized in factory functions.
joshualitta751c972015-11-20 13:37:32 -0800117
joshualitta751c972015-11-20 13:37:32 -0800118 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 }
Brian Salomon344ec422016-12-15 10:58:41 -0500129 return kA8_GrMaskFormat; // suppress warning
joshualitta751c972015-11-20 13:37:32 -0800130 }
131
132 bool usesDistanceFields() const {
133 return kGrayscaleDistanceField_MaskType == fMaskType ||
134 kLCDDistanceField_MaskType == fMaskType;
135 }
136
137 bool isLCD() const {
Brian Salomon344ec422016-12-15 10:58:41 -0500138 return kLCDCoverageMask_MaskType == fMaskType || kLCDDistanceField_MaskType == fMaskType;
joshualitta751c972015-11-20 13:37:32 -0800139 }
140
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400141 inline void flush(GrLegacyMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
joshualitta751c972015-11-20 13:37:32 -0800142
Brian Salomon344ec422016-12-15 10:58:41 -0500143 GrColor color() const { return fColor; }
joshualitt8e0ef292016-02-19 14:13:03 -0800144 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
Brian Salomon344ec422016-12-15 10:58:41 -0500145 bool usesLocalCoords() const { return fUsesLocalCoords; }
146 int numGlyphs() const { return fNumGlyphs; }
joshualitta751c972015-11-20 13:37:32 -0800147
Brian Salomon25a88092016-12-01 09:36:50 -0500148 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
joshualitta751c972015-11-20 13:37:32 -0800149
150 // TODO just use class params
Robert Phillips296b1cc2017-03-15 10:42:12 -0400151 sk_sp<GrGeometryProcessor> setupDfProcessor(GrResourceProvider*,
Jim Van Verthbc2cdd12017-06-08 11:14:35 -0400152 const SkMatrix& viewMatrix, SkColor luminanceColor,
Robert Phillips32f28182017-02-28 16:20:03 -0500153 GrColor color, sk_sp<GrTextureProxy> proxy) const;
joshualitta751c972015-11-20 13:37:32 -0800154
Brian Salomon344ec422016-12-15 10:58:41 -0500155 GrColor fColor;
156 bool fUsesLocalCoords;
Brian Salomon344ec422016-12-15 10:58:41 -0500157 int fNumGlyphs;
joshualitta751c972015-11-20 13:37:32 -0800158
joshualitta751c972015-11-20 13:37:32 -0800159 // The minimum number of Geometry we will try to allocate.
160 enum { kMinGeometryAllocated = 4 };
161 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
162 int fGeoCount;
163
164 enum MaskType {
165 kGrayscaleCoverageMask_MaskType,
166 kLCDCoverageMask_MaskType,
167 kColorBitmapMask_MaskType,
168 kGrayscaleDistanceField_MaskType,
169 kLCDDistanceField_MaskType,
170 } fMaskType;
Brian Salomon344ec422016-12-15 10:58:41 -0500171 bool fUseBGR; // fold this into the enum?
joshualitta751c972015-11-20 13:37:32 -0800172
Brian Salomonf856fd12016-12-16 14:24:34 -0500173 GrAtlasGlyphCache* fFontCache;
joshualitta751c972015-11-20 13:37:32 -0800174
175 // Distance field properties
Hal Canary144caf52016-11-07 17:57:18 -0500176 sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -0400177 SkColor fLuminanceColor;
brianosmanb461d342016-04-13 13:10:14 -0700178 bool fUseGammaCorrectDistanceTable;
joshualitta751c972015-11-20 13:37:32 -0800179
Brian Salomon344ec422016-12-15 10:58:41 -0500180 friend class GrBlobRegenHelper; // Needs to trigger flushes
joshualittddd22d82016-02-16 06:47:52 -0800181
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400182 typedef GrLegacyMeshDrawOp INHERITED;
joshualitta751c972015-11-20 13:37:32 -0800183};
184
joshualittddd22d82016-02-16 06:47:52 -0800185/*
186 * A simple helper class to abstract the interface GrAtlasTextBlob needs to regenerate itself.
187 * It'd be nicer if this was nested, but we need to forward declare it in GrAtlasTextBlob.h
188 */
189class GrBlobRegenHelper {
190public:
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400191 GrBlobRegenHelper(const GrAtlasTextOp* op, GrLegacyMeshDrawOp::Target* target,
Brian Salomon344ec422016-12-15 10:58:41 -0500192 GrAtlasTextOp::FlushInfo* flushInfo)
193 : fOp(op), fTarget(target), fFlushInfo(flushInfo) {}
joshualittddd22d82016-02-16 06:47:52 -0800194
195 void flush();
196
Brian Salomon344ec422016-12-15 10:58:41 -0500197 void incGlyphCount(int glyphCount = 1) { fFlushInfo->fGlyphsToFlush += glyphCount; }
joshualittddd22d82016-02-16 06:47:52 -0800198
199private:
Brian Salomon344ec422016-12-15 10:58:41 -0500200 const GrAtlasTextOp* fOp;
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400201 GrLegacyMeshDrawOp::Target* fTarget;
Brian Salomon344ec422016-12-15 10:58:41 -0500202 GrAtlasTextOp::FlushInfo* fFlushInfo;
joshualittddd22d82016-02-16 06:47:52 -0800203};
204
joshualitta751c972015-11-20 13:37:32 -0800205#endif