GrGLShaderBuilder.h revision ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3
14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* 24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Copyright 2012 Google Inc. 34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * 44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Use of this source code is governed by a BSD-style license that can be 54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * found in the LICENSE file. 64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */ 74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef GrGLShaderBuilder_DEFINED 94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define GrGLShaderBuilder_DEFINED 104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "GrAllocator.h" 124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "GrBackendEffectFactory.h" 134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "GrEffect.h" 144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "gl/GrGLSL.h" 154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "gl/GrGLUniformManager.h" 164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdarg.h> 184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass GrGLContextInfo; 204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/** 224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project Contains all the incremental state of a shader as it is being built,as well as helpers to 234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project manipulate that state. 244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project*/ 254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectclass GrGLShaderBuilder { 264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectpublic: 274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project /** 284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Passed to GrGLEffects to add texture reads to their shader code. 294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project */ 304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project class TextureSampler { 314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project public: 324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project TextureSampler() 334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project : fTextureAccess(NULL) 344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {} 354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project TextureSampler(const TextureSampler& other) { *this = other; } 37 38 TextureSampler& operator= (const TextureSampler& other) { 39 GrAssert(NULL == fTextureAccess); 40 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform); 41 42 fTextureAccess = other.fTextureAccess; 43 fSamplerUniform = other.fSamplerUniform; 44 return *this; 45 } 46 47 const GrTextureAccess* textureAccess() const { return fTextureAccess; } 48 49 private: 50 // The idx param is used to ensure multiple samplers within a single effect have unique 51 // uniform names. 52 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) { 53 GrAssert(NULL == fTextureAccess); 54 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform); 55 56 GrAssert(NULL != builder); 57 GrAssert(NULL != access); 58 SkString name; 59 name.printf("Sampler%d_", idx); 60 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 61 kSampler2D_GrSLType, 62 name.c_str()); 63 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform); 64 65 fTextureAccess = access; 66 } 67 68 const GrTextureAccess* fTextureAccess; 69 GrGLUniformManager::UniformHandle fSamplerUniform; 70 71 friend class GrGLShaderBuilder; // to access fSamplerUniform 72 friend class GrGLProgram; // to construct these and access fSamplerUniform. 73 }; 74 75 typedef SkTArray<TextureSampler> TextureSamplerArray; 76 77 enum ShaderType { 78 kVertex_ShaderType = 0x1, 79 kGeometry_ShaderType = 0x2, 80 kFragment_ShaderType = 0x4, 81 }; 82 83 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&); 84 85 /** 86 * Called by GrGLEffects to add code to one of the shaders. 87 */ 88 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 89 va_list args; 90 va_start(args, format); 91 this->codeAppendf(kVertex_ShaderType, format, args); 92 va_end(args); 93 } 94 95 void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 96 va_list args; 97 va_start(args, format); 98 this->codeAppendf(kGeometry_ShaderType, format, args); 99 va_end(args); 100 } 101 102 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { 103 va_list args; 104 va_start(args, format); 105 this->codeAppendf(kFragment_ShaderType, format, args); 106 va_end(args); 107 } 108 109 void vsCodeAppend(const char* str) { this->codeAppend(kVertex_ShaderType, str); } 110 void gsCodeAppend(const char* str) { this->codeAppend(kGeometry_ShaderType, str); } 111 void fsCodeAppend(const char* str) { this->codeAppend(kFragment_ShaderType, str); } 112 113 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or 114 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle 115 order of the result depends on the GrTextureAccess associated with the TextureSampler. */ 116 void appendTextureLookup(SkString* out, 117 const TextureSampler&, 118 const char* coordName, 119 GrSLType coordType = kVec2f_GrSLType) const; 120 121 /** Version of above that appends the result to the shader code rather than an SkString. 122 Currently the shader type must be kFragment */ 123 void appendTextureLookup(ShaderType, 124 const TextureSampler&, 125 const char* coordName, 126 GrSLType coordType = kVec2f_GrSLType); 127 128 129 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is 130 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or 131 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were 132 called. */ 133 void appendTextureLookupAndModulate(ShaderType, 134 const char* modulation, 135 const TextureSampler&, 136 const char* coordName, 137 GrSLType coordType = kVec2f_GrSLType); 138 139 /** Emits a helper function outside of main(). Currently ShaderType must be 140 kFragment_ShaderType. */ 141 void emitFunction(ShaderType shader, 142 GrSLType returnType, 143 const char* name, 144 int argCnt, 145 const GrGLShaderVar* args, 146 const char* body, 147 SkString* outName); 148 149 /** Generates a EffectKey for the shader code based on the texture access parameters and the 150 capabilities of the GL context. This is useful for keying the shader programs that may 151 have multiple representations, based on the type/format of textures used. */ 152 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&, 153 const GrGLCaps&); 154 155 /** If texture swizzling is available using tex parameters then it is preferred over mangling 156 the generated shader code. This potentially allows greater reuse of cached shaders. */ 157 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); 158 159 /** Add a uniform variable to the current program, that has visibility in one or more shaders. 160 visibility is a bitfield of ShaderType values indicating from which shaders the uniform 161 should be accessible. At least one bit must be set. Geometry shader uniforms are not 162 supported at this time. The actual uniform name will be mangled. If outName is not NULL then 163 it will refer to the final uniform name after return. Use the addUniformArray variant to add 164 an array of uniforms. 165 */ 166 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility, 167 GrSLType type, 168 const char* name, 169 const char** outName = NULL) { 170 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName); 171 } 172 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility, 173 GrSLType type, 174 const char* name, 175 int arrayCount, 176 const char** outName = NULL); 177 178 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const; 179 180 /** 181 * Shortcut for getUniformVariable(u).c_str() 182 */ 183 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const { 184 return this->getUniformVariable(u).c_str(); 185 } 186 187 /** Add a vertex attribute to the current program that is passed in from the vertex data. 188 Returns false if the attribute was already there, true otherwise. */ 189 bool addAttribute(GrSLType type, const char* name); 190 191 /** Add a varying variable to the current program to pass values between vertex and fragment 192 shaders. If the last two parameters are non-NULL, they are filled in with the name 193 generated. */ 194 void addVarying(GrSLType type, 195 const char* name, 196 const char** vsOutName = NULL, 197 const char** fsInName = NULL); 198 199 /** Returns a variable name that represents the position of the fragment in the FS. The position 200 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ 201 const char* fragmentPosition(); 202 203 /** Returns a vertex attribute that represents the vertex position in the VS. This is the 204 pre-matrix position and is commonly used by effects to compute texture coords via a matrix. 205 */ 206 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } 207 208 /** 209 * Interfaces used by GrGLProgram. 210 * TODO: Hide these from the GrEffects using friend or splitting this into two related classes. 211 * Also, GrGLProgram's shader string construction should be moved to this class. 212 */ 213 214 /** Called after building is complete to get the final shader string. */ 215 void getShader(ShaderType, SkString*) const; 216 217 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; } 218 void setNonStage() { fCurrentStageIdx = kNonStageIdx; } 219 // TODO: move remainder of shader code generation to this class and call this privately 220 // Handles of sampler uniforms generated for the effect are appended to samplerHandles. 221 GrGLEffect* createAndEmitGLEffect( 222 const GrEffectStage& stage, 223 GrBackendEffectFactory::EffectKey key, 224 const char* fsInColor, // NULL means no incoming color 225 const char* fsOutColor, 226 const char* vsInCoord, 227 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles); 228 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; } 229 230 struct AttributePair { 231 void set(int index, const SkString& name) { 232 fIndex = index; fName = name; 233 } 234 int fIndex; 235 SkString fName; 236 }; 237 const SkSTArray<10, AttributePair, true>& getEffectAttributes() const { 238 return fEffectAttributes; 239 } 240 const SkString* getEffectAttributeName(int attributeIndex) const; 241 242 // TODO: Make this do all the compiling, linking, etc. 243 void finished(GrGLuint programID); 244 245 const GrGLContextInfo& ctxInfo() const { return fCtxInfo; } 246 247private: 248 void codeAppendf(ShaderType type, const char format[], va_list args); 249 void codeAppend(ShaderType type, const char* str); 250 251 typedef GrTAllocator<GrGLShaderVar> VarArray; 252 253 void appendDecls(const VarArray&, SkString*) const; 254 void appendUniformDecls(ShaderType, SkString*) const; 255 256 typedef GrGLUniformManager::BuilderUniform BuilderUniform; 257 GrGLUniformManager::BuilderUniformArray fUniforms; 258 259 // TODO: Everything below here private. 260public: 261 262 SkString fHeader; // VS+FS, GLSL version, etc 263 VarArray fVSAttrs; 264 VarArray fVSOutputs; 265 VarArray fGSInputs; 266 VarArray fGSOutputs; 267 VarArray fFSInputs; 268 SkString fGSHeader; // layout qualifiers specific to GS 269 VarArray fFSOutputs; 270 bool fUsesGS; 271 272private: 273 enum { 274 kNonStageIdx = -1, 275 }; 276 277 const GrGLContextInfo& fCtxInfo; 278 GrGLUniformManager& fUniformManager; 279 int fCurrentStageIdx; 280 SkString fFSFunctions; 281 SkString fFSHeader; 282 283 SkString fFSCode; 284 SkString fVSCode; 285 SkString fGSCode; 286 287 bool fSetupFragPosition; 288 GrGLUniformManager::UniformHandle fRTHeightUniform; 289 290 SkSTArray<10, AttributePair, true> fEffectAttributes; 291 292 GrGLShaderVar* fPositionVar; 293}; 294 295#endif 296