blob: 0738ce7f205912f2bbb61d4998044279d8372116 [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"
joshualitte8042922015-12-11 06:11:21 -080012#include "text/GrAtlasTextContext.h"
13#include "text/GrDistanceFieldAdjustTable.h"
joshualitta751c972015-11-20 13:37:32 -080014
Brian Salomon44acb5b2017-07-18 19:59:24 -040015class GrAtlasTextOp final : public GrMeshDrawOp {
joshualitta751c972015-11-20 13:37:32 -080016public:
Brian Salomon25a88092016-12-01 09:36:50 -050017 DEFINE_OP_CLASS_ID
joshualitta751c972015-11-20 13:37:32 -080018
Brian Salomonf8334782017-01-03 09:42:58 -050019 ~GrAtlasTextOp() override {
20 for (int i = 0; i < fGeoCount; i++) {
21 fGeoData[i].fBlob->unref();
22 }
23 }
24
joshualitt3660d532015-12-07 11:32:50 -080025 static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
joshualitta751c972015-11-20 13:37:32 -080026 static const int kIndicesPerGlyph = 6;
27
joshualitta751c972015-11-20 13:37:32 -080028 typedef GrAtlasTextBlob Blob;
joshualitta751c972015-11-20 13:37:32 -080029 struct Geometry {
joshualitt8e0ef292016-02-19 14:13:03 -080030 SkMatrix fViewMatrix;
joshualitta751c972015-11-20 13:37:32 -080031 Blob* fBlob;
joshualitt8e0ef292016-02-19 14:13:03 -080032 SkScalar fX;
33 SkScalar fY;
joshualitta751c972015-11-20 13:37:32 -080034 int fRun;
35 int fSubRun;
36 GrColor fColor;
joshualitta751c972015-11-20 13:37:32 -080037 };
38
Brian Salomon44acb5b2017-07-18 19:59:24 -040039 static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrPaint&& paint, GrMaskFormat maskFormat,
40 int glyphCount, GrAtlasGlyphCache* fontCache) {
41 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
joshualitta751c972015-11-20 13:37:32 -080042
Brian Salomon344ec422016-12-15 10:58:41 -050043 op->fFontCache = fontCache;
joshualitta751c972015-11-20 13:37:32 -080044 switch (maskFormat) {
45 case kA8_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050046 op->fMaskType = kGrayscaleCoverageMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080047 break;
48 case kA565_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050049 op->fMaskType = kLCDCoverageMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080050 break;
51 case kARGB_GrMaskFormat:
Brian Salomon344ec422016-12-15 10:58:41 -050052 op->fMaskType = kColorBitmapMask_MaskType;
joshualitta751c972015-11-20 13:37:32 -080053 break;
54 }
Brian Salomon344ec422016-12-15 10:58:41 -050055 op->fNumGlyphs = glyphCount;
56 op->fGeoCount = 1;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -040057 op->fLuminanceColor = 0;
Brian Salomon344ec422016-12-15 10:58:41 -050058 op->fFontCache = fontCache;
Brian Salomon344ec422016-12-15 10:58:41 -050059 return op;
joshualitta751c972015-11-20 13:37:32 -080060 }
61
Brian Salomonf8334782017-01-03 09:42:58 -050062 static std::unique_ptr<GrAtlasTextOp> MakeDistanceField(
Brian Salomon44acb5b2017-07-18 19:59:24 -040063 GrPaint&& paint, int glyphCount, GrAtlasGlyphCache* fontCache,
Brian Salomon344ec422016-12-15 10:58:41 -050064 const GrDistanceFieldAdjustTable* distanceAdjustTable,
Jim Van Verth90e89b32017-07-06 16:36:55 -040065 bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR,
66 bool isAntiAliased) {
Brian Salomon44acb5b2017-07-18 19:59:24 -040067 std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
joshualitta751c972015-11-20 13:37:32 -080068
Brian Salomon344ec422016-12-15 10:58:41 -050069 op->fFontCache = fontCache;
Jim Van Verth90e89b32017-07-06 16:36:55 -040070 op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType
71 : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType
72 : kLCDDistanceField_MaskType)
73 : kGrayscaleDistanceField_MaskType;
Brian Salomon344ec422016-12-15 10:58:41 -050074 op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
75 op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -040076 op->fLuminanceColor = luminanceColor;
Brian Salomon344ec422016-12-15 10:58:41 -050077 op->fNumGlyphs = glyphCount;
78 op->fGeoCount = 1;
79 return op;
joshualitta751c972015-11-20 13:37:32 -080080 }
81
Brian Salomon344ec422016-12-15 10:58:41 -050082 // To avoid even the initial copy of the struct, we have a getter for the first item which
83 // is used to seed the op with its initial geometry. After seeding, the client should call
84 // init() so the op can initialize itself
joshualitta751c972015-11-20 13:37:32 -080085 Geometry& geometry() { return fGeoData[0]; }
86
87 void init() {
88 const Geometry& geo = fGeoData[0];
Brian Salomon344ec422016-12-15 10:58:41 -050089 fColor = geo.fColor;
bsalomon88cf17d2016-07-08 06:40:56 -070090 SkRect bounds;
91 geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
joshualitt8e0ef292016-02-19 14:13:03 -080092 geo.fY);
bsalomon88cf17d2016-07-08 06:40:56 -070093 // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
94 // we treat this as a set of non-AA rects rendered with a texture.
95 this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
joshualitta751c972015-11-20 13:37:32 -080096 }
97
Brian Salomon344ec422016-12-15 10:58:41 -050098 const char* name() const override { return "AtlasTextOp"; }
joshualitta751c972015-11-20 13:37:32 -080099
Robert Phillipsf1748f52017-09-14 14:11:24 -0400100 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400101 fProcessors.visitProxies(func);
102
103 const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(this->maskFormat());
104 for (int i = 0; i < kMaxTextures; ++i) {
105 if (proxies[i]) {
106 func(proxies[i].get());
107 }
108 }
109 }
110
joshualitta751c972015-11-20 13:37:32 -0800111 SkString dumpInfo() const override;
112
Brian Salomon44acb5b2017-07-18 19:59:24 -0400113 FixedFunctionFlags fixedFunctionFlags() const override;
114
Brian Osman9a725dd2017-09-20 09:53:22 -0400115 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
116 GrPixelConfigIsClamped dstIsClamped) override;
Brian Salomon44acb5b2017-07-18 19:59:24 -0400117
joshualitta751c972015-11-20 13:37:32 -0800118private:
Brian Salomon44acb5b2017-07-18 19:59:24 -0400119 GrAtlasTextOp(GrPaint&& paint)
120 : INHERITED(ClassID())
121 , fColor(paint.getColor())
122 , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
123 , fProcessors(std::move(paint)) {}
joshualitta751c972015-11-20 13:37:32 -0800124
125 struct FlushInfo {
Brian Salomon344ec422016-12-15 10:58:41 -0500126 sk_sp<const GrBuffer> fVertexBuffer;
127 sk_sp<const GrBuffer> fIndexBuffer;
Hal Canary144caf52016-11-07 17:57:18 -0500128 sk_sp<GrGeometryProcessor> fGeometryProcessor;
Brian Salomon44acb5b2017-07-18 19:59:24 -0400129 const GrPipeline* fPipeline;
Brian Salomon344ec422016-12-15 10:58:41 -0500130 int fGlyphsToFlush;
131 int fVertexOffset;
joshualitta751c972015-11-20 13:37:32 -0800132 };
133
Brian Salomon91326c32017-08-09 16:02:19 -0400134 void onPrepareDraws(Target*) override;
joshualitta751c972015-11-20 13:37:32 -0800135
joshualitta751c972015-11-20 13:37:32 -0800136 GrMaskFormat maskFormat() const {
137 switch (fMaskType) {
138 case kLCDCoverageMask_MaskType:
139 return kA565_GrMaskFormat;
140 case kColorBitmapMask_MaskType:
141 return kARGB_GrMaskFormat;
142 case kGrayscaleCoverageMask_MaskType:
Jim Van Verth90e89b32017-07-06 16:36:55 -0400143 case kAliasedDistanceField_MaskType:
joshualitta751c972015-11-20 13:37:32 -0800144 case kGrayscaleDistanceField_MaskType:
145 case kLCDDistanceField_MaskType:
Jim Van Verth90e89b32017-07-06 16:36:55 -0400146 case kLCDBGRDistanceField_MaskType:
joshualitta751c972015-11-20 13:37:32 -0800147 return kA8_GrMaskFormat;
148 }
Brian Salomon344ec422016-12-15 10:58:41 -0500149 return kA8_GrMaskFormat; // suppress warning
joshualitta751c972015-11-20 13:37:32 -0800150 }
151
152 bool usesDistanceFields() const {
Jim Van Verth90e89b32017-07-06 16:36:55 -0400153 return kAliasedDistanceField_MaskType == fMaskType ||
154 kGrayscaleDistanceField_MaskType == fMaskType ||
155 kLCDDistanceField_MaskType == fMaskType ||
156 kLCDBGRDistanceField_MaskType == fMaskType;
joshualitta751c972015-11-20 13:37:32 -0800157 }
158
159 bool isLCD() const {
Jim Van Verth90e89b32017-07-06 16:36:55 -0400160 return kLCDCoverageMask_MaskType == fMaskType ||
161 kLCDDistanceField_MaskType == fMaskType ||
162 kLCDBGRDistanceField_MaskType == fMaskType;
joshualitta751c972015-11-20 13:37:32 -0800163 }
164
Brian Salomone5b399e2017-07-19 13:50:54 -0400165 inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
joshualitta751c972015-11-20 13:37:32 -0800166
Brian Salomon344ec422016-12-15 10:58:41 -0500167 GrColor color() const { return fColor; }
joshualitt8e0ef292016-02-19 14:13:03 -0800168 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
Brian Salomon344ec422016-12-15 10:58:41 -0500169 bool usesLocalCoords() const { return fUsesLocalCoords; }
170 int numGlyphs() const { return fNumGlyphs; }
joshualitta751c972015-11-20 13:37:32 -0800171
Brian Salomon25a88092016-12-01 09:36:50 -0500172 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
joshualitta751c972015-11-20 13:37:32 -0800173
Jim Van Vertha950b632017-09-12 11:54:11 -0400174 static constexpr auto kMaxTextures = 4;
Ben Wagner63fd7602017-10-09 15:45:33 -0400175
joshualitta751c972015-11-20 13:37:32 -0800176 // TODO just use class params
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400177 sk_sp<GrGeometryProcessor> setupDfProcessor(const SkMatrix& viewMatrix, SkColor luminanceColor,
Jim Van Vertha950b632017-09-12 11:54:11 -0400178 GrColor color,
179 const sk_sp<GrTextureProxy> [kMaxTextures]) const;
joshualitta751c972015-11-20 13:37:32 -0800180
joshualitta751c972015-11-20 13:37:32 -0800181
joshualitta751c972015-11-20 13:37:32 -0800182 // The minimum number of Geometry we will try to allocate.
183 enum { kMinGeometryAllocated = 4 };
joshualitta751c972015-11-20 13:37:32 -0800184
185 enum MaskType {
186 kGrayscaleCoverageMask_MaskType,
187 kLCDCoverageMask_MaskType,
188 kColorBitmapMask_MaskType,
Jim Van Verth90e89b32017-07-06 16:36:55 -0400189 kAliasedDistanceField_MaskType,
joshualitta751c972015-11-20 13:37:32 -0800190 kGrayscaleDistanceField_MaskType,
191 kLCDDistanceField_MaskType,
Jim Van Verth90e89b32017-07-06 16:36:55 -0400192 kLCDBGRDistanceField_MaskType,
Brian Salomon44acb5b2017-07-18 19:59:24 -0400193 };
joshualitta751c972015-11-20 13:37:32 -0800194
Brian Salomon44acb5b2017-07-18 19:59:24 -0400195 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
196 GrColor fColor;
197 uint32_t fSRGBFlags;
198 GrProcessorSet fProcessors;
199 bool fUsesLocalCoords;
200 bool fCanCombineOnTouchOrOverlap;
201 int fGeoCount;
202 int fNumGlyphs;
203 MaskType fMaskType;
Brian Salomonf856fd12016-12-16 14:24:34 -0500204 GrAtlasGlyphCache* fFontCache;
joshualitta751c972015-11-20 13:37:32 -0800205 // Distance field properties
Hal Canary144caf52016-11-07 17:57:18 -0500206 sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
Jim Van Verthbc2cdd12017-06-08 11:14:35 -0400207 SkColor fLuminanceColor;
brianosmanb461d342016-04-13 13:10:14 -0700208 bool fUseGammaCorrectDistanceTable;
joshualitta751c972015-11-20 13:37:32 -0800209
Brian Salomon344ec422016-12-15 10:58:41 -0500210 friend class GrBlobRegenHelper; // Needs to trigger flushes
joshualittddd22d82016-02-16 06:47:52 -0800211
Brian Salomon44acb5b2017-07-18 19:59:24 -0400212 typedef GrMeshDrawOp INHERITED;
joshualitta751c972015-11-20 13:37:32 -0800213};
214
joshualittddd22d82016-02-16 06:47:52 -0800215/*
216 * A simple helper class to abstract the interface GrAtlasTextBlob needs to regenerate itself.
217 * It'd be nicer if this was nested, but we need to forward declare it in GrAtlasTextBlob.h
218 */
219class GrBlobRegenHelper {
220public:
Brian Salomone5b399e2017-07-19 13:50:54 -0400221 GrBlobRegenHelper(const GrAtlasTextOp* op, GrMeshDrawOp::Target* target,
Brian Salomon344ec422016-12-15 10:58:41 -0500222 GrAtlasTextOp::FlushInfo* flushInfo)
223 : fOp(op), fTarget(target), fFlushInfo(flushInfo) {}
joshualittddd22d82016-02-16 06:47:52 -0800224
225 void flush();
226
Brian Salomon344ec422016-12-15 10:58:41 -0500227 void incGlyphCount(int glyphCount = 1) { fFlushInfo->fGlyphsToFlush += glyphCount; }
joshualittddd22d82016-02-16 06:47:52 -0800228
229private:
Brian Salomon344ec422016-12-15 10:58:41 -0500230 const GrAtlasTextOp* fOp;
Brian Salomone5b399e2017-07-19 13:50:54 -0400231 GrMeshDrawOp::Target* fTarget;
Brian Salomon344ec422016-12-15 10:58:41 -0500232 GrAtlasTextOp::FlushInfo* fFlushInfo;
joshualittddd22d82016-02-16 06:47:52 -0800233};
234
joshualitta751c972015-11-20 13:37:32 -0800235#endif