blob: ce1e6d129044471bc791bade0e8f6b067c2d4792 [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.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 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +000026 * Passed to GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000027 */
28 class TextureSampler {
29 public:
30 TextureSampler()
31 : fTextureAccess(NULL)
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000032 , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {}
33
34 TextureSampler(const TextureSampler& other) { *this = other; }
35
36 TextureSampler& operator= (const TextureSampler& other) {
37 GrAssert(NULL == fTextureAccess);
38 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
39
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000040 fTextureAccess = other.fTextureAccess;
41 fSamplerUniform = other.fSamplerUniform;
42 return *this;
43 }
44
45 const GrTextureAccess* textureAccess() const { return fTextureAccess; }
46
47 private:
bsalomon@google.com34cccde2013-01-04 18:34:30 +000048 // The idx param is used to ensure multiple samplers within a single effect have unique
49 // uniform names.
50 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) {
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000051 GrAssert(NULL == fTextureAccess);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000052 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
53
54 GrAssert(NULL != builder);
55 GrAssert(NULL != access);
bsalomon@google.com34cccde2013-01-04 18:34:30 +000056 SkString name;
57 name.printf("Sampler%d_", idx);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000058 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
59 kSampler2D_GrSLType,
bsalomon@google.com34cccde2013-01-04 18:34:30 +000060 name.c_str());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000061 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
62
63 fTextureAccess = access;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000064 }
65
66 const GrTextureAccess* fTextureAccess;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000067 GrGLUniformManager::UniformHandle fSamplerUniform;
68
69 friend class GrGLShaderBuilder; // to access fSamplerUniform
70 friend class GrGLProgram; // to construct these and access fSamplerUniform.
71 };
72
73 typedef SkTArray<TextureSampler> TextureSamplerArray;
74
bsalomon@google.comeb715c82012-07-11 15:03:31 +000075 enum ShaderType {
76 kVertex_ShaderType = 0x1,
77 kGeometry_ShaderType = 0x2,
78 kFragment_ShaderType = 0x4,
79 };
80
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000081 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000082
bsalomon@google.comdbe49f72012-11-05 16:36:02 +000083 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
84 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
85 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000086 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000087 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +000088 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +000089 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +000090
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000091 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
92 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
93 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
94 called. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000095 void appendTextureLookupAndModulate(SkString* out,
96 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000097 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +000098 const char* coordName,
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000099 GrSLType coordType = kVec2f_GrSLType) const;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000100
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000101 /** Emits a helper function outside of main(). Currently ShaderType must be
102 kFragment_ShaderType. */
103 void emitFunction(ShaderType shader,
104 GrSLType returnType,
105 const char* name,
106 int argCnt,
107 const GrGLShaderVar* args,
108 const char* body,
109 SkString* outName);
110
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000111 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000112 capabilities of the GL context. This is useful for keying the shader programs that may
113 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000114 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
115 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000116
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000117 /** If texture swizzling is available using tex parameters then it is preferred over mangling
118 the generated shader code. This potentially allows greater reuse of cached shaders. */
119 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
120
bsalomon@google.com706f6682012-10-23 14:53:55 +0000121 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000122 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
123 should be accessible. At least one bit must be set. Geometry shader uniforms are not
124 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
125 it will refer to the final uniform name after return. Use the addUniformArray variant to add
126 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000127 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000128 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
129 GrSLType type,
130 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000131 const char** outName = NULL) {
132 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
133 }
134 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
135 GrSLType type,
136 const char* name,
137 int arrayCount,
138 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000139
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000140 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000141
142 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000143 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000144 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000145 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000146 return this->getUniformVariable(u).c_str();
147 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000148
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000149 /** Add a varying variable to the current program to pass values between vertex and fragment
150 shaders. If the last two parameters are non-NULL, they are filled in with the name
151 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000152 void addVarying(GrSLType type,
153 const char* name,
154 const char** vsOutName = NULL,
155 const char** fsInName = NULL);
156
bsalomon@google.com706f6682012-10-23 14:53:55 +0000157 /** Returns a variable name that represents the position of the fragment in the FS. The position
158 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
159 const char* fragmentPosition();
160
bsalomon@google.com17504f52012-10-30 12:34:25 +0000161 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
162 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
163 */
164 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
165
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000166 /**
167 * Interfaces used by GrGLProgram.
168 * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
169 * Also, GrGLProgram's shader string construction should be moved to this class.
170 */
171
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000172 /** Called after building is complete to get the final shader string. */
173 void getShader(ShaderType, SkString*) const;
174
bsalomon@google.com08283af2012-10-26 13:01:20 +0000175 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
176 void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000177 // TODO: move remainder of shader code generation to this class and call this privately
178 // Handles of sampler uniforms generated for the effect are appended to samplerHandles.
179 GrGLEffect* createAndEmitGLEffect(
180 const GrEffectStage& stage,
181 GrBackendEffectFactory::EffectKey key,
182 const char* fsInColor, // NULL means no incoming color
183 const char* fsOutColor,
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000184 const char* vsInCoord,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000185 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000186 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000187 // TODO: Make this do all the compiling, linking, etc.
188 void finished(GrGLuint programID);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000189
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000190 const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
191
bsalomon@google.com032b2212012-07-16 13:36:18 +0000192private:
193 typedef GrTAllocator<GrGLShaderVar> VarArray;
194
bsalomon@google.com032b2212012-07-16 13:36:18 +0000195 void appendDecls(const VarArray&, SkString*) const;
196 void appendUniformDecls(ShaderType, SkString*) const;
197
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000198 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
199 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000200
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000201 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000202public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000203
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000204 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000205 VarArray fVSAttrs;
206 VarArray fVSOutputs;
207 VarArray fGSInputs;
208 VarArray fGSOutputs;
209 VarArray fFSInputs;
210 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000211 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000212 SkString fVSCode;
213 SkString fGSCode;
214 SkString fFSCode;
215 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000216
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000217private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000218 enum {
219 kNonStageIdx = -1,
220 };
221
robertphillips@google.com6177e692013-02-28 20:16:25 +0000222 const GrGLContextInfo& fCtxInfo;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000223 GrGLUniformManager& fUniformManager;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000224 int fCurrentStageIdx;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000225 SkString fFSFunctions;
226 SkString fFSHeader;
227
228 bool fSetupFragPosition;
229 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000230
bsalomon@google.com17504f52012-10-30 12:34:25 +0000231 GrGLShaderVar* fPositionVar;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000232};
233
234#endif