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 "gl/GrGLProgramDesc.h"
     12 #include "gl/GrGLProgramEffects.h"
     13 #include "gl/GrGLSL.h"
     14 #include "gl/GrGLProgramDataManager.h"
     15 #include "GrBackendProcessorFactory.h"
     16 #include "GrColor.h"
     17 #include "GrProcessor.h"
     18 #include "SkTypes.h"
     19 
     20 #include <stdarg.h>
     21 
     22 class GrGLContextInfo;
     23 class GrProcessorStage;
     24 class GrGLProgramDesc;
     25 class GrGLProgramBuilder;
     26 class GrGLFullProgramBuilder;
     27 
     28 /**
     29   base class for all shaders builders
     30 */
     31 class GrGLShaderBuilder {
     32 public:
     33     typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
     34     typedef GrGLProcessor::TextureSampler TextureSampler;
     35     GrGLShaderBuilder(GrGLProgramBuilder* program);
     36 
     37     void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
     38     void addOutput(GrGLShaderVar i) { fOutputs.push_back(i); }
     39 
     40     /*
     41      * We put texture lookups in the base class because it is TECHNICALLY possible to do texture
     42      * lookups in any kind of shader.  However, for the time being using these calls on non-fragment
     43      * shaders will result in a shader compilation error as texture sampler uniforms are only
     44      * visible to the fragment shader.  It would not be hard to change this behavior, if someone
     45      * actually wants to do texture lookups in a non-fragment shader
     46      *
     47      * TODO if append texture lookup is used on a non-fragment shader, sampler uniforms should be
     48      * made visible to that shaders
     49      */
     50     /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
     51         Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
     52         order of the result depends on the GrTextureAccess associated with the TextureSampler. */
     53     void appendTextureLookup(SkString* out,
     54                              const TextureSampler&,
     55                              const char* coordName,
     56                              GrSLType coordType = kVec2f_GrSLType) const;
     57 
     58     /** Version of above that appends the result to the fragment shader code instead.*/
     59     void appendTextureLookup(const TextureSampler&,
     60                              const char* coordName,
     61                              GrSLType coordType = kVec2f_GrSLType);
     62 
     63 
     64     /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
     65         always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
     66         float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
     67         called. */
     68     void appendTextureLookupAndModulate(const char* modulation,
     69                                         const TextureSampler&,
     70                                         const char* coordName,
     71                                         GrSLType coordType = kVec2f_GrSLType);
     72 
     73     /** If texture swizzling is available using tex parameters then it is preferred over mangling
     74         the generated shader code. This potentially allows greater reuse of cached shaders. */
     75     static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
     76 
     77     /**
     78     * Called by GrGLProcessors to add code to one of the shaders.
     79     */
     80     void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
     81        va_list args;
     82        va_start(args, format);
     83        fCode.appendVAList(format, args);
     84        va_end(args);
     85     }
     86 
     87     void codeAppend(const char* str) { fCode.append(str); }
     88 
     89     void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
     90        va_list args;
     91        va_start(args, format);
     92        fCode.prependVAList(format, args);
     93        va_end(args);
     94     }
     95 
     96     /**
     97      * Appends a variable declaration to one of the shaders
     98      */
     99     void declAppend(const GrGLShaderVar& var);
    100 
    101     /** Emits a helper function outside of main() in the fragment shader. */
    102     void emitFunction(GrSLType returnType,
    103                       const char* name,
    104                       int argCnt,
    105                       const GrGLShaderVar* args,
    106                       const char* body,
    107                       SkString* outName);
    108 
    109     /*
    110      * Get parent builder for adding uniforms
    111      */
    112     GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
    113 
    114     /**
    115      * Helper for begining and ending a block in the fragment code.
    116      */
    117     class ShaderBlock {
    118     public:
    119         ShaderBlock(GrGLShaderBuilder* builder) : fBuilder(builder) {
    120             SkASSERT(builder);
    121             fBuilder->codeAppend("{");
    122         }
    123 
    124         ~ShaderBlock() {
    125             fBuilder->codeAppend("}");
    126         }
    127     private:
    128         GrGLShaderBuilder* fBuilder;
    129     };
    130 protected:
    131 
    132     /*
    133      * this super low level function is just for use internally to builders
    134      */
    135     void appendTextureLookup(const char* samplerName,
    136                              const char* coordName,
    137                              uint32_t configComponentMask,
    138                              const char* swizzle);
    139 
    140     /*
    141      * A general function which enables an extension in a shader if the feature bit is not present
    142      */
    143     void addFeature(uint32_t featureBit, const char* extensionName);
    144 
    145     typedef GrTAllocator<GrGLShaderVar> VarArray;
    146 
    147     GrGLProgramBuilder* fProgramBuilder;
    148 
    149     SkString fCode;
    150     SkString fFunctions;
    151     SkString fExtensions;
    152 
    153     VarArray fInputs;
    154     VarArray fOutputs;
    155     uint32_t fFeaturesAddedMask;
    156 };
    157 
    158 
    159 /*
    160  * Full Shader builder is the base class for shaders which are only accessible through full program
    161  * builder, ie vertex, geometry, and later TCU / TES.  Using this base class, they can access the
    162  * full program builder functionality through the full program pointer
    163  */
    164 class GrGLFullShaderBuilder : public GrGLShaderBuilder {
    165 public:
    166     GrGLFullShaderBuilder(GrGLFullProgramBuilder* program);
    167 
    168     GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; }
    169 protected:
    170     GrGLFullProgramBuilder* fFullProgramBuilder;
    171 private:
    172     typedef GrGLShaderBuilder INHERITED;
    173 };
    174 #endif
    175