blob: 9d64143802be318bd5371ea5084d6b595da8c4d1 [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"
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000012#include "GrBackendEffectFactory.h"
bsalomon@google.coma469c282012-10-24 18:28:34 +000013#include "GrEffect.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000014#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.comf910d3b2013-03-07 17:06:57 +000017#include <stdarg.h>
18
bsalomon@google.comad5e9372012-07-11 18:11:27 +000019class GrGLContextInfo;
bsalomon@google.comc7818882013-03-20 19:19:53 +000020class GrEffectStage;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000021
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000022/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000023 Contains all the incremental state of a shader as it is being built,as well as helpers to
24 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000025*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000026class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000027public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000028 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +000029 * Passed to GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000030 */
31 class TextureSampler {
32 public:
33 TextureSampler()
34 : fTextureAccess(NULL)
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000035 , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {}
36
37 TextureSampler(const TextureSampler& other) { *this = other; }
38
39 TextureSampler& operator= (const TextureSampler& other) {
40 GrAssert(NULL == fTextureAccess);
41 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
42
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000043 fTextureAccess = other.fTextureAccess;
44 fSamplerUniform = other.fSamplerUniform;
45 return *this;
46 }
47
48 const GrTextureAccess* textureAccess() const { return fTextureAccess; }
49
50 private:
bsalomon@google.com34cccde2013-01-04 18:34:30 +000051 // The idx param is used to ensure multiple samplers within a single effect have unique
52 // uniform names.
53 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) {
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000054 GrAssert(NULL == fTextureAccess);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000055 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
56
57 GrAssert(NULL != builder);
58 GrAssert(NULL != access);
bsalomon@google.com34cccde2013-01-04 18:34:30 +000059 SkString name;
60 name.printf("Sampler%d_", idx);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000061 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
62 kSampler2D_GrSLType,
bsalomon@google.com34cccde2013-01-04 18:34:30 +000063 name.c_str());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000064 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
65
66 fTextureAccess = access;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000067 }
68
69 const GrTextureAccess* fTextureAccess;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000070 GrGLUniformManager::UniformHandle fSamplerUniform;
71
72 friend class GrGLShaderBuilder; // to access fSamplerUniform
73 friend class GrGLProgram; // to construct these and access fSamplerUniform.
74 };
75
76 typedef SkTArray<TextureSampler> TextureSamplerArray;
77
bsalomon@google.comeb715c82012-07-11 15:03:31 +000078 enum ShaderType {
79 kVertex_ShaderType = 0x1,
80 kGeometry_ShaderType = 0x2,
81 kFragment_ShaderType = 0x4,
82 };
83
bsalomon@google.comc7818882013-03-20 19:19:53 +000084 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, bool explicitLocalCoords);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000085
bsalomon@google.comf910d3b2013-03-07 17:06:57 +000086 /**
87 * Called by GrGLEffects to add code to one of the shaders.
88 */
89 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
90 va_list args;
91 va_start(args, format);
92 this->codeAppendf(kVertex_ShaderType, format, args);
93 va_end(args);
94 }
95
96 void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
97 va_list args;
98 va_start(args, format);
99 this->codeAppendf(kGeometry_ShaderType, format, args);
100 va_end(args);
101 }
102
103 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
104 va_list args;
105 va_start(args, format);
106 this->codeAppendf(kFragment_ShaderType, format, args);
107 va_end(args);
108 }
109
110 void vsCodeAppend(const char* str) { this->codeAppend(kVertex_ShaderType, str); }
111 void gsCodeAppend(const char* str) { this->codeAppend(kGeometry_ShaderType, str); }
112 void fsCodeAppend(const char* str) { this->codeAppend(kFragment_ShaderType, str); }
113
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000114 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
115 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
116 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000117 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000118 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000119 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000120 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000121
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000122 /** Version of above that appends the result to the shader code rather than an SkString.
123 Currently the shader type must be kFragment */
124 void appendTextureLookup(ShaderType,
125 const TextureSampler&,
126 const char* coordName,
127 GrSLType coordType = kVec2f_GrSLType);
128
129
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000130 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
131 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
132 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
133 called. */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000134 void appendTextureLookupAndModulate(ShaderType,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000135 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000136 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000137 const char* coordName,
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000138 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000139
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000140 /** Emits a helper function outside of main(). Currently ShaderType must be
141 kFragment_ShaderType. */
142 void emitFunction(ShaderType shader,
143 GrSLType returnType,
144 const char* name,
145 int argCnt,
146 const GrGLShaderVar* args,
147 const char* body,
148 SkString* outName);
149
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000150 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000151 capabilities of the GL context. This is useful for keying the shader programs that may
152 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000153 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
154 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000155
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000156 /** If texture swizzling is available using tex parameters then it is preferred over mangling
157 the generated shader code. This potentially allows greater reuse of cached shaders. */
158 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
159
bsalomon@google.com706f6682012-10-23 14:53:55 +0000160 /** Add a uniform variable to the current program, that has visibility 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 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000182 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000183 */
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
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000188 /** Add a vertex attribute to the current program that is passed in from the vertex data.
189 Returns false if the attribute was already there, true otherwise. */
190 bool addAttribute(GrSLType type, const char* name);
191
192 /** Add a varying variable to the current program to pass values between vertex and fragment
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000193 shaders. If the last two parameters are non-NULL, they are filled in with the name
194 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000195 void addVarying(GrSLType type,
196 const char* name,
197 const char** vsOutName = NULL,
198 const char** fsInName = NULL);
199
bsalomon@google.com706f6682012-10-23 14:53:55 +0000200 /** Returns a variable name that represents the position of the fragment in the FS. The position
201 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
202 const char* fragmentPosition();
203
bsalomon@google.com17504f52012-10-30 12:34:25 +0000204 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
205 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
206 */
207 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
208
bsalomon@google.comc7818882013-03-20 19:19:53 +0000209 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
210 as positionAttribute() or it may not be. It depends upon whether the rendering code
211 specified explicit local coords or not in the GrDrawState. */
212 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
213
214 /**
215 * Are explicit local coordinates provided as input to the vertex shader.
216 */
217 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
218
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000219 /**
220 * Interfaces used by GrGLProgram.
221 * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
222 * Also, GrGLProgram's shader string construction should be moved to this class.
223 */
224
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000225 /** Called after building is complete to get the final shader string. */
226 void getShader(ShaderType, SkString*) const;
227
bsalomon@google.com08283af2012-10-26 13:01:20 +0000228 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
229 void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000230 // TODO: move remainder of shader code generation to this class and call this privately
231 // Handles of sampler uniforms generated for the effect are appended to samplerHandles.
232 GrGLEffect* createAndEmitGLEffect(
233 const GrEffectStage& stage,
234 GrBackendEffectFactory::EffectKey key,
235 const char* fsInColor, // NULL means no incoming color
236 const char* fsOutColor,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000237 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000238 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000239
240 struct AttributePair {
241 void set(int index, const SkString& name) {
242 fIndex = index; fName = name;
243 }
244 int fIndex;
245 SkString fName;
246 };
247 const SkSTArray<10, AttributePair, true>& getEffectAttributes() const {
248 return fEffectAttributes;
249 }
250 const SkString* getEffectAttributeName(int attributeIndex) const;
251
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000252 // TODO: Make this do all the compiling, linking, etc.
253 void finished(GrGLuint programID);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000254
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000255 const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
256
bsalomon@google.com032b2212012-07-16 13:36:18 +0000257private:
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000258 void codeAppendf(ShaderType type, const char format[], va_list args);
259 void codeAppend(ShaderType type, const char* str);
260
bsalomon@google.com032b2212012-07-16 13:36:18 +0000261 typedef GrTAllocator<GrGLShaderVar> VarArray;
262
bsalomon@google.com032b2212012-07-16 13:36:18 +0000263 void appendDecls(const VarArray&, SkString*) const;
264 void appendUniformDecls(ShaderType, SkString*) const;
265
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000266 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
267 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000268
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000269 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000270public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000271
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000272 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000273 VarArray fVSAttrs;
274 VarArray fVSOutputs;
275 VarArray fGSInputs;
276 VarArray fGSOutputs;
277 VarArray fFSInputs;
278 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000279 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000280 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000281
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000282private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000283 enum {
284 kNonStageIdx = -1,
285 };
286
robertphillips@google.com6177e692013-02-28 20:16:25 +0000287 const GrGLContextInfo& fCtxInfo;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000288 GrGLUniformManager& fUniformManager;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000289 int fCurrentStageIdx;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000290 SkString fFSFunctions;
291 SkString fFSHeader;
292
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000293 SkString fFSCode;
294 SkString fVSCode;
295 SkString fGSCode;
296
bsalomon@google.com706f6682012-10-23 14:53:55 +0000297 bool fSetupFragPosition;
298 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000299
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000300 SkSTArray<10, AttributePair, true> fEffectAttributes;
301
bsalomon@google.com17504f52012-10-30 12:34:25 +0000302 GrGLShaderVar* fPositionVar;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000303 GrGLShaderVar* fLocalCoordsVar;
304
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000305};
306
307#endif