blob: c5ac07807198cc02c364b279b56e2576d9205e68 [file] [log] [blame]
tomhudson@google.comf9ad8862012-05-11 20:38:48 +00001/*
2 * Copyright 2012 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 "GrAllocator.h"
twiz@google.coma5e65ec2012-08-02 15:15:16 +000012#include "GrCustomStage.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000013#include "gl/GrGLShaderVar.h"
14#include "gl/GrGLSL.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000015#include "gl/GrGLUniformManager.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000016
bsalomon@google.comad5e9372012-07-11 18:11:27 +000017class GrGLContextInfo;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000018
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000019/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000020 Contains all the incremental state of a shader as it is being built,as well as helpers to
21 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000022*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000023class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000024public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000025 /**
26 * Used by GrGLProgramStages to add texture reads to their shader code.
27 */
28 class TextureSampler {
29 public:
30 TextureSampler()
31 : fTextureAccess(NULL)
32 , fTexture(NULL)
33 , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {}
34
35 TextureSampler(const TextureSampler& other) { *this = other; }
36
37 TextureSampler& operator= (const TextureSampler& other) {
38 GrAssert(NULL == fTextureAccess);
39 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
40
41 fTexture = other.fTexture;
42 fTextureAccess = other.fTextureAccess;
43 fSamplerUniform = other.fSamplerUniform;
44 return *this;
45 }
46
47 const GrTextureAccess* textureAccess() const { return fTextureAccess; }
48
49 private:
50 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access) {
51 GrAssert(NULL == fTextureAccess);
52 GrAssert(NULL == fTexture);
53 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
54
55 GrAssert(NULL != builder);
56 GrAssert(NULL != access);
57 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
58 kSampler2D_GrSLType,
59 "Sampler");
60 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
61
62 fTextureAccess = access;
63 fTexture = access->getTexture();
64 }
65
66 // TODO: Remove once GrTextureAccess is required.
67 void init(GrGLShaderBuilder* builder, const GrTexture* texture) {
68 GrAssert(NULL == fTextureAccess);
69 GrAssert(NULL == fTexture);
70 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
71
72 GrAssert(NULL != builder);
73 GrAssert(NULL != texture);
74 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
75 kSampler2D_GrSLType,
76 "Sampler");
77 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
78
79 fTexture = texture;
80 }
81
82 const GrTextureAccess* fTextureAccess;
83 const GrTexture* fTexture; // TODO: remove once tex access cannot be NULL
84 GrGLUniformManager::UniformHandle fSamplerUniform;
85
86 friend class GrGLShaderBuilder; // to access fSamplerUniform
87 friend class GrGLProgram; // to construct these and access fSamplerUniform.
88 };
89
90 typedef SkTArray<TextureSampler> TextureSamplerArray;
91
bsalomon@google.comeb715c82012-07-11 15:03:31 +000092 enum ShaderType {
93 kVertex_ShaderType = 0x1,
94 kGeometry_ShaderType = 0x2,
95 kFragment_ShaderType = 0x4,
96 };
97
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000098 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000099
tomhudson@google.com52598142012-05-24 17:44:30 +0000100 void computeSwizzle(uint32_t configFlags);
tomhudson@google.com52598142012-05-24 17:44:30 +0000101
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000102 /** Determines whether we should use texture2D() or texture2Dproj(), and if an explicit divide
103 is required for the sample coordinates, creates the new variable and emits the code to
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000104 initialize it. This should only be called by GrGLProgram.*/
105 void setupTextureAccess(const char* varyingFSName, GrSLType varyingType);
tomhudson@google.com52598142012-05-24 17:44:30 +0000106
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000107 /** appends a texture sample with projection if necessary; if coordName is not
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000108 specified, uses fSampleCoords. coordType must either be Vec2f or Vec3f. The latter is
109 interpreted as projective texture coords. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000110 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000111 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000112 const char* coordName = NULL,
113 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000114
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000115 /** appends a texture lookup, with swizzle as necessary. If coordName is NULL then it as if
116 defaultTexCoordsName() was passed. coordType must be either kVec2f or kVec3f. If modulateVar
117 is not NULL or "" then the texture lookup will be modulated by it. modulation must refer to
118 be expression that evaluates to a float or vec4. */
119 void appendTextureLookupAndModulate(SkString* out,
120 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000121 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000122 const char* coordName = NULL,
123 GrSLType varyingType = kVec2f_GrSLType) const;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000124
125 /** Gets the name of the default texture coords which are always kVec2f */
126 const char* defaultTexCoordsName() const { return fDefaultTexCoordsName.c_str(); }
127
128 /* Returns true if the texture matrix from which the default texture coords are computed has
129 perspective. */
130 bool defaultTextureMatrixIsPerspective() const {
131 return fTexCoordVaryingType == kVec3f_GrSLType;
132 }
tomhudson@google.com52598142012-05-24 17:44:30 +0000133
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000134 /** Emits a texture lookup to the shader code with the form:
135 texture2D{Proj}(samplerName, coordName).swizzle
136 The routine selects the type of texturing based on samplerMode.
137 The generated swizzle state is built based on the format of the texture and the requested
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000138 swizzle access pattern. coordType must either be Vec2f or Vec3f. The latter is interpreted
139 as projective texture coords.*/
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000140 void emitCustomTextureLookup(const TextureSampler&,
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000141 const char* coordName,
142 GrSLType coordType = kVec2f_GrSLType);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000143
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000144 /** Emits a helper function outside of main(). Currently ShaderType must be
145 kFragment_ShaderType. */
146 void emitFunction(ShaderType shader,
147 GrSLType returnType,
148 const char* name,
149 int argCnt,
150 const GrGLShaderVar* args,
151 const char* body,
152 SkString* outName);
153
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000154 /** Generates a StageKey for the shader code based on the texture access parameters and the
155 capabilities of the GL context. This is useful for keying the shader programs that may
156 have multiple representations, based on the type/format of textures used. */
157 static GrCustomStage::StageKey KeyForTextureAccess(const GrTextureAccess& access,
158 const GrGLCaps& caps);
159
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000160 /** Add a uniform variable to the current program, that has visibilty in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000161 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
162 should be accessible. At least one bit must be set. Geometry shader uniforms are not
163 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
164 it will refer to the final uniform name after return. Use the addUniformArray variant to add
165 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000166 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000167 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
168 GrSLType type,
169 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000170 const char** outName = NULL) {
171 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
172 }
173 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
174 GrSLType type,
175 const char* name,
176 int arrayCount,
177 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000178
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000179 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000180
181 /**
182 * Shorcut for getUniformVariable(u).c_str()
183 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000184 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000185 return this->getUniformVariable(u).c_str();
186 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000187
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000188 /** Add a varying variable to the current program to pass values between vertex and fragment
189 shaders. If the last two parameters are non-NULL, they are filled in with the name
190 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000191 void addVarying(GrSLType type,
192 const char* name,
193 const char** vsOutName = NULL,
194 const char** fsInName = NULL);
195
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000196 /** Called after building is complete to get the final shader string. */
197 void getShader(ShaderType, SkString*) const;
198
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000199 /**
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000200 * TODO: Make this do all the compiling, linking, etc. Hide from the custom stages
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000201 */
202 void finished(GrGLuint programID);
203
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000204 /**
205 * Sets the current stage (used to make variable names unique).
206 * TODO: Hide from the custom stages
207 */
208 void setCurrentStage(int stage) { fCurrentStage = stage; }
209 void setNonStage() { fCurrentStage = kNonStageIdx; }
210
bsalomon@google.com032b2212012-07-16 13:36:18 +0000211private:
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000212
bsalomon@google.com032b2212012-07-16 13:36:18 +0000213 typedef GrTAllocator<GrGLShaderVar> VarArray;
214
bsalomon@google.com032b2212012-07-16 13:36:18 +0000215 void appendDecls(const VarArray&, SkString*) const;
216 void appendUniformDecls(ShaderType, SkString*) const;
217
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000218 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
219 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000220
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000221 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000222public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000223
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000224 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000225 VarArray fVSAttrs;
226 VarArray fVSOutputs;
227 VarArray fGSInputs;
228 VarArray fGSOutputs;
229 VarArray fFSInputs;
230 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000231 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000232 SkString fVSCode;
233 SkString fGSCode;
234 SkString fFSCode;
235 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000236
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000237 /// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000238 //@{
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000239
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000240 SkString fSwizzle;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000241
242 //@}
tomhudson@google.com9c639a42012-05-14 19:58:06 +0000243
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000244private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000245 enum {
246 kNonStageIdx = -1,
247 };
248
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000249 const GrGLContextInfo& fContext;
250 GrGLUniformManager& fUniformManager;
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000251 int fCurrentStage;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000252 SkString fFSFunctions;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000253
254 /// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
255 //@{
256 GrSLType fTexCoordVaryingType; // the type, either Vec2f or Vec3f, of the coords passed
257 // as a varying from the VS to the FS.
258 SkString fDefaultTexCoordsName; // the name of the default 2D coords value.
259 //@}
260
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000261};
262
263#endif