Home | History | Annotate | Download | only in builders
      1 /*
      2  * Copyright 2014 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 GrGLProgramBuilder_DEFINED
      9 #define GrGLProgramBuilder_DEFINED
     10 
     11 #include "GrAllocator.h"
     12 #include "GrBackendProcessorFactory.h"
     13 #include "GrColor.h"
     14 #include "GrProcessor.h"
     15 #include "GrGLFragmentShaderBuilder.h"
     16 #include "GrGLGeometryShaderBuilder.h"
     17 #include "GrGLVertexShaderBuilder.h"
     18 #include "SkTypes.h"
     19 #include "gl/GrGLProcessor.h"
     20 #include "gl/GrGLProgramDesc.h"
     21 #include "gl/GrGLProgramEffects.h"
     22 #include "gl/GrGLSL.h"
     23 #include "gl/GrGLProgramDataManager.h"
     24 
     25 #include <stdarg.h>
     26 
     27 class GrGLContextInfo;
     28 class GrProcessorStage;
     29 class GrGLProgramDesc;
     30 
     31 /**
     32   Contains all the incremental state of a shader as it is being built,as well as helpers to
     33   manipulate that state.
     34 */
     35 class GrGLProgramBuilder {
     36 public:
     37     enum ShaderVisibility {
     38         kVertex_Visibility   = 0x1,
     39         kGeometry_Visibility = 0x2,
     40         kFragment_Visibility = 0x4,
     41     };
     42 
     43     typedef GrGLProgramDataManager::UniformHandle UniformHandle;
     44     typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
     45 
     46     // Handles for program uniforms (other than per-effect uniforms)
     47     struct BuiltinUniformHandles {
     48         UniformHandle       fViewMatrixUni;
     49         UniformHandle       fRTAdjustmentUni;
     50         UniformHandle       fColorUni;
     51         UniformHandle       fCoverageUni;
     52 
     53         // We use the render target height to provide a y-down frag coord when specifying
     54         // origin_upper_left is not supported.
     55         UniformHandle       fRTHeightUni;
     56 
     57         // Uniforms for computing texture coords to do the dst-copy lookup
     58         UniformHandle       fDstCopyTopLeftUni;
     59         UniformHandle       fDstCopyScaleUni;
     60         UniformHandle       fDstCopySamplerUni;
     61     };
     62 
     63     struct UniformInfo {
     64         GrGLShaderVar fVariable;
     65         uint32_t      fVisibility;
     66         GrGLint       fLocation;
     67     };
     68 
     69     // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
     70     // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
     71     // name strings. Otherwise, we'd have to hand out copies.
     72     typedef GrTAllocator<UniformInfo> UniformInfoArray;
     73 
     74     struct SeparableVaryingInfo {
     75         GrGLShaderVar fVariable;
     76         GrGLint       fLocation;
     77     };
     78 
     79     typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
     80 
     81     /** Generates a shader program.
     82      *
     83      * The program implements what is specified in the stages given as input.
     84      * After successful generation, the builder result objects are available
     85      * to be used.
     86      * @return true if generation was successful.
     87      */
     88 
     89     bool genProgram(const GrGeometryStage* inGeometryProcessor,
     90                     const GrFragmentStage* inColorStages[],
     91                     const GrFragmentStage* inCoverageStages[]);
     92 
     93     GrGLProgramEffects* getGeometryProcessor() const {
     94         SkASSERT(fProgramID); return fGeometryProcessor.get();
     95     }
     96     GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
     97     GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
     98     const BuiltinUniformHandles& getBuiltinUniformHandles() const {
     99         SkASSERT(fProgramID);
    100         return fUniformHandles;
    101     }
    102     GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
    103     bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
    104     int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
    105     const UniformInfoArray& getUniformInfos() const { return fUniforms; }
    106     const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
    107         return fSeparableVaryingInfos;
    108     }
    109 
    110     virtual ~GrGLProgramBuilder() {}
    111 
    112     /** Add a uniform variable to the current program, that has visibility in one or more shaders.
    113         visibility is a bitfield of ShaderVisibility values indicating from which shaders the
    114         uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
    115         supported at this time. The actual uniform name will be mangled. If outName is not NULL then
    116         it will refer to the final uniform name after return. Use the addUniformArray variant to add
    117         an array of uniforms. */
    118     GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
    119                                                      GrSLType type,
    120                                                      const char* name,
    121                                                      const char** outName = NULL) {
    122         return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
    123     }
    124     GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
    125                                                           GrSLType type,
    126                                                           const char* name,
    127                                                           int arrayCount,
    128                                                           const char** outName = NULL);
    129 
    130     const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
    131         return fUniforms[u.toShaderBuilderIndex()].fVariable;
    132     }
    133 
    134     /**
    135      * Shortcut for getUniformVariable(u).c_str()
    136      */
    137     const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
    138         return this->getUniformVariable(u).c_str();
    139     }
    140 
    141     const GrGLContextInfo& ctxInfo() const;
    142 
    143     GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
    144     GrGpuGL* gpu() const { return fGpu; }
    145 
    146 protected:
    147     typedef GrTAllocator<GrGLShaderVar> VarArray;
    148     GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
    149 
    150     const GrGLProgramDesc& desc() const { return fDesc; }
    151 
    152     // Helper for emitEffects().
    153     void createAndEmitEffects(const GrFragmentStage* effectStages[],
    154                               int effectCnt,
    155                               const GrGLProgramDesc::EffectKeyProvider&,
    156                               GrGLSLExpr4* inOutFSColor);
    157 
    158     /*
    159      * A helper function called to emit the geometry processor as well as individual coverage
    160      * and color stages.  this will call into subclasses emit effect
    161      */
    162     void emitEffect(const GrProcessorStage& effectStage,
    163                     int effectIndex,
    164                     const GrGLProgramDesc::EffectKeyProvider& keyProvider,
    165                     GrGLSLExpr4* inColor,
    166                     GrGLSLExpr4* outColor);
    167 
    168     /**
    169      * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
    170      * appends the necessary data to the TextureSamplerArray* object so effects can add texture
    171      * lookups to their code. This method is only meant to be called during the construction phase.
    172      */
    173     void emitSamplers(const GrProcessor& effect,
    174                       GrGLProcessor::TextureSamplerArray* outSamplers);
    175 
    176     // Generates a name for a variable. The generated string will be name prefixed by the prefix
    177     // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
    178     // generating stage code.
    179     void nameVariable(SkString* out, char prefix, const char* name);
    180 
    181     virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
    182 
    183     virtual void bindProgramLocations(GrGLuint programId);
    184     void resolveProgramLocations(GrGLuint programId);
    185 
    186     void appendDecls(const VarArray&, SkString*) const;
    187     void appendUniformDecls(ShaderVisibility, SkString*) const;
    188 
    189     class CodeStage : SkNoncopyable {
    190     public:
    191         CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
    192 
    193         bool inStageCode() const {
    194             this->validate();
    195             return SkToBool(fEffectStage);
    196         }
    197 
    198         const GrProcessorStage* effectStage() const {
    199             this->validate();
    200             return fEffectStage;
    201         }
    202 
    203         int stageIndex() const {
    204             this->validate();
    205             return fCurrentIndex;
    206         }
    207 
    208         class AutoStageRestore : SkNoncopyable {
    209         public:
    210             AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
    211                 SkASSERT(codeStage);
    212                 fSavedIndex = codeStage->fCurrentIndex;
    213                 fSavedEffectStage = codeStage->fEffectStage;
    214 
    215                 if (NULL == newStage) {
    216                     codeStage->fCurrentIndex = -1;
    217                 } else {
    218                     codeStage->fCurrentIndex = codeStage->fNextIndex++;
    219                 }
    220                 codeStage->fEffectStage = newStage;
    221 
    222                 fCodeStage = codeStage;
    223             }
    224             ~AutoStageRestore() {
    225                 fCodeStage->fCurrentIndex = fSavedIndex;
    226                 fCodeStage->fEffectStage = fSavedEffectStage;
    227             }
    228         private:
    229             CodeStage*              fCodeStage;
    230             int                     fSavedIndex;
    231             const GrProcessorStage*    fSavedEffectStage;
    232         };
    233     private:
    234         void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
    235         int                     fNextIndex;
    236         int                     fCurrentIndex;
    237         const GrProcessorStage*    fEffectStage;
    238     };
    239 
    240     class GrGLProcessorEmitterInterface {
    241      public:
    242         virtual ~GrGLProcessorEmitterInterface() {}
    243         virtual GrGLProcessor* createGLInstance() = 0;
    244         virtual void emit(const GrProcessorKey& key,
    245                           const char* outColor,
    246                           const char* inColor,
    247                           const GrGLProcessor::TransformedCoordsArray& coords,
    248                           const GrGLProcessor::TextureSamplerArray& samplers) = 0;
    249     };
    250 
    251     class GrGLFragmentProcessorEmitter  : public GrGLProcessorEmitterInterface {
    252     public:
    253         GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
    254             : fBuilder(builder)
    255             , fFragmentProcessor(NULL)
    256             , fGLFragmentProcessor(NULL) {}
    257         virtual ~GrGLFragmentProcessorEmitter() {}
    258         void set(const GrFragmentProcessor* fp) {
    259             SkASSERT(NULL == fFragmentProcessor);
    260             fFragmentProcessor = fp;
    261         }
    262         virtual GrGLProcessor* createGLInstance() {
    263             SkASSERT(fFragmentProcessor);
    264             SkASSERT(NULL == fGLFragmentProcessor);
    265             fGLFragmentProcessor =
    266                     fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
    267             return fGLFragmentProcessor;
    268         }
    269         virtual void emit(const GrProcessorKey& key,
    270                           const char* outColor,
    271                           const char* inColor,
    272                           const GrGLProcessor::TransformedCoordsArray& coords,
    273                           const GrGLProcessor::TextureSamplerArray& samplers) {
    274             SkASSERT(fFragmentProcessor);
    275             SkASSERT(fGLFragmentProcessor);
    276             fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
    277                                            coords, samplers);
    278             // this will not leak because it hasa already been used by createGLInstance
    279             fGLFragmentProcessor = NULL;
    280             fFragmentProcessor = NULL;
    281         }
    282     private:
    283         GrGLProgramBuilder*         fBuilder;
    284         const GrFragmentProcessor*  fFragmentProcessor;
    285         GrGLFragmentProcessor*      fGLFragmentProcessor;
    286     };
    287 
    288     GrGLProcessorEmitterInterface*   fEffectEmitter;
    289     CodeStage                        fCodeStage;
    290     SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
    291     SkAutoTUnref<GrGLProgramEffects> fColorEffects;
    292     SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
    293     BuiltinUniformHandles            fUniformHandles;
    294     bool                             fFragOnly;
    295     int                              fTexCoordSetCnt;
    296     GrGLuint                         fProgramID;
    297     GrGLFragmentShaderBuilder        fFS;
    298     SeparableVaryingInfoArray        fSeparableVaryingInfos;
    299 
    300 private:
    301     virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
    302                                       const GrFragmentStage* colorStages[],
    303                                       const GrFragmentStage* coverageStages[],
    304                                       GrGLSLExpr4* inputColor,
    305                                       GrGLSLExpr4* inputCoverage) = 0;
    306     /*
    307      * Subclasses override emitEffect below to emit data and code for a specific single effect
    308      */
    309     virtual void emitEffect(const GrProcessorStage&,
    310                             const GrProcessorKey&,
    311                             const char* outColor,
    312                             const char* inColor,
    313                             int stageIndex) = 0;
    314 
    315     /*
    316      * Because we have fragment only builders, and those builders need to implement a subclass
    317      * of program effects, we have to have base classes overload the program effects here
    318      */
    319     virtual GrGLProgramEffects* getProgramEffects() = 0;
    320 
    321     /**
    322      * Compiles all the shaders, links them into a program, and writes the program id to the output
    323      * struct.
    324      **/
    325     bool finish();
    326 
    327     GrGLFragmentProcessorEmitter            fGrProcessorEmitter;
    328 
    329     const GrGLProgramDesc&                  fDesc;
    330     GrGpuGL*                                fGpu;
    331     UniformInfoArray                        fUniforms;
    332 
    333     friend class GrGLShaderBuilder;
    334     friend class GrGLVertexShaderBuilder;
    335     friend class GrGLFragmentShaderBuilder;
    336     friend class GrGLGeometryShaderBuilder;
    337 };
    338 
    339 #endif
    340