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