blob: 5f2983d19dbbfd36eb857f09ca09fdea3dfdbc04 [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"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000015#include "SkTypes.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000016#include "gl/GrGLSL.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000017#include "gl/GrGLUniformManager.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000018
bsalomon@google.comf910d3b2013-03-07 17:06:57 +000019#include <stdarg.h>
20
bsalomon@google.comad5e9372012-07-11 18:11:27 +000021class GrGLContextInfo;
bsalomon@google.comc7818882013-03-20 19:19:53 +000022class GrEffectStage;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000023class GrGLProgramDesc;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000024
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000025/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000026 Contains all the incremental state of a shader as it is being built,as well as helpers to
27 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000028*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000029class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000030public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000031 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +000032 * Passed to GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000033 */
34 class TextureSampler {
35 public:
36 TextureSampler()
commit-bot@chromium.org7425c122013-08-14 18:14:19 +000037 : fConfigComponentMask(0) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000038 // 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) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000046 SkASSERT(0 == fConfigComponentMask);
47 SkASSERT(!fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000048
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) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000068 SkASSERT(!this->isInitialized());
69 SkASSERT(0 != configComponentMask);
70 SkASSERT(!fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000071
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000072 SkASSERT(NULL != builder);
bsalomon@google.com34cccde2013-01-04 18:34:30 +000073 SkString name;
bsalomon@google.com504976e2013-05-09 13:45:02 +000074 name.printf("Sampler%d", idx);
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +000075 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000076 kSampler2D_GrSLType,
bsalomon@google.com34cccde2013-01-04 18:34:30 +000077 name.c_str());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000078 SkASSERT(fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000079
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) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000085 SkASSERT(NULL != access);
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000086 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;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000100 typedef GrTAllocator<GrGLShaderVar> VarArray;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000101
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000102 enum ShaderVisibility {
103 kVertex_Visibility = 0x1,
104 kGeometry_Visibility = 0x2,
105 kFragment_Visibility = 0x4,
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000106 };
107
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000108 GrGLShaderBuilder(const GrGLContextInfo&,
109 GrGLUniformManager&,
110 const GrGLProgramDesc&,
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000111 bool hasVertexShaderEffects);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000112
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000113 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000114 * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
115 * if code is added that uses one of these features without calling enableFeature()
116 */
117 enum GLSLFeature {
118 kStandardDerivatives_GLSLFeature = 0,
119
120 kLastGLSLFeature = kStandardDerivatives_GLSLFeature
121 };
122
123 /**
124 * If the feature is supported then true is returned and any necessary #extension declarations
125 * are added to the shaders. If the feature is not supported then false will be returned.
126 */
127 bool enableFeature(GLSLFeature);
128
129 /**
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000130 * Called by GrGLEffects to add code the fragment shader.
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000131 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000132 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
133 va_list args;
134 va_start(args, format);
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000135 fFSCode.appendf(format, args);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000136 va_end(args);
137 }
138
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000139 void fsCodeAppend(const char* str) { fFSCode.append(str); }
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000140
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000141 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
142 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
143 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000144 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000145 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000146 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000147 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000148
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000149 /** Version of above that appends the result to the fragment shader code instead.*/
150 void fsAppendTextureLookup(const TextureSampler&,
151 const char* coordName,
152 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000153
154
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000155 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
156 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
157 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
158 called. */
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000159 void fsAppendTextureLookupAndModulate(const char* modulation,
160 const TextureSampler&,
161 const char* coordName,
162 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000163
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000164 /** Emits a helper function outside of main() in the fragment shader. */
165 void fsEmitFunction(GrSLType returnType,
166 const char* name,
167 int argCnt,
168 const GrGLShaderVar* args,
169 const char* body,
170 SkString* outName);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000171
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000172 /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
173 GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
174 GrGLShaderVar& fsOutputAppend() { return fFSOutputs.push_back(); }
175 GrGLShaderVar& fsInputAppend(const GrGLShaderVar& var) { return fFSInputs.push_back(var); }
176 GrGLShaderVar& fsOutputAppend(const GrGLShaderVar& var) { return fFSOutputs.push_back(var); }
177
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000178 /** Generates a EffectKey for the shader code based on the texture access parameters and the
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000179 capabilities of the GL context. This is useful for keying the shader programs that may
180 have multiple representations, based on the type/format of textures used. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000181 static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
182 const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000183
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000184 typedef uint8_t DstReadKey;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000185 typedef uint8_t FragPosKey;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000186
187 /** Returns a key for adding code to read the copy-of-dst color in service of effects that
188 require reading the dst. It must not return 0 because 0 indicates that there is no dst
bsalomon@google.comb5158812013-05-13 18:50:25 +0000189 copy read at all (in which case this function should not be called). */
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000190 static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
191
bsalomon@google.comb5158812013-05-13 18:50:25 +0000192 /** Returns a key for reading the fragment location. This should only be called if there is an
193 effect that will requires the fragment position. If the fragment position is not required,
194 the key is 0. */
195 static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);
196
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000197 /** If texture swizzling is available using tex parameters then it is preferred over mangling
198 the generated shader code. This potentially allows greater reuse of cached shaders. */
199 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
200
bsalomon@google.com706f6682012-10-23 14:53:55 +0000201 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000202 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
203 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000204 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
205 it will refer to the final uniform name after return. Use the addUniformArray variant to add
206 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000207 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000208 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
209 GrSLType type,
210 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000211 const char** outName = NULL) {
212 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
213 }
214 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
215 GrSLType type,
216 const char* name,
217 int arrayCount,
218 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000219
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000220 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle u) const {
221 return fUniformManager.getBuilderUniform(fUniforms, u).fVariable;
222 }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000223
224 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000225 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000226 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000227 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000228 return this->getUniformVariable(u).c_str();
229 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000230
bsalomon@google.com706f6682012-10-23 14:53:55 +0000231 /** Returns a variable name that represents the position of the fragment in the FS. The position
232 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
233 const char* fragmentPosition();
234
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000235 /** Returns the color of the destination pixel. This may be NULL if no effect advertised
236 that it will read the destination. */
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000237 const char* dstColor();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000238
bsalomon@google.comc7818882013-03-20 19:19:53 +0000239 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000240 * Interfaces used by GrGLProgram.
241 * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
242 * Also, GrGLProgram's shader string construction should be moved to this class.
243 */
244
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000245 /** Called after building is complete to get the final shader string. To acces the vertex
246 and geometry shaders, use the VertexBuilder. */
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000247 void fsGetShader(SkString*) const;
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000248
bsalomon@google.com504976e2013-05-09 13:45:02 +0000249 /**
250 * Adds code for effects. effectStages contains the effects to add. effectKeys[i] is the key
251 * generated from effectStages[i]. An entry in effectStages can be NULL, in which case it is
252 * skipped. Moreover, if the corresponding key is GrGLEffect::NoEffectKey then it is skipped.
253 * inOutFSColor specifies the input color to the first stage and is updated to be the
254 * output color of the last stage. fsInOutColorKnownValue specifies whether the input color
255 * has a known constant value and is updated to refer to the status of the output color.
256 * The handles to texture samplers for effectStage[i] are added to effectSamplerHandles[i]. The
257 * glEffects array is updated to contain the GrGLEffect generated for each entry in
258 * effectStages.
259 */
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000260 void emitEffects(GrGLEffect* const glEffects[],
261 const GrDrawEffect drawEffects[],
bsalomon@google.com504976e2013-05-09 13:45:02 +0000262 const GrBackendEffectFactory::EffectKey effectKeys[],
263 int effectCnt,
264 SkString* inOutFSColor,
265 GrSLConstantVec* fsInOutColorKnownValue,
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000266 SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[]);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000267
bsalomon@google.com706f6682012-10-23 14:53:55 +0000268 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000269 GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
270 return fDstCopyTopLeftUniform;
271 }
272 GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
273 return fDstCopyScaleUniform;
274 }
275 GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
276 return fDstCopySampler.fSamplerUniform;
277 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000278
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000279 /** Helper class used to build the vertex and geometry shaders. This functionality
280 is kept separate from the rest of GrGLShaderBuilder to allow for shaders programs
281 that only use the fragment shader. */
282 class VertexBuilder {
283 public:
284 VertexBuilder(GrGLShaderBuilder* parent, const GrGLProgramDesc&);
285
286 /**
287 * Called by GrGLEffects to add code to one of the shaders.
288 */
289 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
290 va_list args;
291 va_start(args, format);
292 fVSCode.appendf(format, args);
293 va_end(args);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000294 }
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000295
296 void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
297 va_list args;
298 va_start(args, format);
299 fGSCode.appendf(format, args);
300 va_end(args);
301 }
302
303 void vsCodeAppend(const char* str) { fVSCode.append(str); }
304 void gsCodeAppend(const char* str) { fGSCode.append(str); }
305
306 /** Add a vertex attribute to the current program that is passed in from the vertex data.
307 Returns false if the attribute was already there, true otherwise. */
308 bool addAttribute(GrSLType type, const char* name);
309
310 /** Add a varying variable to the current program to pass values between vertex and fragment
311 shaders. If the last two parameters are non-NULL, they are filled in with the name
312 generated. */
313 void addVarying(GrSLType type,
314 const char* name,
315 const char** vsOutName = NULL,
316 const char** fsInName = NULL);
317
318 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
319 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
320 */
321 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
322
323 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
324 as positionAttribute() or it may not be. It depends upon whether the rendering code
325 specified explicit local coords or not in the GrDrawState. */
326 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
327
328 /**
329 * Are explicit local coordinates provided as input to the vertex shader.
330 */
331 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
332
333 /** Called after building is complete to get the final shader string. */
334 void vsGetShader(SkString*) const;
335 void gsGetShader(SkString*) const;
336
337 struct AttributePair {
338 void set(int index, const SkString& name) {
339 fIndex = index; fName = name;
340 }
341 int fIndex;
342 SkString fName;
343 };
344 const SkTArray<AttributePair, true>& getEffectAttributes() const {
345 return fEffectAttributes;
346 }
347 bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
348 const SkString* getEffectAttributeName(int attributeIndex) const;
349
350 // TODO: Everything below here private.
351 public:
352
353 VarArray fVSAttrs;
354 VarArray fVSOutputs;
355 VarArray fGSInputs;
356 VarArray fGSOutputs;
357 SkString fGSHeader; // layout qualifiers specific to GS
358
359 private:
360 GrGLShaderBuilder* fParent;
361
362 bool fUsesGS;
363
364 SkString fVSCode;
365 SkString fGSCode;
366
367 SkSTArray<10, AttributePair, true> fEffectAttributes;
368
369 GrGLShaderVar* fPositionVar;
370 GrGLShaderVar* fLocalCoordsVar;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000371 };
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000372
373 /** Gets the vertex builder that is used to construct the vertex and geometry shaders.
374 It may be NULL if this shader program is only meant to have a fragment shader. */
375 VertexBuilder* getVertexBuilder() const { return fVertexBuilder.get(); }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000376
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000377 // TODO: Make this do all the compiling, linking, etc.
378 void finished(GrGLuint programID);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000379
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000380 const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
381
bsalomon@google.com032b2212012-07-16 13:36:18 +0000382private:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000383 void appendDecls(const VarArray&, SkString*) const;
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000384 void appendUniformDecls(ShaderVisibility, SkString*) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000385
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000386 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
387 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000388
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000389private:
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000390 class CodeStage : public SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000391 public:
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000392 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffect(NULL) {}
bsalomon@google.com504976e2013-05-09 13:45:02 +0000393
394 bool inStageCode() const {
395 this->validate();
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000396 return NULL != fEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000397 }
398
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000399 const GrEffectRef* effect() const {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000400 this->validate();
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000401 return fEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000402 }
403
404 int stageIndex() const {
skia.committer@gmail.com0f20a3f2013-05-10 07:01:04 +0000405 this->validate();
bsalomon@google.com504976e2013-05-09 13:45:02 +0000406 return fCurrentIndex;
407 }
408
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000409 class AutoStageRestore : public SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000410 public:
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000411 AutoStageRestore(CodeStage* codeStage, const GrEffectRef* effect) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000412 SkASSERT(NULL != codeStage);
bsalomon@google.com504976e2013-05-09 13:45:02 +0000413 fSavedIndex = codeStage->fCurrentIndex;
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000414 fSavedEffect = codeStage->fEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000415
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000416 if (NULL == effect) {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000417 codeStage->fCurrentIndex = -1;
418 } else {
419 codeStage->fCurrentIndex = codeStage->fNextIndex++;
420 }
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000421 codeStage->fEffect = effect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000422
423 fCodeStage = codeStage;
424 }
425 ~AutoStageRestore() {
426 fCodeStage->fCurrentIndex = fSavedIndex;
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000427 fCodeStage->fEffect = fSavedEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000428 }
429 private:
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000430 CodeStage* fCodeStage;
431 int fSavedIndex;
432 const GrEffectRef* fSavedEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000433 };
434 private:
commit-bot@chromium.orga91f0312013-09-06 20:19:56 +0000435 void validate() const { SkASSERT((NULL == fEffect) == (-1 == fCurrentIndex)); }
436 int fNextIndex;
437 int fCurrentIndex;
438 const GrEffectRef* fEffect;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000439 } fCodeStage;
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000440
bsalomon@google.com42eff162013-04-02 12:50:49 +0000441 /**
442 * Features that should only be enabled by GrGLShaderBuilder itself.
443 */
444 enum GLSLPrivateFeature {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000445 kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
446 kEXTShaderFramebufferFetch_GLSLPrivateFeature,
447 kNVShaderFramebufferFetch_GLSLPrivateFeature,
bsalomon@google.com42eff162013-04-02 12:50:49 +0000448 };
449 bool enablePrivateFeature(GLSLPrivateFeature);
450
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000451 // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and
452 // track the enables separately for each shader.
bsalomon@google.com42eff162013-04-02 12:50:49 +0000453 void addFSFeature(uint32_t featureBit, const char* extensionName);
454
bsalomon@google.com504976e2013-05-09 13:45:02 +0000455 // Generates a name for a variable. The generated string will be name prefixed by the prefix
456 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
457 // generating stage code.
458 void nameVariable(SkString* out, char prefix, const char* name);
459
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000460 // Interpretation of DstReadKey when generating code
461 enum {
462 kNoDstRead_DstReadKey = 0,
463 kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
464 kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
465 kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
466 };
467
bsalomon@google.comb5158812013-05-13 18:50:25 +0000468 enum {
469 kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
470 kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
471 kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
472 };
473
robertphillips@google.com6177e692013-02-28 20:16:25 +0000474 const GrGLContextInfo& fCtxInfo;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000475 GrGLUniformManager& fUniformManager;
bsalomon@google.com42eff162013-04-02 12:50:49 +0000476 uint32_t fFSFeaturesAddedMask;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000477 SkString fFSFunctions;
bsalomon@google.com42eff162013-04-02 12:50:49 +0000478 SkString fFSExtensions;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000479 VarArray fFSInputs;
480 VarArray fFSOutputs;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000481
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000482 SkString fFSCode;
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000483
bsalomon@google.com706f6682012-10-23 14:53:55 +0000484 bool fSetupFragPosition;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000485 TextureSampler fDstCopySampler;
486
bsalomon@google.com706f6682012-10-23 14:53:55 +0000487 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000488 GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
489 GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000490
bsalomon@google.comb5158812013-05-13 18:50:25 +0000491 bool fTopLeftFragPosRead;
492
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000493 SkAutoTDelete<VertexBuilder> fVertexBuilder;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000494};
495
496#endif