GrGLProgramEffects.h revision 0a6fe71f1bc0e601b41b7ae6d28b8c96a2c41116
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 GrGLProgramEffects_DEFINED
9#define GrGLProgramEffects_DEFINED
10
11#include "GrBackendEffectFactory.h"
12#include "GrTexture.h"
13#include "GrTextureAccess.h"
14#include "GrGLUniformManager.h"
15
16class GrEffectStage;
17class GrGLVertexProgramEffectsBuilder;
18class GrGLShaderBuilder;
19class GrGLFullShaderBuilder;
20class GrGLFragmentOnlyShaderBuilder;
21
22/**
23 * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms
24 * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
25 * state and shader uniforms.
26 */
27class GrGLProgramEffects {
28public:
29    typedef GrBackendEffectFactory::EffectKey EffectKey;
30    typedef GrGLUniformManager::UniformHandle UniformHandle;
31
32    /**
33     * These methods generate different portions of an effect's final key.
34     */
35    static EffectKey GenAttribKey(const GrDrawEffect&);
36    static EffectKey GenTransformKey(const GrDrawEffect&);
37    static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
38
39    virtual ~GrGLProgramEffects();
40
41    /**
42     * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
43     * available unit to *texUnitIdx when it returns.
44     */
45    void initSamplers(const GrGLUniformManager&, int* texUnitIdx);
46
47    /**
48     * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
49     */
50    virtual void setData(GrGpuGL*,
51                         const GrGLUniformManager&,
52                         const GrEffectStage* effectStages[]) = 0;
53
54    /**
55     * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
56     */
57    class TransformedCoords {
58    public:
59        TransformedCoords(const SkString& name, GrSLType type)
60            : fName(name), fType(type) {
61        }
62
63        const char* c_str() const { return fName.c_str(); }
64        GrSLType type() const { return fType; }
65        const SkString& getName() const { return fName; }
66
67    private:
68        SkString fName;
69        GrSLType fType;
70    };
71
72    typedef SkTArray<TransformedCoords> TransformedCoordsArray;
73
74    /**
75     * Passed to GrGLEffects so they can add texture reads to their shader code.
76     */
77    class TextureSampler {
78    public:
79        TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
80            : fSamplerUniform(uniform)
81            , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
82            SkASSERT(0 != fConfigComponentMask);
83            memcpy(fSwizzle, access.getSwizzle(), 5);
84        }
85
86        UniformHandle samplerUniform() const { return fSamplerUniform; }
87        // bitfield of GrColorComponentFlags present in the texture's config.
88        uint32_t configComponentMask() const { return fConfigComponentMask; }
89        const char* swizzle() const { return fSwizzle; }
90
91    private:
92        UniformHandle fSamplerUniform;
93        uint32_t      fConfigComponentMask;
94        char          fSwizzle[5];
95    };
96
97    typedef SkTArray<TextureSampler> TextureSamplerArray;
98
99protected:
100    GrGLProgramEffects(int reserveCount)
101        : fGLEffects(reserveCount)
102        , fSamplers(reserveCount) {
103    }
104
105    /**
106     * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
107     * appends the necessary data to the TextureSamplerArray* object so effects can add texture
108     * lookups to their code. This method is only meant to be called during the construction phase.
109     */
110    void emitSamplers(GrGLShaderBuilder*, const GrEffectRef&, TextureSamplerArray*);
111
112    /**
113     * Helper for setData(). Binds all the textures for an effect.
114     */
115    void bindTextures(GrGpuGL*, const GrEffectRef&, int effectIdx);
116
117    struct Sampler {
118        SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
119        UniformHandle fUniform;
120        int           fTextureUnit;
121    };
122
123    SkTArray<GrGLEffect*>                  fGLEffects;
124    SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
125};
126
127/**
128 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
129 */
130class GrGLProgramEffectsBuilder {
131public:
132    virtual ~GrGLProgramEffectsBuilder() { }
133
134    /**
135     * Emits the effect's shader code, and stores the necessary uniforms internally.
136     */
137    virtual void emitEffect(const GrEffectStage&,
138                            GrGLProgramEffects::EffectKey,
139                            const char* outColor,
140                            const char* inColor,
141                            int stageIndex) = 0;
142};
143
144////////////////////////////////////////////////////////////////////////////////
145
146/**
147 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
148 */
149class GrGLVertexProgramEffects : public GrGLProgramEffects {
150public:
151    virtual void setData(GrGpuGL*,
152                         const GrGLUniformManager&,
153                         const GrEffectStage* effectStages[]) SK_OVERRIDE;
154
155private:
156    friend class GrGLVertexProgramEffectsBuilder;
157
158    GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
159        : INHERITED(reserveCount)
160        , fTransforms(reserveCount)
161        , fHasExplicitLocalCoords(explicitLocalCoords) {
162    }
163
164    /**
165     * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
166     * during the construction phase.
167     */
168    void emitEffect(GrGLFullShaderBuilder*,
169                    const GrEffectStage&,
170                    GrGLProgramEffects::EffectKey,
171                    const char* outColor,
172                    const char* inColor,
173                    int stageIndex);
174
175    /**
176     * Helper for emitEffect(). Emits any attributes an effect may have.
177     */
178    void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
179
180    /**
181     * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
182     * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
183     * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
184     * of the varyings in the VS and FS as well their types are appended to the
185     * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
186     */
187    void emitTransforms(GrGLFullShaderBuilder*,
188                        const GrEffectRef&,
189                        EffectKey,
190                        TransformedCoordsArray*);
191
192    /**
193     * Helper for setData(). Sets all the transform matrices for an effect.
194     */
195    void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
196
197    struct Transform {
198        Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
199        UniformHandle fHandle;
200        GrSLType      fType;
201        SkMatrix      fCurrentValue;
202    };
203
204    SkTArray<SkSTArray<2, Transform, true> > fTransforms;
205    bool                                     fHasExplicitLocalCoords;
206
207    typedef GrGLProgramEffects INHERITED;
208};
209
210/**
211 * This class is used to construct a GrGLVertexProgramEffects* object.
212 */
213class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
214public:
215    GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
216    virtual ~GrGLVertexProgramEffectsBuilder() { }
217
218    virtual void emitEffect(const GrEffectStage&,
219                            GrGLProgramEffects::EffectKey,
220                            const char* outColor,
221                            const char* inColor,
222                            int stageIndex) SK_OVERRIDE;
223
224    /**
225     * Finalizes the building process and returns the effect array. After this call, the builder
226     * becomes invalid.
227     */
228    GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
229
230private:
231    GrGLFullShaderBuilder*                  fBuilder;
232    SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
233
234    typedef GrGLProgramEffectsBuilder INHERITED;
235};
236
237////////////////////////////////////////////////////////////////////////////////
238
239/**
240 * This is a GrGLProgramEffects implementation that does coord transforms with
241 * the the  NV_path_rendering PathTexGen functionality.
242 */
243class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
244public:
245    virtual void setData(GrGpuGL*,
246                         const GrGLUniformManager&,
247                         const GrEffectStage* effectStages[]) SK_OVERRIDE;
248
249private:
250    friend class GrGLPathTexGenProgramEffectsBuilder;
251
252    GrGLPathTexGenProgramEffects(int reserveCount)
253        : INHERITED(reserveCount)
254        , fTransforms(reserveCount) {
255    }
256
257    /**
258     * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
259     * during the construction phase.
260     */
261    void emitEffect(GrGLFragmentOnlyShaderBuilder*,
262                    const GrEffectStage&,
263                    GrGLProgramEffects::EffectKey,
264                    const char* outColor,
265                    const char* inColor,
266                    int stageIndex);
267
268    /**
269     * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
270     * effect. The transforms all use adjacent texture units. They either use two or three of the
271     * coordinates at a given texture unit, depending on if they need perspective interpolation.
272     * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
273     * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
274     * effect's emitCode() function.
275     */
276    void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
277                         const GrEffectRef&,
278                         EffectKey,
279                         TransformedCoordsArray*);
280
281    /**
282     * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
283     */
284    void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
285
286    struct Transforms {
287        Transforms(EffectKey transformKey, int texCoordIndex)
288            : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
289        EffectKey fTransformKey;
290        int fTexCoordIndex;
291    };
292
293    SkTArray<Transforms> fTransforms;
294
295    typedef GrGLProgramEffects INHERITED;
296};
297
298/**
299 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
300 */
301class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
302public:
303    GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
304    virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
305
306    virtual void emitEffect(const GrEffectStage&,
307                            GrGLProgramEffects::EffectKey,
308                            const char* outColor,
309                            const char* inColor,
310                            int stageIndex) SK_OVERRIDE;
311
312    /**
313     * Finalizes the building process and returns the effect array. After this call, the builder
314     * becomes invalid.
315     */
316    GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
317
318private:
319    GrGLFragmentOnlyShaderBuilder*          fBuilder;
320    SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
321
322    typedef GrGLProgramEffectsBuilder INHERITED;
323};
324
325#endif
326