Home | History | Annotate | Download | only in gl
      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:
     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 
     99 protected:
    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:
    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 
    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  */
    213 class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
    214 public:
    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 
    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 
    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 {
    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 GrGLTexGenProgramEffects* object.
    300  */
    301 class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
    302 public:
    303     GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
    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      */
    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