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 addInput(GrGLShaderVar i)31 void addInput(GrGLShaderVar i) { fInputs.push_back(i); } addOutput(GrGLShaderVar 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 */ codeAppendf(const char format[],...)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 codeAppend(const char * str)81 void codeAppend(const char* str) { this->code().append(str); } 82 codePrependf(const char format[],...)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 */ getProgramBuilder()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: ShaderBlock(GrGLShaderBuilder * builder)113 ShaderBlock(GrGLShaderBuilder* builder) : fBuilder(builder) { 114 SkASSERT(builder); 115 fBuilder->codeAppend("{"); 116 } 117 ~ShaderBlock()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 nextStage()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 versionDecl()165 SkString& versionDecl() { return fShaderStrings[kVersionDecl]; } extensions()166 SkString& extensions() { return fShaderStrings[kExtensions]; } precisionQualifier()167 SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; } layoutQualifiers()168 SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; } uniforms()169 SkString& uniforms() { return fShaderStrings[kUniforms]; } inputs()170 SkString& inputs() { return fShaderStrings[kInputs]; } outputs()171 SkString& outputs() { return fShaderStrings[kOutputs]; } functions()172 SkString& functions() { return fShaderStrings[kFunctions]; } main()173 SkString& main() { return fShaderStrings[kMain]; } code()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