• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 skgpu_ganesh_AtlasTextOp_DEFINED
9 #define skgpu_ganesh_AtlasTextOp_DEFINED
10 
11 #include "src/gpu/AtlasTypes.h"
12 #include "src/gpu/ganesh/GrColorSpaceXform.h"
13 #include "src/gpu/ganesh/effects/GrDistanceFieldGeoProc.h"
14 #include "src/gpu/ganesh/ops/GrMeshDrawOp.h"
15 #include "src/text/gpu/TextBlob.h"
16 
17 class GrProgramInfo;
18 class GrRecordingContext;
19 
20 namespace skgpu::ganesh {
21 
22 class AtlasTextOp final : public GrMeshDrawOp {
23 public:
24     DEFINE_OP_CLASS_ID
25 
~AtlasTextOp()26     ~AtlasTextOp() override {
27         for (const Geometry* g = fHead; g != nullptr;) {
28             const Geometry* next = g->fNext;
29             g->~Geometry();
30             g = next;
31         }
32     }
33 
34     void* operator new(size_t s);
35     void operator delete(void* b) noexcept;
36     static void ClearCache();
37 
38     struct Geometry {
GeometryGeometry39         Geometry(const sktext::gpu::AtlasSubRun& subRun,
40                  const SkMatrix& drawMatrix,
41                  SkPoint drawOrigin,
42                  SkIRect clipRect,
43                  sk_sp<SkRefCnt>&& supportData,
44                  const SkPMColor4f& color)
45             : fSubRun{subRun}
46             , fSupportDataKeepAlive{std::move(supportData)}
47             , fDrawMatrix{drawMatrix}
48             , fDrawOrigin{drawOrigin}
49             , fClipRect{clipRect}
50             , fColor{color} {
51                 SkASSERT(fSupportDataKeepAlive != nullptr);
52         }
53 
54         static Geometry* Make(const sktext::gpu::AtlasSubRun& subRun,
55                               const SkMatrix& drawMatrix,
56                               SkPoint drawOrigin,
57                               SkIRect clipRect,
58                               sk_sp<SkRefCnt>&& supportData,
59                               const SkPMColor4f& color,
60                               SkArenaAlloc* alloc);
61 
62         void fillVertexData(void* dst, int offset, int count) const;
63 
64         const sktext::gpu::AtlasSubRun& fSubRun;
65 
66         // Keep the TextBlob or Slug alive until the op is deleted.
67         sk_sp<SkRefCnt> fSupportDataKeepAlive;
68 
69         const SkMatrix fDrawMatrix;
70         const SkPoint fDrawOrigin;
71 
72         // fClipRect is only used in the DirectMaskSubRun case to do geometric clipping.
73         // TransformedMaskSubRun, and SDFTSubRun don't use this field, and expect an empty rect.
74         const SkIRect fClipRect;
75 
76         // Color is updated after processor analysis if it was determined the shader resolves to
77         // a constant color that we then evaluate on the CPU.
78         // TODO: This can be made const once processor analysis is separated from op creation.
79         SkPMColor4f fColor;
80         Geometry* fNext{nullptr};
81     };
82 
name()83     const char* name() const override { return "AtlasTextOp"; }
84 
85     void visitProxies(const GrVisitProxyFunc&) const override;
86 
87     FixedFunctionFlags fixedFunctionFlags() const override;
88 
89     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
90 
91     enum class MaskType : uint32_t {
92         kGrayscaleCoverage,
93         kLCDCoverage,
94         kColorBitmap,
95 #if !defined(SK_DISABLE_SDF_TEXT)
96         kAliasedDistanceField,
97         kGrayscaleDistanceField,
98         kLCDDistanceField,
99         kLCDBGRDistanceField,
100 
101         kLast = kLCDBGRDistanceField
102 #else
103         kLast = kColorBitmap
104 #endif
105     };
106     inline static constexpr int kMaskTypeCount = static_cast<int>(MaskType::kLast) + 1;
107 
108 #if GR_TEST_UTILS
109     static GrOp::Owner CreateOpTestingOnly(skgpu::v1::SurfaceDrawContext*,
110                                            const SkPaint&,
111                                            const SkFont&,
112                                            const SkMatrixProvider&,
113                                            const char* text,
114                                            int x,
115                                            int y);
116 #endif
117 
118 private:
119     friend class GrOp; // for ctor
120 
121     struct FlushInfo {
122         sk_sp<const GrBuffer> fVertexBuffer;
123         sk_sp<const GrBuffer> fIndexBuffer;
124         GrGeometryProcessor*  fGeometryProcessor;
125         const GrSurfaceProxy** fPrimProcProxies;
126         int fGlyphsToFlush = 0;
127         int fVertexOffset = 0;
128         int fNumDraws = 0;
129     };
130 
131     AtlasTextOp(MaskType maskType,
132                 bool needsTransform,
133                 int glyphCount,
134                 SkRect deviceRect,
135                 Geometry* geo,
136                 const GrColorInfo& dstColorInfo,
137                 GrPaint&& paint);
138 
139     AtlasTextOp(MaskType maskType,
140                 bool needsTransform,
141                 int glyphCount,
142                 SkRect deviceRect,
143                 SkColor luminanceColor,
144                 bool useGammaCorrectDistanceTable,
145                 uint32_t DFGPFlags,
146                 Geometry* geo,
147                 GrPaint&& paint);
148 
programInfo()149     GrProgramInfo* programInfo() override {
150         // TODO [PI]: implement
151         return nullptr;
152     }
153 
addGeometry(Geometry * geometry)154     void addGeometry(Geometry* geometry) {
155         *fTail = geometry;
156         // The geometry may have many entries. Find the end.
157         do {
158             fTail = &(*fTail)->fNext;
159         } while (*fTail != nullptr);
160     }
161 
onCreateProgramInfo(const GrCaps *,SkArenaAlloc *,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip &&,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)162     void onCreateProgramInfo(const GrCaps*,
163                              SkArenaAlloc*,
164                              const GrSurfaceProxyView& writeView,
165                              bool usesMSAASurface,
166                              GrAppliedClip&&,
167                              const GrDstProxyView&,
168                              GrXferBarrierFlags renderPassXferBarriers,
169                              GrLoadOp colorLoadOp) override {
170         // We cannot surface the AtlasTextOp's programInfo at record time. As currently
171         // implemented, the GP is modified at flush time based on the number of pages in the
172         // atlas.
173     }
174 
onPrePrepareDraws(GrRecordingContext *,const GrSurfaceProxyView & writeView,GrAppliedClip *,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)175     void onPrePrepareDraws(GrRecordingContext*,
176                            const GrSurfaceProxyView& writeView,
177                            GrAppliedClip*,
178                            const GrDstProxyView&,
179                            GrXferBarrierFlags renderPassXferBarriers,
180                            GrLoadOp colorLoadOp) override {
181         // TODO [PI]: implement
182     }
183 
184     void onPrepareDraws(GrMeshDrawTarget*) override;
185     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
186 
187 #if GR_TEST_UTILS
188     SkString onDumpInfo() const override;
189 #endif
190 
maskFormat()191     skgpu::MaskFormat maskFormat() const {
192         switch (this->maskType()) {
193             case MaskType::kLCDCoverage:
194                 return skgpu::MaskFormat::kA565;
195             case MaskType::kColorBitmap:
196                 return skgpu::MaskFormat::kARGB;
197             case MaskType::kGrayscaleCoverage:
198 #if !defined(SK_DISABLE_SDF_TEXT)
199             case MaskType::kAliasedDistanceField:
200             case MaskType::kGrayscaleDistanceField:
201             case MaskType::kLCDDistanceField:
202             case MaskType::kLCDBGRDistanceField:
203 #endif
204                 return skgpu::MaskFormat::kA8;
205         }
206         // SkUNREACHABLE;
207         return skgpu::MaskFormat::kA8;
208     }
209 
210 #if !defined(SK_DISABLE_SDF_TEXT)
usesDistanceFields()211     bool usesDistanceFields() const {
212         return MaskType::kAliasedDistanceField == this->maskType() ||
213                MaskType::kGrayscaleDistanceField == this->maskType() ||
214                MaskType::kLCDDistanceField == this->maskType() ||
215                MaskType::kLCDBGRDistanceField == this->maskType();
216     }
217 
isLCD()218     bool isLCD() const {
219         return MaskType::kLCDCoverage == this->maskType() ||
220                MaskType::kLCDDistanceField == this->maskType() ||
221                MaskType::kLCDBGRDistanceField == this->maskType();
222     }
223 #else
isLCD()224     bool isLCD() const {
225         return MaskType::kLCDCoverage == this->maskType();
226     }
227 #endif
228 
229     inline void createDrawForGeneratedGlyphs(
230             GrMeshDrawTarget* target, FlushInfo* flushInfo) const;
231 
maskType()232     MaskType maskType() const { return static_cast<MaskType>(fMaskType); }
233 
234     CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override;
235 
236 #if !defined(SK_DISABLE_SDF_TEXT)
237     GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*,
238                                           const GrShaderCaps&,
239                                           const SkMatrix& localMatrix,
240                                           const GrSurfaceProxyView* views,
241                                           unsigned int numActiveViews) const;
242 #endif
243 
244     GrProcessorSet fProcessors;
245     int fNumGlyphs; // Sum of glyphs in each geometry's subrun
246 
247     // All combinable atlas ops have equal bit field values
248     uint32_t fDFGPFlags                    : 10; // Distance field properties
249     uint32_t fMaskType                     : 3;  // MaskType
250     uint32_t fUsesLocalCoords              : 1;  // Filled in post processor analysis
251     uint32_t fNeedsGlyphTransform          : 1;
252     uint32_t fHasPerspective               : 1;  // True if perspective affects draw
253     uint32_t fUseGammaCorrectDistanceTable : 1;
254     static_assert(kMaskTypeCount <= 8, "MaskType does not fit in 3 bits");
255 #if !defined(SK_DISABLE_SDF_TEXT)
256     static_assert(kInvalid_DistanceFieldEffectFlag <= (1 << 9), "DFGP Flags do not fit in 10 bits");
257 #endif
258 
259     // Only needed for color emoji
260     sk_sp<GrColorSpaceXform> fColorSpaceXform;
261 
262     // Only used for distance fields; per-channel luminance for LCD, or gamma-corrected luminance
263     // for single-channel distance fields.
264     const SkColor fLuminanceColor{0};
265 
266     Geometry* fHead{nullptr};
267     Geometry** fTail{&fHead};
268 
269     using INHERITED = GrMeshDrawOp;
270 };
271 
272 } // namespace skgpu::ganesh
273 
274 #endif // skgpu_ganesh_AtlasTextOp_DEFINED
275