xref: /aosp_15_r20/external/skia/src/gpu/ganesh/effects/GrDistanceFieldGeoProc.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2013 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 GrDistanceFieldGeoProc_DEFINED
9 #define GrDistanceFieldGeoProc_DEFINED
10 
11 #if !defined(SK_DISABLE_SDF_TEXT)
12 
13 #include "include/core/SkMatrix.h"
14 #include "include/core/SkScalar.h"
15 #include "include/core/SkSize.h"
16 #include "src/base/SkArenaAlloc.h"
17 #include "src/gpu/ganesh/GrGeometryProcessor.h"
18 #include "src/gpu/ganesh/GrProcessorUnitTest.h"
19 #include "src/gpu/ganesh/GrSamplerState.h"
20 
21 #include <cstdint>
22 #include <memory>
23 
24 class GrSurfaceProxyView;
25 namespace skgpu { class KeyBuilder; }
26 struct GrShaderCaps;
27 
28 enum GrDistanceFieldEffectFlags {
29     kSimilarity_DistanceFieldEffectFlag   = 0x001, // ctm is similarity matrix
30     kScaleOnly_DistanceFieldEffectFlag    = 0x002, // ctm has only scale and translate
31     kPerspective_DistanceFieldEffectFlag  = 0x004, // ctm has perspective (and positions are x,y,w)
32     kUseLCD_DistanceFieldEffectFlag       = 0x008, // use lcd text
33     kBGR_DistanceFieldEffectFlag          = 0x010, // lcd display has bgr order
34     kPortrait_DistanceFieldEffectFlag     = 0x020, // lcd display is in portrait mode
35     kGammaCorrect_DistanceFieldEffectFlag = 0x040, // assume gamma-correct output (linear blending)
36     kAliased_DistanceFieldEffectFlag      = 0x080, // monochrome output
37     kWideColor_DistanceFieldEffectFlag    = 0x100, // use wide color (only for path)
38 
39     kInvalid_DistanceFieldEffectFlag      = 0x200,   // invalid state (for initialization)
40 
41     kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag |
42                                             kScaleOnly_DistanceFieldEffectFlag,
43     // The subset of the flags relevant to GrDistanceFieldA8TextGeoProc
44     kNonLCD_DistanceFieldEffectMask       = kSimilarity_DistanceFieldEffectFlag |
45                                             kScaleOnly_DistanceFieldEffectFlag |
46                                             kPerspective_DistanceFieldEffectFlag |
47                                             kGammaCorrect_DistanceFieldEffectFlag |
48                                             kAliased_DistanceFieldEffectFlag,
49     // The subset of the flags relevant to GrDistanceFieldPathGeoProc
50     kPath_DistanceFieldEffectMask         = kSimilarity_DistanceFieldEffectFlag |
51                                             kScaleOnly_DistanceFieldEffectFlag |
52                                             kPerspective_DistanceFieldEffectFlag |
53                                             kGammaCorrect_DistanceFieldEffectFlag |
54                                             kAliased_DistanceFieldEffectFlag |
55                                             kWideColor_DistanceFieldEffectFlag,
56     // The subset of the flags relevant to GrDistanceFieldLCDTextGeoProc
57     kLCD_DistanceFieldEffectMask          = kSimilarity_DistanceFieldEffectFlag |
58                                             kScaleOnly_DistanceFieldEffectFlag |
59                                             kPerspective_DistanceFieldEffectFlag |
60                                             kUseLCD_DistanceFieldEffectFlag |
61                                             kBGR_DistanceFieldEffectFlag |
62                                             kPortrait_DistanceFieldEffectFlag |
63                                             kGammaCorrect_DistanceFieldEffectFlag,
64 };
65 
66 /**
67  * The output color of this effect is a modulation of the input color and a sample from a
68  * distance field texture (using a smoothed step function near 0.5).
69  * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input
70  * coords are a custom attribute. Gamma correction is handled via a texture LUT.
71  */
72 class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
73 public:
74     inline static constexpr int kMaxTextures = 4;
75 
76     /** The local matrix should be identity if local coords are not required by the GrPipeline. */
77 #ifdef SK_GAMMA_APPLY_TO_A8
Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,float lum,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)78     static GrGeometryProcessor* Make(SkArenaAlloc* arena,
79                                      const GrShaderCaps& caps,
80                                      const GrSurfaceProxyView* views,
81                                      int numActiveViews,
82                                      GrSamplerState params,
83                                      float lum,
84                                      uint32_t flags,
85                                      const SkMatrix& localMatrixIfUsesLocalCoords) {
86         return arena->make([&](void* ptr) {
87             return new (ptr) GrDistanceFieldA8TextGeoProc(
88                     caps, views, numActiveViews, params, lum, flags, localMatrixIfUsesLocalCoords);
89         });
90     }
91 #else
Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)92     static GrGeometryProcessor* Make(SkArenaAlloc* arena,
93                                      const GrShaderCaps& caps,
94                                      const GrSurfaceProxyView* views,
95                                      int numActiveViews,
96                                      GrSamplerState params,
97                                      uint32_t flags,
98                                      const SkMatrix& localMatrixIfUsesLocalCoords) {
99         return arena->make([&](void* ptr) {
100             return new (ptr) GrDistanceFieldA8TextGeoProc(
101                     caps, views, numActiveViews, params, flags, localMatrixIfUsesLocalCoords);
102         });
103     }
104 #endif
105 
~GrDistanceFieldA8TextGeoProc()106     ~GrDistanceFieldA8TextGeoProc() override {}
107 
name()108     const char* name() const override { return "DistanceFieldA8Text"; }
109 
110     void addNewViews(const GrSurfaceProxyView* views, int numViews, GrSamplerState);
111 
112     void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override;
113 
114     std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
115 
116 private:
117     class Impl;
118 
119     GrDistanceFieldA8TextGeoProc(const GrShaderCaps& caps,
120                                  const GrSurfaceProxyView* views,
121                                  int numActiveViews,
122                                  GrSamplerState params,
123 #ifdef SK_GAMMA_APPLY_TO_A8
124                                  float distanceAdjust,
125 #endif
126                                  uint32_t flags,
127                                  const SkMatrix& localMatrix);
128 
onTextureSampler(int i)129     const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
130 
131     TextureSampler   fTextureSamplers[kMaxTextures];
132     SkISize          fAtlasDimensions;  // dimensions for all textures used with fTextureSamplers[].
133     SkMatrix         fLocalMatrix;
134     Attribute        fInPosition;
135     Attribute        fInColor;
136     Attribute        fInTextureCoords;
137     uint32_t         fFlags;
138 #ifdef SK_GAMMA_APPLY_TO_A8
139     float            fDistanceAdjust;
140 #endif
141 
142     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
143 
144     using INHERITED = GrGeometryProcessor;
145 };
146 
147 /**
148  * The output color of this effect is a modulation of the input color and a sample from a
149  * distance field texture (using a smoothed step function near 0.5).
150  * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input
151  * coords are a custom attribute. No gamma correct blending is applied. Used for paths only.
152  */
153 class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
154 public:
155     inline static constexpr int kMaxTextures = 4;
156 
157     /** The local matrix should be identity if local coords are not required by the GrPipeline. */
Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,const SkMatrix & localMatrix,uint32_t flags)158     static GrGeometryProcessor* Make(SkArenaAlloc* arena, const GrShaderCaps& caps,
159                                      const GrSurfaceProxyView* views, int numActiveViews,
160                                      GrSamplerState params, const SkMatrix& localMatrix,
161                                      uint32_t flags) {
162         return arena->make([&](void* ptr) {
163             return new (ptr) GrDistanceFieldPathGeoProc(caps, views, numActiveViews,
164                                                         params, localMatrix, flags);
165         });
166     }
167 
~GrDistanceFieldPathGeoProc()168     ~GrDistanceFieldPathGeoProc() override {}
169 
name()170     const char* name() const override { return "DistanceFieldPath"; }
171 
172     void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState);
173 
174     void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override;
175 
176     std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
177 
178 private:
179     class Impl;
180 
181     GrDistanceFieldPathGeoProc(const GrShaderCaps& caps,
182                                const GrSurfaceProxyView* views,
183                                int numActiveViews,
184                                GrSamplerState,
185                                const SkMatrix& localMatrix,
186                                uint32_t flags);
187 
onTextureSampler(int i)188     const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
189 
190     SkMatrix         fLocalMatrix;
191     TextureSampler   fTextureSamplers[kMaxTextures];
192     SkISize          fAtlasDimensions;  // dimensions for all textures used with fTextureSamplers[].
193     Attribute        fInPosition;
194     Attribute        fInColor;
195     Attribute        fInTextureCoords;
196     uint32_t         fFlags;
197 
198     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
199 
200     using INHERITED = GrGeometryProcessor;
201 };
202 
203 /**
204  * The output color of this effect is a modulation of the input color and samples from a
205  * distance field texture (using a smoothed step function near 0.5), adjusted for LCD displays.
206  * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input
207  * coords are a custom attribute. Gamma correction is handled via a texture LUT.
208  */
209 class GrDistanceFieldLCDTextGeoProc : public GrGeometryProcessor {
210 public:
211     inline static constexpr int kMaxTextures = 4;
212 
213     struct DistanceAdjust {
214         SkScalar fR, fG, fB;
MakeDistanceAdjust215         static DistanceAdjust Make(SkScalar r, SkScalar g, SkScalar b) {
216             DistanceAdjust result;
217             result.fR = r; result.fG = g; result.fB = b;
218             return result;
219         }
220         bool operator==(const DistanceAdjust& wa) const {
221             return (fR == wa.fR && fG == wa.fG && fB == wa.fB);
222         }
223         bool operator!=(const DistanceAdjust& wa) const {
224             return !(*this == wa);
225         }
226     };
227 
Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,DistanceAdjust distanceAdjust,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)228     static GrGeometryProcessor* Make(SkArenaAlloc* arena,
229                                      const GrShaderCaps& caps,
230                                      const GrSurfaceProxyView* views,
231                                      int numActiveViews,
232                                      GrSamplerState params,
233                                      DistanceAdjust distanceAdjust,
234                                      uint32_t flags,
235                                      const SkMatrix& localMatrixIfUsesLocalCoords) {
236         return arena->make([&](void* ptr) {
237             return new (ptr) GrDistanceFieldLCDTextGeoProc(caps, views, numActiveViews, params,
238                                                            distanceAdjust, flags,
239                                                            localMatrixIfUsesLocalCoords);
240         });
241     }
242 
~GrDistanceFieldLCDTextGeoProc()243     ~GrDistanceFieldLCDTextGeoProc() override {}
244 
name()245     const char* name() const override { return "DistanceFieldLCDText"; }
246 
247     void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState);
248 
249     void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override;
250 
251     std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
252 
253 private:
254     class Impl;
255 
256     GrDistanceFieldLCDTextGeoProc(const GrShaderCaps& caps, const GrSurfaceProxyView* views,
257                                   int numActiveViews, GrSamplerState params, DistanceAdjust wa,
258                                   uint32_t flags, const SkMatrix& localMatrix);
259 
onTextureSampler(int i)260     const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
261 
262     TextureSampler   fTextureSamplers[kMaxTextures];
263     SkISize          fAtlasDimensions;  // dimensions for all textures used with fTextureSamplers[].
264     const SkMatrix   fLocalMatrix;
265     DistanceAdjust   fDistanceAdjust;
266     Attribute        fInPosition;
267     Attribute        fInColor;
268     Attribute        fInTextureCoords;
269     uint32_t         fFlags;
270 
271     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
272 
273     using INHERITED = GrGeometryProcessor;
274 };
275 
276 #endif // !defined(SK_DISABLE_SDF_TEXT)
277 
278 #endif
279