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 GrGLShaderBuilder_DEFINED
      9 #define GrGLShaderBuilder_DEFINED
     10 
     11 #include "SkTArray.h"
     12 #include "gl/GrGLProcessor.h"
     13 #include "gl/GrGLProgramDesc.h"
     14 #include "gl/GrGLProgramDataManager.h"
     15 
     16 #include <stdarg.h>
     17 
     18 class GrGLContextInfo;
     19 class GrGLProgramBuilder;
     20 
     21 /**
     22   base class for all shaders builders
     23 */
     24 class GrGLShaderBuilder {
     25 public:
     26     typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
     27     typedef GrGLProcessor::TextureSampler TextureSampler;
     28 
     29     GrGLShaderBuilder(GrGLProgramBuilder* program);
     30 
     31     void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
     32     void addOutput(GrGLShaderVar i) { fOutputs.push_back(i); }
     33 
     34     /*
     35      * We put texture lookups in the base class because it is TECHNICALLY possible to do texture
     36      * lookups in any kind of shader.  However, for the time being using these calls on non-fragment
     37      * shaders will result in a shader compilation error as texture sampler uniforms are only
     38      * visible to the fragment shader.  It would not be hard to change this behavior, if someone
     39      * actually wants to do texture lookups in a non-fragment shader
     40      *
     41      * TODO if append texture lookup is used on a non-fragment shader, sampler uniforms should be
     42      * made visible to that shaders
     43      */
     44     /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
     45         Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
     46         order of the result depends on the GrTextureAccess associated with the TextureSampler. */
     47     void appendTextureLookup(SkString* out,
     48                              const TextureSampler&,
     49                              const char* coordName,
     50                              GrSLType coordType = kVec2f_GrSLType) const;
     51 
     52     /** Version of above that appends the result to the fragment shader code instead.*/
     53     void appendTextureLookup(const TextureSampler&,
     54                              const char* coordName,
     55                              GrSLType coordType = kVec2f_GrSLType);
     56 
     57 
     58     /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
     59         always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
     60         float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
     61         called. */
     62     void appendTextureLookupAndModulate(const char* modulation,
     63                                         const TextureSampler&,
     64                                         const char* coordName,
     65                                         GrSLType coordType = kVec2f_GrSLType);
     66 
     67     /** If texture swizzling is available using tex parameters then it is preferred over mangling
     68         the generated shader code. This potentially allows greater reuse of cached shaders. */
     69     static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
     70 
     71     /**
     72     * Called by GrGLProcessors to add code to one of the shaders.
     73     */
     74     void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
     75        va_list args;
     76        va_start(args, format);
     77        this->code().appendVAList(format, args);
     78        va_end(args);
     79     }
     80 
     81     void codeAppend(const char* str) { this->code().append(str); }
     82 
     83     void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
     84        va_list args;
     85        va_start(args, format);
     86        this->code().prependVAList(format, args);
     87        va_end(args);
     88     }
     89 
     90     /**
     91      * Appends a variable declaration to one of the shaders
     92      */
     93     void declAppend(const GrGLShaderVar& var);
     94 
     95     /** Emits a helper function outside of main() in the fragment shader. */
     96     void emitFunction(GrSLType returnType,
     97                       const char* name,
     98                       int argCnt,
     99                       const GrGLShaderVar* args,
    100                       const char* body,
    101                       SkString* outName);
    102 
    103     /*
    104      * Get parent builder for adding uniforms
    105      */
    106     GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
    107 
    108     /**
    109      * Helper for begining and ending a block in the shader code.
    110      */
    111     class ShaderBlock {
    112     public:
    113         ShaderBlock(GrGLShaderBuilder* builder) : fBuilder(builder) {
    114             SkASSERT(builder);
    115             fBuilder->codeAppend("{");
    116         }
    117 
    118         ~ShaderBlock() {
    119             fBuilder->codeAppend("}");
    120         }
    121     private:
    122         GrGLShaderBuilder* fBuilder;
    123     };
    124 
    125 protected:
    126     typedef GrTAllocator<GrGLShaderVar> VarArray;
    127     void appendDecls(const VarArray& vars, SkString* out) const;
    128 
    129     /*
    130      * this super low level function is just for use internally to builders
    131      */
    132     void appendTextureLookup(const char* samplerName,
    133                              const char* coordName,
    134                              uint32_t configComponentMask,
    135                              const char* swizzle);
    136 
    137     /*
    138      * A general function which enables an extension in a shader if the feature bit is not present
    139      */
    140     void addFeature(uint32_t featureBit, const char* extensionName);
    141 
    142     enum InterfaceQualifier {
    143         kOut_InterfaceQualifier,
    144         kLastInterfaceQualifier = kOut_InterfaceQualifier
    145     };
    146 
    147     /*
    148      * A low level function to build default layout qualifiers.
    149      *
    150      *   e.g. layout(param1, param2, ...) out;
    151      *
    152      * GLSL allows default layout qualifiers for in, out, and uniform.
    153      */
    154     void addLayoutQualifier(const char* param, InterfaceQualifier);
    155 
    156     void compileAndAppendLayoutQualifiers();
    157 
    158     void nextStage() {
    159         fShaderStrings.push_back();
    160         fCompilerStrings.push_back(this->code().c_str());
    161         fCompilerStringLengths.push_back((int)this->code().size());
    162         fCodeIndex++;
    163     }
    164 
    165     SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
    166     SkString& extensions() { return fShaderStrings[kExtensions]; }
    167     SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
    168     SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
    169     SkString& uniforms() { return fShaderStrings[kUniforms]; }
    170     SkString& inputs() { return fShaderStrings[kInputs]; }
    171     SkString& outputs() { return fShaderStrings[kOutputs]; }
    172     SkString& functions() { return fShaderStrings[kFunctions]; }
    173     SkString& main() { return fShaderStrings[kMain]; }
    174     SkString& code() { return fShaderStrings[fCodeIndex]; }
    175     bool finalize(GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds);
    176 
    177     enum {
    178         kVersionDecl,
    179         kExtensions,
    180         kPrecisionQualifier,
    181         kLayoutQualifiers,
    182         kUniforms,
    183         kInputs,
    184         kOutputs,
    185         kFunctions,
    186         kMain,
    187         kCode,
    188     };
    189 
    190     GrGLProgramBuilder* fProgramBuilder;
    191     SkSTArray<kCode, const char*, true> fCompilerStrings;
    192     SkSTArray<kCode, int, true> fCompilerStringLengths;
    193     SkSTArray<kCode, SkString> fShaderStrings;
    194     SkString fCode;
    195     SkString fFunctions;
    196     SkString fExtensions;
    197 
    198     VarArray fInputs;
    199     VarArray fOutputs;
    200     uint32_t fFeaturesAddedMask;
    201     SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
    202     int fCodeIndex;
    203     bool fFinalized;
    204 
    205     friend class GrGLProgramBuilder;
    206 };
    207 #endif
    208