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