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 |
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 |
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 | |
85 | ~GrDistanceFieldA8TextGeoProc() override {} |
86 | |
87 | const char* name() const override { return "DistanceFieldA8Text" ; } |
88 | |
89 | const Attribute& inPosition() const { return fInPosition; } |
90 | const Attribute& inColor() const { return fInColor; } |
91 | const Attribute& inTextureCoords() const { return fInTextureCoords; } |
92 | const SkMatrix& localMatrix() const { return fLocalMatrix; } |
93 | #ifdef SK_GAMMA_APPLY_TO_A8 |
94 | float getDistanceAdjust() const { return fDistanceAdjust; } |
95 | #endif |
96 | uint32_t getFlags() const { return fFlags; } |
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 | |
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. */ |
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 | |
155 | ~GrDistanceFieldPathGeoProc() override {} |
156 | |
157 | const char* name() const override { return "DistanceFieldPath" ; } |
158 | |
159 | const Attribute& inPosition() const { return fInPosition; } |
160 | const Attribute& inColor() const { return fInColor; } |
161 | const Attribute& inTextureCoords() const { return fInTextureCoords; } |
162 | const SkMatrix& matrix() const { return fMatrix; } |
163 | uint32_t getFlags() const { return fFlags; } |
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 | |
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; |
210 | 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 | |
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 | |
236 | ~GrDistanceFieldLCDTextGeoProc() override {} |
237 | |
238 | const char* name() const override { return "DistanceFieldLCDText" ; } |
239 | |
240 | const Attribute& inPosition() const { return fInPosition; } |
241 | const Attribute& inColor() const { return fInColor; } |
242 | const Attribute& inTextureCoords() const { return fInTextureCoords; } |
243 | DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; } |
244 | uint32_t getFlags() const { return fFlags; } |
245 | const SkMatrix& localMatrix() const { return fLocalMatrix; } |
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 | |
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 | |