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
15class GrGLDistanceFieldA8TextGeoProc;
16class GrGLDistanceFieldPathGeoProc;
17class GrGLDistanceFieldLCDTextGeoProc;
18class GrInvariantOutput;
19
20enum 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 */
55class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
56public:
57#ifdef SK_ENABLE_SMALL_PAGE
58    inline static constexpr int kMaxTextures = 16;
59#else
60    inline static constexpr int kMaxTextures = 4;
61#endif
62
63    /** The local matrix should be identity if local coords are not required by the GrPipeline. */
64#ifdef SK_GAMMA_APPLY_TO_A8
65    static GrGeometryProcessor* Make(SkArenaAlloc* arena,
66                                     const GrShaderCaps& caps,
67                                     const GrSurfaceProxyView* views,
68                                     int numActiveViews,
69                                     GrSamplerState params,
70                                     float lum,
71                                     uint32_t flags,
72                                     const SkMatrix& localMatrixIfUsesLocalCoords) {
73        return arena->make([&](void* ptr) {
74            return new (ptr) GrDistanceFieldA8TextGeoProc(
75                    caps, views, numActiveViews, params, lum, flags, localMatrixIfUsesLocalCoords);
76        });
77    }
78#else
79    static GrGeometryProcessor* Make(SkArenaAlloc* arena,
80                                     const GrShaderCaps& caps,
81                                     const GrSurfaceProxyView* views,
82                                     int numActiveViews,
83                                     GrSamplerState params,
84                                     uint32_t flags,
85                                     const SkMatrix& localMatrixIfUsesLocalCoords) {
86        return arena->make([&](void* ptr) {
87            return new (ptr) GrDistanceFieldA8TextGeoProc(
88                    caps, views, numActiveViews, params, flags, localMatrixIfUsesLocalCoords);
89        });
90    }
91#endif
92
93    ~GrDistanceFieldA8TextGeoProc() override {}
94
95    const char* name() const override { return "DistanceFieldA8Text"; }
96
97    SkString getShaderDfxInfo() const override;
98
99    void addNewViews(const GrSurfaceProxyView* views, int numViews, GrSamplerState);
100
101    void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
102
103    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
104
105private:
106    class Impl;
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    using INHERITED = GrGeometryProcessor;
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 */
142class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
143public:
144#ifdef SK_ENABLE_SMALL_PAGE
145    inline static constexpr int kMaxTextures = 16;
146#else
147    inline static constexpr int kMaxTextures = 4;
148#endif
149
150    /** The local matrix should be identity if local coords are not required by the GrPipeline. */
151    static GrGeometryProcessor* Make(SkArenaAlloc* arena, const GrShaderCaps& caps,
152                                     const SkMatrix& matrix, bool wideColor,
153                                     const GrSurfaceProxyView* views, int numActiveViews,
154                                     GrSamplerState params, uint32_t flags) {
155        return arena->make([&](void* ptr) {
156            return new (ptr) GrDistanceFieldPathGeoProc(caps, matrix, wideColor, views,
157                                                        numActiveViews, params, flags);
158        });
159    }
160
161    ~GrDistanceFieldPathGeoProc() override {}
162
163    const char* name() const override { return "DistanceFieldPath"; }
164
165    SkString getShaderDfxInfo() const override;
166
167    void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState);
168
169    void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
170
171    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
172
173private:
174    class Impl;
175
176    GrDistanceFieldPathGeoProc(const GrShaderCaps& caps,
177                               const SkMatrix& matrix,
178                               bool wideColor,
179                               const GrSurfaceProxyView* views,
180                               int numActiveViews,
181                               GrSamplerState,
182                               uint32_t flags);
183
184    const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
185
186    SkMatrix         fMatrix;     // view matrix if perspective, local matrix otherwise
187    TextureSampler   fTextureSamplers[kMaxTextures];
188    SkISize          fAtlasDimensions;  // dimensions for all textures used with fTextureSamplers[].
189    Attribute        fInPosition;
190    Attribute        fInColor;
191    Attribute        fInTextureCoords;
192    uint32_t         fFlags;
193
194    GR_DECLARE_GEOMETRY_PROCESSOR_TEST
195
196    using INHERITED = GrGeometryProcessor;
197};
198
199/**
200 * The output color of this effect is a modulation of the input color and samples from a
201 * distance field texture (using a smoothed step function near 0.5), adjusted for LCD displays.
202 * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input
203 * coords are a custom attribute. Gamma correction is handled via a texture LUT.
204 */
205class GrDistanceFieldLCDTextGeoProc : public GrGeometryProcessor {
206public:
207#ifdef SK_ENABLE_SMALL_PAGE
208    inline static constexpr int kMaxTextures = 16;
209#else
210    inline static constexpr int kMaxTextures = 4;
211#endif
212
213    struct DistanceAdjust {
214        SkScalar fR, fG, fB;
215        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
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
243    ~GrDistanceFieldLCDTextGeoProc() override {}
244
245    const char* name() const override { return "DistanceFieldLCDText"; }
246
247    SkString getShaderDfxInfo() const override;
248
249    void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState);
250
251    void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
252
253    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
254
255private:
256    class Impl;
257
258    GrDistanceFieldLCDTextGeoProc(const GrShaderCaps& caps, const GrSurfaceProxyView* views,
259                                  int numActiveViews, GrSamplerState params, DistanceAdjust wa,
260                                  uint32_t flags, const SkMatrix& localMatrix);
261
262    const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; }
263
264    TextureSampler   fTextureSamplers[kMaxTextures];
265    SkISize          fAtlasDimensions;  // dimensions for all textures used with fTextureSamplers[].
266    const SkMatrix   fLocalMatrix;
267    DistanceAdjust   fDistanceAdjust;
268    Attribute        fInPosition;
269    Attribute        fInColor;
270    Attribute        fInTextureCoords;
271    uint32_t         fFlags;
272
273    GR_DECLARE_GEOMETRY_PROCESSOR_TEST
274
275    using INHERITED = GrGeometryProcessor;
276};
277
278#endif
279