blob: fa682685767c07ae83beafbad6a5dd592fcf6a5d [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.coma469c282012-10-24 18:28:34 +000012#include "GrEffect.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 /**
bsalomon@google.com422e81a2012-10-25 14:11:03 +000026 * Used by 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:
48 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access) {
49 GrAssert(NULL == fTextureAccess);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000050 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
51
52 GrAssert(NULL != builder);
53 GrAssert(NULL != access);
54 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
55 kSampler2D_GrSLType,
56 "Sampler");
57 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
58
59 fTextureAccess = access;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000060 }
61
62 const GrTextureAccess* fTextureAccess;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000063 GrGLUniformManager::UniformHandle fSamplerUniform;
64
65 friend class GrGLShaderBuilder; // to access fSamplerUniform
66 friend class GrGLProgram; // to construct these and access fSamplerUniform.
67 };
68
69 typedef SkTArray<TextureSampler> TextureSamplerArray;
70
bsalomon@google.comeb715c82012-07-11 15:03:31 +000071 enum ShaderType {
72 kVertex_ShaderType = 0x1,
73 kGeometry_ShaderType = 0x2,
74 kFragment_ShaderType = 0x4,
75 };
76
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000077 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000078
bsalomon@google.comeb715c82012-07-11 15:03:31 +000079 /** Determines whether we should use texture2D() or texture2Dproj(), and if an explicit divide
80 is required for the sample coordinates, creates the new variable and emits the code to
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +000081 initialize it. This should only be called by GrGLProgram.*/
82 void setupTextureAccess(const char* varyingFSName, GrSLType varyingType);
tomhudson@google.com52598142012-05-24 17:44:30 +000083
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000084 /** Appends a texture sample with projection if necessary; if coordName is not
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +000085 specified, uses fSampleCoords. coordType must either be Vec2f or Vec3f. The latter is
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000086 interpreted as projective texture coords. The vec length and swizzle order of the result
87 depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000088 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000089 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +000090 const char* coordName = NULL,
91 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +000092
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000093 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
94 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
95 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
96 called. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000097 void appendTextureLookupAndModulate(SkString* out,
98 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000099 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000100 const char* coordName = NULL,
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000101 GrSLType coordType = kVec2f_GrSLType) const;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000102
103 /** Gets the name of the default texture coords which are always kVec2f */
104 const char* defaultTexCoordsName() const { return fDefaultTexCoordsName.c_str(); }
105
106 /* Returns true if the texture matrix from which the default texture coords are computed has
107 perspective. */
108 bool defaultTextureMatrixIsPerspective() const {
109 return fTexCoordVaryingType == kVec3f_GrSLType;
110 }
tomhudson@google.com52598142012-05-24 17:44:30 +0000111
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000112 /** Emits a helper function outside of main(). Currently ShaderType must be
113 kFragment_ShaderType. */
114 void emitFunction(ShaderType shader,
115 GrSLType returnType,
116 const char* name,
117 int argCnt,
118 const GrGLShaderVar* args,
119 const char* body,
120 SkString* outName);
121
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000122 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000123 capabilities of the GL context. This is useful for keying the shader programs that may
124 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000125 static GrEffect::EffectKey KeyForTextureAccess(const GrTextureAccess& access,
126 const GrGLCaps& caps);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000127
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000128 /** If texture swizzling is available using tex parameters then it is preferred over mangling
129 the generated shader code. This potentially allows greater reuse of cached shaders. */
130 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
131
bsalomon@google.com706f6682012-10-23 14:53:55 +0000132 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000133 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
134 should be accessible. At least one bit must be set. Geometry shader uniforms are not
135 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
136 it will refer to the final uniform name after return. Use the addUniformArray variant to add
137 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000138 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000139 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
140 GrSLType type,
141 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000142 const char** outName = NULL) {
143 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
144 }
145 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
146 GrSLType type,
147 const char* name,
148 int arrayCount,
149 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000150
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000151 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000152
153 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000154 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000155 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000156 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000157 return this->getUniformVariable(u).c_str();
158 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000159
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000160 /** Add a varying variable to the current program to pass values between vertex and fragment
161 shaders. If the last two parameters are non-NULL, they are filled in with the name
162 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000163 void addVarying(GrSLType type,
164 const char* name,
165 const char** vsOutName = NULL,
166 const char** fsInName = NULL);
167
bsalomon@google.com706f6682012-10-23 14:53:55 +0000168 /** Returns a variable name that represents the position of the fragment in the FS. The position
169 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
170 const char* fragmentPosition();
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.comdbbc4e22012-07-25 17:48:39 +0000175 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000176 * TODO: Make this do all the compiling, linking, etc. Hide from the GrEffects
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000177 */
178 void finished(GrGLuint programID);
179
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000180 /**
181 * Sets the current stage (used to make variable names unique).
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000182 * TODO: Hide from the GrEffects
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000183 */
184 void setCurrentStage(int stage) { fCurrentStage = stage; }
185 void setNonStage() { fCurrentStage = kNonStageIdx; }
186
bsalomon@google.com706f6682012-10-23 14:53:55 +0000187 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
188
bsalomon@google.com032b2212012-07-16 13:36:18 +0000189private:
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000190
bsalomon@google.com032b2212012-07-16 13:36:18 +0000191 typedef GrTAllocator<GrGLShaderVar> VarArray;
192
bsalomon@google.com032b2212012-07-16 13:36:18 +0000193 void appendDecls(const VarArray&, SkString*) const;
194 void appendUniformDecls(ShaderType, SkString*) const;
195
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000196 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
197 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000198
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000199 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000200public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000201
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000202 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000203 VarArray fVSAttrs;
204 VarArray fVSOutputs;
205 VarArray fGSInputs;
206 VarArray fGSOutputs;
207 VarArray fFSInputs;
208 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000209 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000210 SkString fVSCode;
211 SkString fGSCode;
212 SkString fFSCode;
213 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000214
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000215private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000216 enum {
217 kNonStageIdx = -1,
218 };
219
bsalomon@google.com706f6682012-10-23 14:53:55 +0000220 const GrGLContextInfo& fContext;
221 GrGLUniformManager& fUniformManager;
222 int fCurrentStage;
223 SkString fFSFunctions;
224 SkString fFSHeader;
225
226 bool fSetupFragPosition;
227 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000228
229 /// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
230 //@{
231 GrSLType fTexCoordVaryingType; // the type, either Vec2f or Vec3f, of the coords passed
232 // as a varying from the VS to the FS.
233 SkString fDefaultTexCoordsName; // the name of the default 2D coords value.
234 //@}
235
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000236};
237
238#endif