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;
15class SkAtlasTextTarget;
16
17class GrAtlasTextOp final : public GrMeshDrawOp {
18public:
19 DEFINE_OP_CLASS_ID
20
21 ~GrAtlasTextOp() override {
22 for (int i = 0; i < fGeoCount; i++) {
23 fGeoData[i].fBlob->unref();
24 }
25 }
26
27 static const int kVerticesPerGlyph = GrTextBlob::kVerticesPerGlyph;
28 static const int kIndicesPerGlyph = 6;
29
30 struct Geometry {
31 SkMatrix fDrawMatrix;
32 SkIRect fClipRect;
33 GrTextBlob* fBlob;
34 SkPoint fDrawOrigin;
35 GrTextBlob::SubRun* fSubRunPtr;
36 SkPMColor4f fColor;
37 };
38
39 static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrRecordingContext*,
40 GrPaint&&,
41 GrMaskFormat,
42 int glyphCount,
43 bool needsTransform);
44
45 static std::unique_ptr<GrAtlasTextOp> MakeDistanceField(
46 GrRecordingContext*,
47 GrPaint&&,
48 int glyphCount,
49 bool useGammaCorrectDistanceTable,
50 SkColor luminanceColor,
51 const SkSurfaceProps&,
52 bool isAntiAliased,
53 bool useLCD);
54
55 // To avoid even the initial copy of the struct, we have a getter for the first item which
56 // is used to seed the op with its initial geometry. After seeding, the client should call
57 // init() so the op can initialize itself
58 Geometry& geometry() { return fGeoData[0]; }
59
60 /** Called after this->geometry() has been configured. */
61 void init();
62
63 const char* name() const override { return "AtlasTextOp"; }
64
65 void visitProxies(const VisitProxyFunc& func) const override;
66
67#ifdef SK_DEBUG
68 SkString dumpInfo() const override;
69#endif
70
71 FixedFunctionFlags fixedFunctionFlags() const override;
72
73 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
74 bool hasMixedSampledCoverage, GrClampType) override;
75
76 enum MaskType {
77 kGrayscaleCoverageMask_MaskType,
78 kLCDCoverageMask_MaskType,
79 kColorBitmapMask_MaskType,
80 kAliasedDistanceField_MaskType,
81 kGrayscaleDistanceField_MaskType,
82 kLCDDistanceField_MaskType,
83 kLCDBGRDistanceField_MaskType,
84 };
85
86 MaskType maskType() const { return fMaskType; }
87
88 void finalizeForTextTarget(uint32_t color, const GrCaps&);
89 void executeForTextTarget(SkAtlasTextTarget*);
90
91private:
92 friend class GrOpMemoryPool; // for ctor
93
94 // The minimum number of Geometry we will try to allocate.
95 static constexpr auto kMinGeometryAllocated = 12;
96
97 GrAtlasTextOp(GrPaint&& paint)
98 : INHERITED(ClassID())
99 , fGeoDataAllocSize(kMinGeometryAllocated)
100 , fProcessors(std::move(paint)) {}
101
102 struct FlushInfo {
103 sk_sp<const GrBuffer> fVertexBuffer;
104 sk_sp<const GrBuffer> fIndexBuffer;
105 GrGeometryProcessor* fGeometryProcessor;
106 const GrSurfaceProxy** fPrimProcProxies;
107 int fGlyphsToFlush = 0;
108 int fVertexOffset = 0;
109 int fNumDraws = 0;
110 };
111
112 GrProgramInfo* programInfo() override {
113 // TODO [PI]: implement
114 return nullptr;
115 }
116
117 void onCreateProgramInfo(const GrCaps*,
118 SkArenaAlloc*,
119 const GrSurfaceProxyView* writeView,
120 GrAppliedClip&&,
121 const GrXferProcessor::DstProxyView&) override {
122 // TODO [PI]: implement
123 }
124
125 void onPrePrepareDraws(GrRecordingContext*,
126 const GrSurfaceProxyView* writeView,
127 GrAppliedClip*,
128 const GrXferProcessor::DstProxyView&) override {
129 // TODO [PI]: implement
130 }
131
132 void onPrepareDraws(Target*) override;
133 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
134
135 GrMaskFormat maskFormat() const {
136 switch (fMaskType) {
137 case kLCDCoverageMask_MaskType:
138 return kA565_GrMaskFormat;
139 case kColorBitmapMask_MaskType:
140 return kARGB_GrMaskFormat;
141 case kGrayscaleCoverageMask_MaskType:
142 case kAliasedDistanceField_MaskType:
143 case kGrayscaleDistanceField_MaskType:
144 case kLCDDistanceField_MaskType:
145 case kLCDBGRDistanceField_MaskType:
146 return kA8_GrMaskFormat;
147 }
148 return kA8_GrMaskFormat; // suppress warning
149 }
150
151 bool usesDistanceFields() const {
152 return kAliasedDistanceField_MaskType == fMaskType ||
153 kGrayscaleDistanceField_MaskType == fMaskType ||
154 kLCDDistanceField_MaskType == fMaskType ||
155 kLCDBGRDistanceField_MaskType == fMaskType;
156 }
157
158 bool isLCD() const {
159 return kLCDCoverageMask_MaskType == fMaskType ||
160 kLCDDistanceField_MaskType == fMaskType ||
161 kLCDBGRDistanceField_MaskType == fMaskType;
162 }
163
164 inline void createDrawForGeneratedGlyphs(
165 GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
166
167 const SkPMColor4f& color() const { SkASSERT(fGeoCount > 0); return fGeoData[0].fColor; }
168 bool usesLocalCoords() const { return fUsesLocalCoords; }
169 int numGlyphs() const { return fNumGlyphs; }
170
171 CombineResult onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
172 const GrCaps& caps) override;
173
174 GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*,
175 const GrShaderCaps&,
176 const GrSurfaceProxyView* views,
177 unsigned int numActiveViews) const;
178
179 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
180 int fGeoDataAllocSize;
181 GrProcessorSet fProcessors;
182 struct {
183 uint32_t fUsesLocalCoords : 1;
184 uint32_t fUseGammaCorrectDistanceTable : 1;
185 uint32_t fNeedsGlyphTransform : 1;
186 };
187 int fGeoCount;
188 int fNumGlyphs;
189 MaskType fMaskType;
190 // Distance field properties
191 SkColor fLuminanceColor;
192 uint32_t fDFGPFlags = 0;
193
194 typedef GrMeshDrawOp INHERITED;
195};
196
197#endif
198