• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 class GrEffectStage;
17 class GrGLVertexProgramEffectsBuilder;
18 class GrGLShaderBuilder;
19 class GrGLFullShaderBuilder;
20 class 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  */
27 class GrGLProgramEffects : public SkRefCnt {
28 public:
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:
TransformedCoords(const SkString & name,GrSLType type)59         TransformedCoords(const SkString& name, GrSLType type)
60             : fName(name), fType(type) {
61         }
62 
c_str()63         const char* c_str() const { return fName.c_str(); }
type()64         GrSLType type() const { return fType; }
getName()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:
TextureSampler(UniformHandle uniform,const GrTextureAccess & access)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 
samplerUniform()86         UniformHandle samplerUniform() const { return fSamplerUniform; }
87         // bitfield of GrColorComponentFlags present in the texture's config.
configComponentMask()88         uint32_t configComponentMask() const { return fConfigComponentMask; }
swizzle()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 
99 protected:
GrGLProgramEffects(int reserveCount)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 private:
127     typedef SkRefCnt INHERITED;
128 };
129 
130 /**
131  * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
132  */
133 class GrGLProgramEffectsBuilder {
134 public:
~GrGLProgramEffectsBuilder()135     virtual ~GrGLProgramEffectsBuilder() { }
136 
137     /**
138      * Emits the effect's shader code, and stores the necessary uniforms internally.
139      */
140     virtual void emitEffect(const GrEffectStage&,
141                             GrGLProgramEffects::EffectKey,
142                             const char* outColor,
143                             const char* inColor,
144                             int stageIndex) = 0;
145 };
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 
149 /**
150  * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
151  */
152 class GrGLVertexProgramEffects : public GrGLProgramEffects {
153 public:
154     virtual void setData(GrGpuGL*,
155                          const GrGLUniformManager&,
156                          const GrEffectStage* effectStages[]) SK_OVERRIDE;
157 
158 private:
159     friend class GrGLVertexProgramEffectsBuilder;
160 
GrGLVertexProgramEffects(int reserveCount,bool explicitLocalCoords)161     GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
162         : INHERITED(reserveCount)
163         , fTransforms(reserveCount)
164         , fHasExplicitLocalCoords(explicitLocalCoords) {
165     }
166 
167     /**
168      * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
169      * during the construction phase.
170      */
171     void emitEffect(GrGLFullShaderBuilder*,
172                     const GrEffectStage&,
173                     GrGLProgramEffects::EffectKey,
174                     const char* outColor,
175                     const char* inColor,
176                     int stageIndex);
177 
178     /**
179      * Helper for emitEffect(). Emits any attributes an effect may have.
180      */
181     void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
182 
183     /**
184      * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
185      * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
186      * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
187      * of the varyings in the VS and FS as well their types are appended to the
188      * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
189      */
190     void emitTransforms(GrGLFullShaderBuilder*,
191                         const GrEffectRef&,
192                         EffectKey,
193                         TransformedCoordsArray*);
194 
195     /**
196      * Helper for setData(). Sets all the transform matrices for an effect.
197      */
198     void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
199 
200     struct Transform {
TransformTransform201         Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
202         UniformHandle fHandle;
203         GrSLType      fType;
204         SkMatrix      fCurrentValue;
205     };
206 
207     SkTArray<SkSTArray<2, Transform, true> > fTransforms;
208     bool                                     fHasExplicitLocalCoords;
209 
210     typedef GrGLProgramEffects INHERITED;
211 };
212 
213 /**
214  * This class is used to construct a GrGLVertexProgramEffects* object.
215  */
216 class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
217 public:
218     GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
~GrGLVertexProgramEffectsBuilder()219     virtual ~GrGLVertexProgramEffectsBuilder() { }
220 
221     virtual void emitEffect(const GrEffectStage&,
222                             GrGLProgramEffects::EffectKey,
223                             const char* outColor,
224                             const char* inColor,
225                             int stageIndex) SK_OVERRIDE;
226 
227     /**
228      * Finalizes the building process and returns the effect array. After this call, the builder
229      * becomes invalid.
230      */
finish()231     GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
232 
233 private:
234     GrGLFullShaderBuilder*                  fBuilder;
235     SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
236 
237     typedef GrGLProgramEffectsBuilder INHERITED;
238 };
239 
240 ////////////////////////////////////////////////////////////////////////////////
241 
242 /**
243  * This is a GrGLProgramEffects implementation that does coord transforms with
244  * the the  NV_path_rendering PathTexGen functionality.
245  */
246 class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
247 public:
248     virtual void setData(GrGpuGL*,
249                          const GrGLUniformManager&,
250                          const GrEffectStage* effectStages[]) SK_OVERRIDE;
251 
252 private:
253     friend class GrGLPathTexGenProgramEffectsBuilder;
254 
GrGLPathTexGenProgramEffects(int reserveCount)255     GrGLPathTexGenProgramEffects(int reserveCount)
256         : INHERITED(reserveCount)
257         , fTransforms(reserveCount) {
258     }
259 
260     /**
261      * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
262      * during the construction phase.
263      */
264     void emitEffect(GrGLFragmentOnlyShaderBuilder*,
265                     const GrEffectStage&,
266                     GrGLProgramEffects::EffectKey,
267                     const char* outColor,
268                     const char* inColor,
269                     int stageIndex);
270 
271     /**
272      * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
273      * effect. The transforms all use adjacent texture units. They either use two or three of the
274      * coordinates at a given texture unit, depending on if they need perspective interpolation.
275      * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
276      * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
277      * effect's emitCode() function.
278      */
279     void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
280                          const GrEffectRef&,
281                          EffectKey,
282                          TransformedCoordsArray*);
283 
284     /**
285      * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
286      */
287     void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
288 
289     struct Transforms {
TransformsTransforms290         Transforms(EffectKey transformKey, int texCoordIndex)
291             : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
292         EffectKey fTransformKey;
293         int fTexCoordIndex;
294     };
295 
296     SkTArray<Transforms> fTransforms;
297 
298     typedef GrGLProgramEffects INHERITED;
299 };
300 
301 /**
302  * This class is used to construct a GrGLPathTexGenProgramEffects* object.
303  */
304 class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
305 public:
306     GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
~GrGLPathTexGenProgramEffectsBuilder()307     virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
308 
309     virtual void emitEffect(const GrEffectStage&,
310                             GrGLProgramEffects::EffectKey,
311                             const char* outColor,
312                             const char* inColor,
313                             int stageIndex) SK_OVERRIDE;
314 
315     /**
316      * Finalizes the building process and returns the effect array. After this call, the builder
317      * becomes invalid.
318      */
finish()319     GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
320 
321 private:
322     GrGLFragmentOnlyShaderBuilder*          fBuilder;
323     SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
324 
325     typedef GrGLProgramEffectsBuilder INHERITED;
326 };
327 
328 #endif
329