blob: 8f5d6956ac2227db8d8dabdb0a49b68d9397b02c [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/GrGLShaderVar.h"
15#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.comad5e9372012-07-11 18:11:27 +000018class GrGLContextInfo;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000019
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000020/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000021 Contains all the incremental state of a shader as it is being built,as well as helpers to
22 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000023*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000024class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000025public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000026 /**
bsalomon@google.com422e81a2012-10-25 14:11:03 +000027 * Used by GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000028 */
29 class TextureSampler {
30 public:
31 TextureSampler()
32 : fTextureAccess(NULL)
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000033 , 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
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000041 fTextureAccess = other.fTextureAccess;
42 fSamplerUniform = other.fSamplerUniform;
43 return *this;
44 }
45
46 const GrTextureAccess* textureAccess() const { return fTextureAccess; }
47
48 private:
49 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access) {
50 GrAssert(NULL == fTextureAccess);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000051 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
52
53 GrAssert(NULL != builder);
54 GrAssert(NULL != access);
55 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
56 kSampler2D_GrSLType,
57 "Sampler");
58 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
59
60 fTextureAccess = access;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000061 }
62
63 const GrTextureAccess* fTextureAccess;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000064 GrGLUniformManager::UniformHandle fSamplerUniform;
65
66 friend class GrGLShaderBuilder; // to access fSamplerUniform
67 friend class GrGLProgram; // to construct these and access fSamplerUniform.
68 };
69
70 typedef SkTArray<TextureSampler> TextureSamplerArray;
71
bsalomon@google.comeb715c82012-07-11 15:03:31 +000072 enum ShaderType {
73 kVertex_ShaderType = 0x1,
74 kGeometry_ShaderType = 0x2,
75 kFragment_ShaderType = 0x4,
76 };
77
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000078 GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000079
bsalomon@google.comeb715c82012-07-11 15:03:31 +000080 /** Determines whether we should use texture2D() or texture2Dproj(), and if an explicit divide
81 is required for the sample coordinates, creates the new variable and emits the code to
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +000082 initialize it. This should only be called by GrGLProgram.*/
83 void setupTextureAccess(const char* varyingFSName, GrSLType varyingType);
tomhudson@google.com52598142012-05-24 17:44:30 +000084
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000085 /** Appends a texture sample with projection if necessary; if coordName is not
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +000086 specified, uses fSampleCoords. coordType must either be Vec2f or Vec3f. The latter is
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000087 interpreted as projective texture coords. The vec length and swizzle order of the result
88 depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000089 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000090 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +000091 const char* coordName = NULL,
92 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +000093
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000094 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
95 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
96 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
97 called. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000098 void appendTextureLookupAndModulate(SkString* out,
99 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000100 const TextureSampler&,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000101 const char* coordName = NULL,
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000102 GrSLType coordType = kVec2f_GrSLType) const;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000103
104 /** Gets the name of the default texture coords which are always kVec2f */
105 const char* defaultTexCoordsName() const { return fDefaultTexCoordsName.c_str(); }
106
107 /* Returns true if the texture matrix from which the default texture coords are computed has
108 perspective. */
109 bool defaultTextureMatrixIsPerspective() const {
110 return fTexCoordVaryingType == kVec3f_GrSLType;
111 }
tomhudson@google.com52598142012-05-24 17:44:30 +0000112
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000113 /** Emits a helper function outside of main(). Currently ShaderType must be
114 kFragment_ShaderType. */
115 void emitFunction(ShaderType shader,
116 GrSLType returnType,
117 const char* name,
118 int argCnt,
119 const GrGLShaderVar* args,
120 const char* body,
121 SkString* outName);
122
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000123 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000124 capabilities of the GL context. This is useful for keying the shader programs that may
125 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000126 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
127 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000128
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000129 /** If texture swizzling is available using tex parameters then it is preferred over mangling
130 the generated shader code. This potentially allows greater reuse of cached shaders. */
131 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
132
bsalomon@google.com706f6682012-10-23 14:53:55 +0000133 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000134 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
135 should be accessible. At least one bit must be set. Geometry shader uniforms are not
136 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
137 it will refer to the final uniform name after return. Use the addUniformArray variant to add
138 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000139 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000140 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
141 GrSLType type,
142 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000143 const char** outName = NULL) {
144 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
145 }
146 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
147 GrSLType type,
148 const char* name,
149 int arrayCount,
150 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000151
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000152 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000153
154 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000155 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000156 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000157 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000158 return this->getUniformVariable(u).c_str();
159 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000160
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000161 /** Add a varying variable to the current program to pass values between vertex and fragment
162 shaders. If the last two parameters are non-NULL, they are filled in with the name
163 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000164 void addVarying(GrSLType type,
165 const char* name,
166 const char** vsOutName = NULL,
167 const char** fsInName = NULL);
168
bsalomon@google.com706f6682012-10-23 14:53:55 +0000169 /** Returns a variable name that represents the position of the fragment in the FS. The position
170 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
171 const char* fragmentPosition();
172
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000173 /** Called after building is complete to get the final shader string. */
174 void getShader(ShaderType, SkString*) const;
175
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000176 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000177 * TODO: Make this do all the compiling, linking, etc. Hide from the GrEffects
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000178 */
179 void finished(GrGLuint programID);
180
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000181 /**
182 * Sets the current stage (used to make variable names unique).
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000183 * TODO: Hide from the GrEffects
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000184 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000185 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
186 void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000187
bsalomon@google.com706f6682012-10-23 14:53:55 +0000188 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
189
bsalomon@google.com032b2212012-07-16 13:36:18 +0000190private:
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000191
bsalomon@google.com032b2212012-07-16 13:36:18 +0000192 typedef GrTAllocator<GrGLShaderVar> VarArray;
193
bsalomon@google.com032b2212012-07-16 13:36:18 +0000194 void appendDecls(const VarArray&, SkString*) const;
195 void appendUniformDecls(ShaderType, SkString*) const;
196
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000197 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
198 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000199
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000200 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000201public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000202
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000203 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000204 VarArray fVSAttrs;
205 VarArray fVSOutputs;
206 VarArray fGSInputs;
207 VarArray fGSOutputs;
208 VarArray fFSInputs;
209 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000210 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000211 SkString fVSCode;
212 SkString fGSCode;
213 SkString fFSCode;
214 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000215
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000216private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000217 enum {
218 kNonStageIdx = -1,
219 };
220
bsalomon@google.com706f6682012-10-23 14:53:55 +0000221 const GrGLContextInfo& fContext;
222 GrGLUniformManager& fUniformManager;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000223 int fCurrentStageIdx;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000224 SkString fFSFunctions;
225 SkString fFSHeader;
226
227 bool fSetupFragPosition;
228 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000229
230 /// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
231 //@{
232 GrSLType fTexCoordVaryingType; // the type, either Vec2f or Vec3f, of the coords passed
233 // as a varying from the VS to the FS.
234 SkString fDefaultTexCoordsName; // the name of the default 2D coords value.
235 //@}
236
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000237};
238
239#endif