blob: 4e39f91e35c792c9cd6cacf457f425377c9fc4aa [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.comb8eb2e82013-03-28 13:46:42 +000013#include "GrColor.h"
bsalomon@google.coma469c282012-10-24 18:28:34 +000014#include "GrEffect.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000015#include "gl/GrGLSL.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000016#include "gl/GrGLUniformManager.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000017
bsalomon@google.comf910d3b2013-03-07 17:06:57 +000018#include <stdarg.h>
19
bsalomon@google.comad5e9372012-07-11 18:11:27 +000020class GrGLContextInfo;
bsalomon@google.comc7818882013-03-20 19:19:53 +000021class GrEffectStage;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000022class GrGLProgramDesc;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000023
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000024/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000025 Contains all the incremental state of a shader as it is being built,as well as helpers to
26 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000027*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000028class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000029public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000030 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +000031 * Passed to GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000032 */
33 class TextureSampler {
34 public:
35 TextureSampler()
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000036 : fConfigComponentMask(0)
37 , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {
38 // we will memcpy the first 4 bytes from passed in swizzle. This ensures the string is
39 // terminated.
40 fSwizzle[4] = '\0';
41 }
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000042
43 TextureSampler(const TextureSampler& other) { *this = other; }
44
45 TextureSampler& operator= (const TextureSampler& other) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000046 GrAssert(0 == fConfigComponentMask);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000047 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
48
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000049 fConfigComponentMask = other.fConfigComponentMask;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000050 fSamplerUniform = other.fSamplerUniform;
51 return *this;
52 }
53
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000054 // bitfield of GrColorComponentFlags present in the texture's config.
55 uint32_t configComponentMask() const { return fConfigComponentMask; }
56
57 const char* swizzle() const { return fSwizzle; }
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000058
bsalomon@google.com26e18b52013-03-29 19:22:36 +000059 bool isInitialized() const { return 0 != fConfigComponentMask; }
60
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000061 private:
bsalomon@google.com34cccde2013-01-04 18:34:30 +000062 // The idx param is used to ensure multiple samplers within a single effect have unique
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000063 // uniform names. swizzle is a four char max string made up of chars 'r', 'g', 'b', and 'a'.
64 void init(GrGLShaderBuilder* builder,
65 uint32_t configComponentMask,
66 const char* swizzle,
67 int idx) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +000068 GrAssert(!this->isInitialized());
69 GrAssert(0 != configComponentMask);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000070 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
71
72 GrAssert(NULL != builder);
bsalomon@google.com34cccde2013-01-04 18:34:30 +000073 SkString name;
74 name.printf("Sampler%d_", idx);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000075 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
76 kSampler2D_GrSLType,
bsalomon@google.com34cccde2013-01-04 18:34:30 +000077 name.c_str());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000078 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
79
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000080 fConfigComponentMask = configComponentMask;
81 memcpy(fSwizzle, swizzle, 4);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000082 }
83
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000084 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) {
85 GrAssert(NULL != access);
86 this->init(builder,
87 GrPixelConfigComponentMask(access->getTexture()->config()),
88 access->getSwizzle(),
89 idx);
90 }
91
92 uint32_t fConfigComponentMask;
93 char fSwizzle[5];
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000094 GrGLUniformManager::UniformHandle fSamplerUniform;
95
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000096 friend class GrGLShaderBuilder; // to call init().
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000097 };
98
99 typedef SkTArray<TextureSampler> TextureSamplerArray;
100
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000101 enum ShaderType {
102 kVertex_ShaderType = 0x1,
103 kGeometry_ShaderType = 0x2,
104 kFragment_ShaderType = 0x4,
105 };
106
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000107 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000108
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000109 /**
110 * Called by GrGLEffects to add code to one of the shaders.
111 */
112 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
113 va_list args;
114 va_start(args, format);
115 this->codeAppendf(kVertex_ShaderType, format, args);
116 va_end(args);
117 }
118
119 void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
120 va_list args;
121 va_start(args, format);
122 this->codeAppendf(kGeometry_ShaderType, format, args);
123 va_end(args);
124 }
125
126 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
127 va_list args;
128 va_start(args, format);
129 this->codeAppendf(kFragment_ShaderType, format, args);
130 va_end(args);
131 }
132
133 void vsCodeAppend(const char* str) { this->codeAppend(kVertex_ShaderType, str); }
134 void gsCodeAppend(const char* str) { this->codeAppend(kGeometry_ShaderType, str); }
135 void fsCodeAppend(const char* str) { this->codeAppend(kFragment_ShaderType, str); }
136
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000137 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
138 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
139 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000140 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000141 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000142 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000143 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000144
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000145 /** Version of above that appends the result to the shader code rather than an SkString.
146 Currently the shader type must be kFragment */
147 void appendTextureLookup(ShaderType,
148 const TextureSampler&,
149 const char* coordName,
150 GrSLType coordType = kVec2f_GrSLType);
151
152
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000153 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
154 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
155 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
156 called. */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000157 void appendTextureLookupAndModulate(ShaderType,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000158 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000159 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000160 const char* coordName,
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000161 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000162
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000163 /** Emits a helper function outside of main(). Currently ShaderType must be
164 kFragment_ShaderType. */
165 void emitFunction(ShaderType shader,
166 GrSLType returnType,
167 const char* name,
168 int argCnt,
169 const GrGLShaderVar* args,
170 const char* body,
171 SkString* outName);
172
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000173 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000174 capabilities of the GL context. This is useful for keying the shader programs that may
175 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000176 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
177 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000178
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000179 typedef uint8_t DstReadKey;
180
181 /** Returns a key for adding code to read the copy-of-dst color in service of effects that
182 require reading the dst. It must not return 0 because 0 indicates that there is no dst
183 copy read at all. */
184 static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
185
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000186 /** If texture swizzling is available using tex parameters then it is preferred over mangling
187 the generated shader code. This potentially allows greater reuse of cached shaders. */
188 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
189
bsalomon@google.com706f6682012-10-23 14:53:55 +0000190 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000191 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
192 should be accessible. At least one bit must be set. Geometry shader uniforms are not
193 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
194 it will refer to the final uniform name after return. Use the addUniformArray variant to add
195 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000196 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000197 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
198 GrSLType type,
199 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000200 const char** outName = NULL) {
201 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
202 }
203 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
204 GrSLType type,
205 const char* name,
206 int arrayCount,
207 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000208
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000209 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000210
211 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000212 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000213 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000214 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000215 return this->getUniformVariable(u).c_str();
216 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000217
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000218 /** Add a vertex attribute to the current program that is passed in from the vertex data.
219 Returns false if the attribute was already there, true otherwise. */
220 bool addAttribute(GrSLType type, const char* name);
221
222 /** Add a varying variable to the current program to pass values between vertex and fragment
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000223 shaders. If the last two parameters are non-NULL, they are filled in with the name
224 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000225 void addVarying(GrSLType type,
226 const char* name,
227 const char** vsOutName = NULL,
228 const char** fsInName = NULL);
229
bsalomon@google.com706f6682012-10-23 14:53:55 +0000230 /** Returns a variable name that represents the position of the fragment in the FS. The position
231 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
232 const char* fragmentPosition();
233
bsalomon@google.com17504f52012-10-30 12:34:25 +0000234 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
235 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
236 */
237 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
238
bsalomon@google.comc7818882013-03-20 19:19:53 +0000239 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
240 as positionAttribute() or it may not be. It depends upon whether the rendering code
241 specified explicit local coords or not in the GrDrawState. */
242 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
243
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000244 /** Returns the color of the destination pixel. This may be NULL if no effect advertised
245 that it will read the destination. */
246 const char* dstColor() const;
247
bsalomon@google.comc7818882013-03-20 19:19:53 +0000248 /**
249 * Are explicit local coordinates provided as input to the vertex shader.
250 */
251 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
252
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000253 /**
254 * Interfaces used by GrGLProgram.
255 * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
256 * Also, GrGLProgram's shader string construction should be moved to this class.
257 */
258
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000259 /** Called after building is complete to get the final shader string. */
260 void getShader(ShaderType, SkString*) const;
261
bsalomon@google.com08283af2012-10-26 13:01:20 +0000262 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
263 void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000264 // TODO: move remainder of shader code generation to this class and call this privately
265 // Handles of sampler uniforms generated for the effect are appended to samplerHandles.
266 GrGLEffect* createAndEmitGLEffect(
267 const GrEffectStage& stage,
268 GrBackendEffectFactory::EffectKey key,
269 const char* fsInColor, // NULL means no incoming color
270 const char* fsOutColor,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000271 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000272
bsalomon@google.com706f6682012-10-23 14:53:55 +0000273 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000274 GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
275 return fDstCopyTopLeftUniform;
276 }
277 GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
278 return fDstCopyScaleUniform;
279 }
280 GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
281 return fDstCopySampler.fSamplerUniform;
282 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000283
284 struct AttributePair {
285 void set(int index, const SkString& name) {
286 fIndex = index; fName = name;
287 }
288 int fIndex;
289 SkString fName;
290 };
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000291 const SkTArray<AttributePair, true>& getEffectAttributes() const {
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000292 return fEffectAttributes;
293 }
294 const SkString* getEffectAttributeName(int attributeIndex) const;
295
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000296 // TODO: Make this do all the compiling, linking, etc.
297 void finished(GrGLuint programID);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000298
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000299 const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
300
bsalomon@google.com032b2212012-07-16 13:36:18 +0000301private:
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000302 void codeAppendf(ShaderType type, const char format[], va_list args);
303 void codeAppend(ShaderType type, const char* str);
304
bsalomon@google.com032b2212012-07-16 13:36:18 +0000305 typedef GrTAllocator<GrGLShaderVar> VarArray;
306
bsalomon@google.com032b2212012-07-16 13:36:18 +0000307 void appendDecls(const VarArray&, SkString*) const;
308 void appendUniformDecls(ShaderType, SkString*) const;
309
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000310 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
311 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000312
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000313 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000314public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000315
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000316 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000317 VarArray fVSAttrs;
318 VarArray fVSOutputs;
319 VarArray fGSInputs;
320 VarArray fGSOutputs;
321 VarArray fFSInputs;
322 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000323 VarArray fFSOutputs;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000324
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000325private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000326 enum {
327 kNonStageIdx = -1,
328 };
329
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000330 // Interpretation of DstReadKey when generating code
331 enum {
332 kNoDstRead_DstReadKey = 0,
333 kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
334 kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
335 kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
336 };
337
robertphillips@google.com6177e692013-02-28 20:16:25 +0000338 const GrGLContextInfo& fCtxInfo;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000339 GrGLUniformManager& fUniformManager;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000340 int fCurrentStageIdx;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000341 SkString fFSFunctions;
342 SkString fFSHeader;
343
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000344 bool fUsesGS;
345
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000346 SkString fFSCode;
347 SkString fVSCode;
348 SkString fGSCode;
349
bsalomon@google.com706f6682012-10-23 14:53:55 +0000350 bool fSetupFragPosition;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000351 TextureSampler fDstCopySampler;
352
bsalomon@google.com706f6682012-10-23 14:53:55 +0000353 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000354 GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
355 GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000356
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000357 SkSTArray<10, AttributePair, true> fEffectAttributes;
358
bsalomon@google.com17504f52012-10-30 12:34:25 +0000359 GrGLShaderVar* fPositionVar;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000360 GrGLShaderVar* fLocalCoordsVar;
361
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000362};
363
364#endif