blob: 852079a09eb6ac76a585f3e448098564924a631e [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.comdbe49f72012-11-05 16:36:02 +000080 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
81 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
82 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000083 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000084 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +000085 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +000086 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +000087
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000088 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
89 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
90 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
91 called. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +000092 void appendTextureLookupAndModulate(SkString* out,
93 const char* modulation,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000094 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +000095 const char* coordName,
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +000096 GrSLType coordType = kVec2f_GrSLType) const;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +000097
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +000098 /** Emits a helper function outside of main(). Currently ShaderType must be
99 kFragment_ShaderType. */
100 void emitFunction(ShaderType shader,
101 GrSLType returnType,
102 const char* name,
103 int argCnt,
104 const GrGLShaderVar* args,
105 const char* body,
106 SkString* outName);
107
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000108 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000109 capabilities of the GL context. This is useful for keying the shader programs that may
110 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000111 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
112 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000113
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000114 /** If texture swizzling is available using tex parameters then it is preferred over mangling
115 the generated shader code. This potentially allows greater reuse of cached shaders. */
116 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
117
bsalomon@google.com706f6682012-10-23 14:53:55 +0000118 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000119 visibility is a bitfield of ShaderType values indicating from which shaders the uniform
120 should be accessible. At least one bit must be set. Geometry shader uniforms are not
121 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
122 it will refer to the final uniform name after return. Use the addUniformArray variant to add
123 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000124 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000125 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
126 GrSLType type,
127 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000128 const char** outName = NULL) {
129 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
130 }
131 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
132 GrSLType type,
133 const char* name,
134 int arrayCount,
135 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000136
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000137 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000138
139 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000140 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000141 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000142 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000143 return this->getUniformVariable(u).c_str();
144 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000145
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000146 /** Add a varying variable to the current program to pass values between vertex and fragment
147 shaders. If the last two parameters are non-NULL, they are filled in with the name
148 generated. */
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000149 void addVarying(GrSLType type,
150 const char* name,
151 const char** vsOutName = NULL,
152 const char** fsInName = NULL);
153
bsalomon@google.com706f6682012-10-23 14:53:55 +0000154 /** Returns a variable name that represents the position of the fragment in the FS. The position
155 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
156 const char* fragmentPosition();
157
bsalomon@google.com17504f52012-10-30 12:34:25 +0000158 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
159 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
160 */
161 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
162
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000163 /** Called after building is complete to get the final shader string. */
164 void getShader(ShaderType, SkString*) const;
165
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000166 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000167 * TODO: Make this do all the compiling, linking, etc. Hide from the GrEffects
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000168 */
169 void finished(GrGLuint programID);
170
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000171 /**
172 * Sets the current stage (used to make variable names unique).
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000173 * TODO: Hide from the GrEffects
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000174 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000175 void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
176 void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000177
bsalomon@google.com706f6682012-10-23 14:53:55 +0000178 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
179
bsalomon@google.com032b2212012-07-16 13:36:18 +0000180private:
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000181
bsalomon@google.com032b2212012-07-16 13:36:18 +0000182 typedef GrTAllocator<GrGLShaderVar> VarArray;
183
bsalomon@google.com032b2212012-07-16 13:36:18 +0000184 void appendDecls(const VarArray&, SkString*) const;
185 void appendUniformDecls(ShaderType, SkString*) const;
186
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000187 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
188 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000189
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000190 // TODO: Everything below here private.
bsalomon@google.com032b2212012-07-16 13:36:18 +0000191public:
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000192
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000193 SkString fHeader; // VS+FS, GLSL version, etc
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000194 VarArray fVSAttrs;
195 VarArray fVSOutputs;
196 VarArray fGSInputs;
197 VarArray fGSOutputs;
198 VarArray fFSInputs;
199 SkString fGSHeader; // layout qualifiers specific to GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000200 VarArray fFSOutputs;
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000201 SkString fVSCode;
202 SkString fGSCode;
203 SkString fFSCode;
204 bool fUsesGS;
tomhudson@google.com040c41a2012-05-18 14:57:40 +0000205
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000206private:
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000207 enum {
208 kNonStageIdx = -1,
209 };
210
bsalomon@google.com706f6682012-10-23 14:53:55 +0000211 const GrGLContextInfo& fContext;
212 GrGLUniformManager& fUniformManager;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000213 int fCurrentStageIdx;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000214 SkString fFSFunctions;
215 SkString fFSHeader;
216
217 bool fSetupFragPosition;
218 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000219
bsalomon@google.com17504f52012-10-30 12:34:25 +0000220 GrGLShaderVar* fPositionVar;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000221};
222
223#endif