• 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 {
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 
127 /**
128  * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
129  */
130 class GrGLProgramEffectsBuilder {
131 public:
~GrGLProgramEffectsBuilder()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  */
149 class GrGLVertexProgramEffects : public GrGLProgramEffects {
150 public:
151     virtual void setData(GrGpuGL*,
152                          const GrGLUniformManager&,
153                          const GrEffectStage* effectStages[]) SK_OVERRIDE;
154 
155 private:
156     friend class GrGLVertexProgramEffectsBuilder;
157 
GrGLVertexProgramEffects(int reserveCount,bool explicitLocalCoords)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 {
TransformTransform198         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  */
213 class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
214 public:
215     GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
~GrGLVertexProgramEffectsBuilder()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      */
finish()228     GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
229 
230 private:
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 the the built-in GL
241  * TexGen functionality.
242  */
243 class GrGLTexGenProgramEffects : public GrGLProgramEffects {
244 public:
245     virtual void setData(GrGpuGL*,
246                          const GrGLUniformManager&,
247                          const GrEffectStage* effectStages[]) SK_OVERRIDE;
248 
249 private:
250     friend class GrGLTexGenProgramEffectsBuilder;
251 
GrGLTexGenProgramEffects(int reserveCount)252     GrGLTexGenProgramEffects(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 setupTexGen(GrGLFragmentOnlyShaderBuilder*,
277                      const GrEffectRef&,
278                      EffectKey,
279                      TransformedCoordsArray*);
280 
281     /**
282      * Helper for setData(). Sets the TexGen state for each transform in an effect.
283      */
284     void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
285 
286     struct Transforms {
TransformsTransforms287         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 GrGLTexGenProgramEffects* object.
300  */
301 class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
302 public:
303     GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
~GrGLTexGenProgramEffectsBuilder()304     virtual ~GrGLTexGenProgramEffectsBuilder() { }
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      */
finish()316     GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
317 
318 private:
319     GrGLFragmentOnlyShaderBuilder*          fBuilder;
320     SkAutoTDelete<GrGLTexGenProgramEffects> fProgramEffects;
321 
322     typedef GrGLProgramEffectsBuilder INHERITED;
323 };
324 
325 #endif
326