1/*
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
8#ifndef GrAtlasTextOp_DEFINED
9#define GrAtlasTextOp_DEFINED
10
11#include "src/gpu/ops/GrMeshDrawOp.h"
12#include "src/gpu/text/GrTextBlob.h"
13
14class GrRecordingContext;
15
16class GrAtlasTextOp final : public GrMeshDrawOp {
17public:
18 DEFINE_OP_CLASS_ID
19
20 ~GrAtlasTextOp() override {
21 for (int i = 0; i < fGeoCount; i++) {
22 fGeoData[i].fBlob->unref();
23 }
24 }
25
26 static const int kVerticesPerGlyph = GrAtlasSubRun::kVerticesPerGlyph;
27 static const int kIndicesPerGlyph = 6;
28
29 struct Geometry {
30 void fillVertexData(void* dst, int offset, int count) const;
31
32 const GrAtlasSubRun& fSubRun;
33 const SkMatrix fDrawMatrix;
34 const SkPoint fDrawOrigin;
35 const SkIRect fClipRect;
36 GrTextBlob* const fBlob; // mutable to make unref call in Op dtor.
37
38 // Strangely, the color is mutated as part of the onPrepare process.
39 SkPMColor4f fColor;
40 };
41
42 const char* name() const override { return "AtlasTextOp"; }
43
44 void visitProxies(const VisitProxyFunc& func) const override;
45
46 FixedFunctionFlags fixedFunctionFlags() const override;
47
48 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
49 bool hasMixedSampledCoverage, GrClampType) override;
50
51 enum MaskType {
52 kGrayscaleCoverageMask_MaskType,
53 kLCDCoverageMask_MaskType,
54 kColorBitmapMask_MaskType,
55 kAliasedDistanceField_MaskType,
56 kGrayscaleDistanceField_MaskType,
57 kLCDDistanceField_MaskType,
58 kLCDBGRDistanceField_MaskType,
59 };
60
61 MaskType maskType() const { return fMaskType; }
62
63#if GR_TEST_UTILS
64 static std::unique_ptr<GrDrawOp> CreateOpTestingOnly(GrRenderTargetContext* rtc,
65 const SkPaint& skPaint,
66 const SkFont& font,
67 const SkMatrixProvider& mtxProvider,
68 const char* text,
69 int x,
70 int y);
71#endif
72
73private:
74 friend class GrOpMemoryPool; // for ctor
75
76 // The minimum number of Geometry we will try to allocate.
77 static constexpr auto kMinGeometryAllocated = 12;
78
79 GrAtlasTextOp(MaskType maskType,
80 bool needsTransform,
81 int glyphCount,
82 SkRect deviceRect,
83 const Geometry& geo,
84 GrPaint&& paint);
85
86 GrAtlasTextOp(MaskType maskType,
87 bool needsTransform,
88 int glyphCount,
89 SkRect deviceRect,
90 SkColor luminanceColor,
91 bool useGammaCorrectDistanceTable,
92 uint32_t DFGPFlags,
93 const Geometry& geo,
94 GrPaint&& paint);
95
96 struct FlushInfo {
97 sk_sp<const GrBuffer> fVertexBuffer;
98 sk_sp<const GrBuffer> fIndexBuffer;
99 GrGeometryProcessor* fGeometryProcessor;
100 const GrSurfaceProxy** fPrimProcProxies;
101 int fGlyphsToFlush = 0;
102 int fVertexOffset = 0;
103 int fNumDraws = 0;
104 };
105
106 GrProgramInfo* programInfo() override {
107 // TODO [PI]: implement
108 return nullptr;
109 }
110
111 void onCreateProgramInfo(const GrCaps*,
112 SkArenaAlloc*,
113 const GrSurfaceProxyView* writeView,
114 GrAppliedClip&&,
115 const GrXferProcessor::DstProxyView&) override {
116 // TODO [PI]: implement
117 }
118
119 void onPrePrepareDraws(GrRecordingContext*,
120 const GrSurfaceProxyView* writeView,
121 GrAppliedClip*,
122 const GrXferProcessor::DstProxyView&) override {
123 // TODO [PI]: implement
124 }
125
126 void onPrepareDraws(Target*) override;
127 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
128
129#if GR_TEST_UTILS
130 SkString onDumpInfo() const override;
131#endif
132
133 GrMaskFormat maskFormat() const {
134 switch (fMaskType) {
135 case kLCDCoverageMask_MaskType:
136 return kA565_GrMaskFormat;
137 case kColorBitmapMask_MaskType:
138 return kARGB_GrMaskFormat;
139 case kGrayscaleCoverageMask_MaskType:
140 case kAliasedDistanceField_MaskType:
141 case kGrayscaleDistanceField_MaskType:
142 case kLCDDistanceField_MaskType:
143 case kLCDBGRDistanceField_MaskType:
144 return kA8_GrMaskFormat;
145 }
146 return kA8_GrMaskFormat; // suppress warning
147 }
148
149 bool usesDistanceFields() const {
150 return kAliasedDistanceField_MaskType == fMaskType ||
151 kGrayscaleDistanceField_MaskType == fMaskType ||
152 kLCDDistanceField_MaskType == fMaskType ||
153 kLCDBGRDistanceField_MaskType == fMaskType;
154 }
155
156 bool isLCD() const {
157 return kLCDCoverageMask_MaskType == fMaskType ||
158 kLCDDistanceField_MaskType == fMaskType ||
159 kLCDBGRDistanceField_MaskType == fMaskType;
160 }
161
162 inline void createDrawForGeneratedGlyphs(
163 GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
164
165 const SkPMColor4f& color() const { SkASSERT(fGeoCount > 0); return fGeoData[0].fColor; }
166 bool usesLocalCoords() const { return fUsesLocalCoords; }
167 int numGlyphs() const { return fNumGlyphs; }
168
169 CombineResult onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
170 const GrCaps& caps) override;
171
172 GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*,
173 const GrShaderCaps&,
174 const GrSurfaceProxyView* views,
175 unsigned int numActiveViews) const;
176
177 const MaskType fMaskType;
178 const bool fNeedsGlyphTransform;
179 const SkColor fLuminanceColor{0};
180 const bool fUseGammaCorrectDistanceTable{false};
181 // Distance field properties
182 const uint32_t fDFGPFlags;
183 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
184 int fGeoDataAllocSize;
185 GrProcessorSet fProcessors;
186 bool fUsesLocalCoords;
187 int fGeoCount;
188 int fNumGlyphs;
189
190 typedef GrMeshDrawOp INHERITED;
191};
192
193#endif
194