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 : 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:
     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 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:
    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 
    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 {
    201         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);
    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      */
    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 
    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 {
    290         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);
    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      */
    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