blob: a70a0b04a72f5f4f7eb1804048e8747ce705b8bb [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"
bsalomon@google.com77af6802013-10-02 13:04:56 +000016#include "gl/GrGLCoordTransform.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000017#include "gl/GrGLSL.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000018#include "gl/GrGLUniformManager.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000019
bsalomon@google.comf910d3b2013-03-07 17:06:57 +000020#include <stdarg.h>
21
bsalomon@google.comad5e9372012-07-11 18:11:27 +000022class GrGLContextInfo;
bsalomon@google.comc7818882013-03-20 19:19:53 +000023class GrEffectStage;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000024class GrGLProgramDesc;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000025
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000026/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000027 Contains all the incremental state of a shader as it is being built,as well as helpers to
28 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000029*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000030class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000031public:
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000032 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +000033 * Passed to GrGLEffects to add texture reads to their shader code.
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000034 */
35 class TextureSampler {
36 public:
37 TextureSampler()
commit-bot@chromium.org7425c122013-08-14 18:14:19 +000038 : fConfigComponentMask(0) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000039 // we will memcpy the first 4 bytes from passed in swizzle. This ensures the string is
40 // terminated.
41 fSwizzle[4] = '\0';
42 }
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000043
44 TextureSampler(const TextureSampler& other) { *this = other; }
45
46 TextureSampler& operator= (const TextureSampler& other) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000047 SkASSERT(0 == fConfigComponentMask);
48 SkASSERT(!fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000049
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000050 fConfigComponentMask = other.fConfigComponentMask;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000051 fSamplerUniform = other.fSamplerUniform;
52 return *this;
53 }
54
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000055 // bitfield of GrColorComponentFlags present in the texture's config.
56 uint32_t configComponentMask() const { return fConfigComponentMask; }
57
58 const char* swizzle() const { return fSwizzle; }
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000059
bsalomon@google.com26e18b52013-03-29 19:22:36 +000060 bool isInitialized() const { return 0 != fConfigComponentMask; }
61
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000062 private:
bsalomon@google.com34cccde2013-01-04 18:34:30 +000063 // The idx param is used to ensure multiple samplers within a single effect have unique
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000064 // uniform names. swizzle is a four char max string made up of chars 'r', 'g', 'b', and 'a'.
65 void init(GrGLShaderBuilder* builder,
66 uint32_t configComponentMask,
67 const char* swizzle,
68 int idx) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000069 SkASSERT(!this->isInitialized());
70 SkASSERT(0 != configComponentMask);
71 SkASSERT(!fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000072
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000073 SkASSERT(NULL != builder);
bsalomon@google.com34cccde2013-01-04 18:34:30 +000074 SkString name;
bsalomon@google.com504976e2013-05-09 13:45:02 +000075 name.printf("Sampler%d", idx);
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +000076 fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000077 kSampler2D_GrSLType,
bsalomon@google.com34cccde2013-01-04 18:34:30 +000078 name.c_str());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000079 SkASSERT(fSamplerUniform.isValid());
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000080
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000081 fConfigComponentMask = configComponentMask;
82 memcpy(fSwizzle, swizzle, 4);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000083 }
84
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000085 void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000086 SkASSERT(NULL != access);
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000087 this->init(builder,
88 GrPixelConfigComponentMask(access->getTexture()->config()),
89 access->getSwizzle(),
90 idx);
91 }
92
93 uint32_t fConfigComponentMask;
94 char fSwizzle[5];
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000095 GrGLUniformManager::UniformHandle fSamplerUniform;
96
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000097 friend class GrGLShaderBuilder; // to call init().
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000098 };
99
bsalomon@google.com77af6802013-10-02 13:04:56 +0000100 typedef SkTArray<GrGLCoordTransform::TransformedCoords> TransformedCoordsArray;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000101 typedef SkTArray<TextureSampler> TextureSamplerArray;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000102 typedef GrTAllocator<GrGLShaderVar> VarArray;
bsalomon@google.com77af6802013-10-02 13:04:56 +0000103 typedef GrBackendEffectFactory::EffectKey EffectKey;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000104
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000105 enum ShaderVisibility {
106 kVertex_Visibility = 0x1,
107 kGeometry_Visibility = 0x2,
108 kFragment_Visibility = 0x4,
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000109 };
110
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000111 GrGLShaderBuilder(GrGpuGL*,
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000112 GrGLUniformManager&,
113 const GrGLProgramDesc&,
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000114 bool needsVertexShader);
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000115
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000116 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000117 * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
118 * if code is added that uses one of these features without calling enableFeature()
119 */
120 enum GLSLFeature {
121 kStandardDerivatives_GLSLFeature = 0,
122
123 kLastGLSLFeature = kStandardDerivatives_GLSLFeature
124 };
125
126 /**
127 * If the feature is supported then true is returned and any necessary #extension declarations
128 * are added to the shaders. If the feature is not supported then false will be returned.
129 */
130 bool enableFeature(GLSLFeature);
131
132 /**
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000133 * Called by GrGLEffects to add code the fragment shader.
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000134 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000135 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
136 va_list args;
137 va_start(args, format);
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000138 fFSCode.appendf(format, args);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000139 va_end(args);
140 }
141
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000142 void fsCodeAppend(const char* str) { fFSCode.append(str); }
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000143
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000144 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
145 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
146 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000147 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000148 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000149 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000150 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000151
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000152 /** Version of above that appends the result to the fragment shader code instead.*/
153 void fsAppendTextureLookup(const TextureSampler&,
154 const char* coordName,
155 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000156
157
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000158 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
159 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
160 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
161 called. */
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000162 void fsAppendTextureLookupAndModulate(const char* modulation,
163 const TextureSampler&,
164 const char* coordName,
165 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000166
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000167 /** Emits a helper function outside of main() in the fragment shader. */
168 void fsEmitFunction(GrSLType returnType,
169 const char* name,
170 int argCnt,
171 const GrGLShaderVar* args,
172 const char* body,
173 SkString* outName);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000174
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000175 /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
176 GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000177
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.com77af6802013-10-02 13:04:56 +0000181 static EffectKey KeyForTextureAccess(const GrTextureAccess&, const GrGLCaps&);
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000182
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000183 typedef uint8_t DstReadKey;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000184 typedef uint8_t FragPosKey;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000185
186 /** Returns a key for adding code to read the copy-of-dst color in service of effects that
187 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 +0000188 copy read at all (in which case this function should not be called). */
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000189 static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
190
bsalomon@google.comb5158812013-05-13 18:50:25 +0000191 /** Returns a key for reading the fragment location. This should only be called if there is an
192 effect that will requires the fragment position. If the fragment position is not required,
193 the key is 0. */
194 static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);
195
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000196 /** If texture swizzling is available using tex parameters then it is preferred over mangling
197 the generated shader code. This potentially allows greater reuse of cached shaders. */
198 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
199
bsalomon@google.com706f6682012-10-23 14:53:55 +0000200 /** 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 +0000201 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
202 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000203 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
204 it will refer to the final uniform name after return. Use the addUniformArray variant to add
205 an array of uniforms.
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000206 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000207 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
208 GrSLType type,
209 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000210 const char** outName = NULL) {
211 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
212 }
213 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
214 GrSLType type,
215 const char* name,
216 int arrayCount,
217 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000218
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000219 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle u) const {
220 return fUniformManager.getBuilderUniform(fUniforms, u).fVariable;
221 }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000222
223 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000224 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000225 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000226 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000227 return this->getUniformVariable(u).c_str();
228 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000229
bsalomon@google.com77af6802013-10-02 13:04:56 +0000230 /**
231 * This returns a variable name to access the 2D, perspective correct version of the coords in
232 * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a
233 * perspective divide into the fragment shader (xy / z) to convert them to 2D.
234 */
235 SkString ensureFSCoords2D(const TransformedCoordsArray&, int index);
236
bsalomon@google.com706f6682012-10-23 14:53:55 +0000237 /** Returns a variable name that represents the position of the fragment in the FS. The position
238 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
239 const char* fragmentPosition();
240
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000241 /** Returns the color of the destination pixel. This may be NULL if no effect advertised
242 that it will read the destination. */
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000243 const char* dstColor();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000244
bsalomon@google.comc7818882013-03-20 19:19:53 +0000245 /**
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000246 * Interfaces used by GrGLProgram.
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000247 * TODO: These are used by GrGLProgram to insert a mode color filter. Remove these when the
248 * color filter is expressed as a GrEffect.
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000249 */
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000250 const SkString& getInputColor() const { return fInputColor; }
251 GrSLConstantVec getKnownColorValue() const { return fKnownColorValue; }
252 const SkString& getInputCoverage() const { return fInputCoverage; }
253 GrSLConstantVec getKnownCoverageValue() const { return fKnownCoverageValue; }
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000254
bsalomon@google.com504976e2013-05-09 13:45:02 +0000255 /**
256 * Adds code for effects. effectStages contains the effects to add. effectKeys[i] is the key
257 * generated from effectStages[i]. An entry in effectStages can be NULL, in which case it is
258 * skipped. Moreover, if the corresponding key is GrGLEffect::NoEffectKey then it is skipped.
259 * inOutFSColor specifies the input color to the first stage and is updated to be the
260 * output color of the last stage. fsInOutColorKnownValue specifies whether the input color
261 * has a known constant value and is updated to refer to the status of the output color.
262 * The handles to texture samplers for effectStage[i] are added to effectSamplerHandles[i]. The
263 * glEffects array is updated to contain the GrGLEffect generated for each entry in
264 * effectStages.
265 */
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000266 void emitEffects(const GrEffectStage* effectStages[],
bsalomon@google.com77af6802013-10-02 13:04:56 +0000267 const EffectKey effectKeys[],
bsalomon@google.com504976e2013-05-09 13:45:02 +0000268 int effectCnt,
269 SkString* inOutFSColor,
270 GrSLConstantVec* fsInOutColorKnownValue,
bsalomon@google.com77af6802013-10-02 13:04:56 +0000271 SkTArray<GrGLCoordTransform, false>* effectCoordTransformArrays[],
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000272 SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
273 GrGLEffect* glEffects[]);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000274
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000275 const char* getColorOutputName() const;
276 const char* enableSecondaryOutput();
277
bsalomon@google.com706f6682012-10-23 14:53:55 +0000278 GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000279 GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
280 return fDstCopyTopLeftUniform;
281 }
282 GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
283 return fDstCopyScaleUniform;
284 }
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000285 GrGLUniformManager::UniformHandle getColorUniform() const { return fColorUniform; }
286 GrGLUniformManager::UniformHandle getCoverageUniform() const { return fCoverageUniform; }
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000287 GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
288 return fDstCopySampler.fSamplerUniform;
289 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000290
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000291 /** Helper class used to build the vertex and geometry shaders. This functionality
292 is kept separate from the rest of GrGLShaderBuilder to allow for shaders programs
293 that only use the fragment shader. */
294 class VertexBuilder {
295 public:
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000296 VertexBuilder(GrGLShaderBuilder* parent, GrGpuGL* gpu, const GrGLProgramDesc&);
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000297
298 /**
299 * Called by GrGLEffects to add code to one of the shaders.
300 */
301 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
302 va_list args;
303 va_start(args, format);
304 fVSCode.appendf(format, args);
305 va_end(args);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000306 }
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000307
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000308 void vsCodeAppend(const char* str) { fVSCode.append(str); }
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000309
310 /** Add a vertex attribute to the current program that is passed in from the vertex data.
311 Returns false if the attribute was already there, true otherwise. */
312 bool addAttribute(GrSLType type, const char* name);
313
314 /** Add a varying variable to the current program to pass values between vertex and fragment
315 shaders. If the last two parameters are non-NULL, they are filled in with the name
316 generated. */
317 void addVarying(GrSLType type,
318 const char* name,
319 const char** vsOutName = NULL,
320 const char** fsInName = NULL);
321
322 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
323 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
324 */
325 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
326
327 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
328 as positionAttribute() or it may not be. It depends upon whether the rendering code
329 specified explicit local coords or not in the GrDrawState. */
330 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
331
332 /**
333 * Are explicit local coordinates provided as input to the vertex shader.
334 */
335 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
336
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000337 bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
338 const SkString* getEffectAttributeName(int attributeIndex) const;
339
340 GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
341 return fViewMatrixUniform;
342 }
343
344 bool compileAndAttachShaders(GrGLuint programId) const;
345 void bindProgramLocations(GrGLuint programId) const;
346
347 private:
348 GrGLShaderBuilder* fParent;
349 GrGpuGL* fGpu;
350 const GrGLProgramDesc& fDesc;
351 VarArray fVSAttrs;
352 VarArray fVSOutputs;
353 VarArray fGSInputs;
354 VarArray fGSOutputs;
355
356 SkString fVSCode;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000357
358 struct AttributePair {
359 void set(int index, const SkString& name) {
360 fIndex = index; fName = name;
361 }
362 int fIndex;
363 SkString fName;
364 };
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000365 SkSTArray<10, AttributePair, true> fEffectAttributes;
366
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000367 GrGLUniformManager::UniformHandle fViewMatrixUniform;
368
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000369 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
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000377 bool finish(GrGLuint* outProgramId);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000378
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000379 const GrGLContextInfo& ctxInfo() const;
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000380
bsalomon@google.com032b2212012-07-16 13:36:18 +0000381private:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000382 void appendDecls(const VarArray&, SkString*) const;
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000383 void appendUniformDecls(ShaderVisibility, SkString*) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000384
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000385 bool compileAndAttachShaders(GrGLuint programId) const;
386 void bindProgramLocations(GrGLuint programId) const;
387
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000388 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
389 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000390
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000391private:
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000392 class CodeStage : public SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000393 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000394 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
bsalomon@google.com504976e2013-05-09 13:45:02 +0000395
396 bool inStageCode() const {
397 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000398 return NULL != fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000399 }
400
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000401 const GrEffectStage* effectStage() const {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000402 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000403 return fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000404 }
405
406 int stageIndex() const {
skia.committer@gmail.com0f20a3f2013-05-10 07:01:04 +0000407 this->validate();
bsalomon@google.com504976e2013-05-09 13:45:02 +0000408 return fCurrentIndex;
409 }
410
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000411 class AutoStageRestore : public SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000412 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000413 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000414 SkASSERT(NULL != codeStage);
bsalomon@google.com504976e2013-05-09 13:45:02 +0000415 fSavedIndex = codeStage->fCurrentIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000416 fSavedEffectStage = codeStage->fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000417
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000418 if (NULL == newStage) {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000419 codeStage->fCurrentIndex = -1;
420 } else {
421 codeStage->fCurrentIndex = codeStage->fNextIndex++;
422 }
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000423 codeStage->fEffectStage = newStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000424
425 fCodeStage = codeStage;
426 }
427 ~AutoStageRestore() {
428 fCodeStage->fCurrentIndex = fSavedIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000429 fCodeStage->fEffectStage = fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000430 }
431 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000432 CodeStage* fCodeStage;
433 int fSavedIndex;
434 const GrEffectStage* fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000435 };
436 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000437 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
438 int fNextIndex;
439 int fCurrentIndex;
440 const GrEffectStage* fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000441 } fCodeStage;
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000442
bsalomon@google.com42eff162013-04-02 12:50:49 +0000443 /**
444 * Features that should only be enabled by GrGLShaderBuilder itself.
445 */
446 enum GLSLPrivateFeature {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000447 kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
448 kEXTShaderFramebufferFetch_GLSLPrivateFeature,
449 kNVShaderFramebufferFetch_GLSLPrivateFeature,
bsalomon@google.com42eff162013-04-02 12:50:49 +0000450 };
451 bool enablePrivateFeature(GLSLPrivateFeature);
452
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000453 // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and
454 // track the enables separately for each shader.
bsalomon@google.com42eff162013-04-02 12:50:49 +0000455 void addFSFeature(uint32_t featureBit, const char* extensionName);
456
bsalomon@google.com504976e2013-05-09 13:45:02 +0000457 // Generates a name for a variable. The generated string will be name prefixed by the prefix
458 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
459 // generating stage code.
460 void nameVariable(SkString* out, char prefix, const char* name);
461
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000462 // Interpretation of DstReadKey when generating code
463 enum {
464 kNoDstRead_DstReadKey = 0,
465 kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
466 kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
467 kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
468 };
469
bsalomon@google.comb5158812013-05-13 18:50:25 +0000470 enum {
471 kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
472 kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
473 kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
474 };
475
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000476 GrGpuGL* fGpu;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000477 GrGLUniformManager& fUniformManager;
bsalomon@google.com42eff162013-04-02 12:50:49 +0000478 uint32_t fFSFeaturesAddedMask;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000479 SkString fFSFunctions;
bsalomon@google.com42eff162013-04-02 12:50:49 +0000480 SkString fFSExtensions;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000481 VarArray fFSInputs;
482 VarArray fFSOutputs;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000483
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000484 SkString fFSCode;
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000485
bsalomon@google.com706f6682012-10-23 14:53:55 +0000486 bool fSetupFragPosition;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000487 TextureSampler fDstCopySampler;
488
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000489 SkString fInputColor;
490 GrSLConstantVec fKnownColorValue;
491 SkString fInputCoverage;
492 GrSLConstantVec fKnownCoverageValue;
493
494 bool fHasCustomColorOutput;
495 bool fHasSecondaryOutput;
496
bsalomon@google.com706f6682012-10-23 14:53:55 +0000497 GrGLUniformManager::UniformHandle fRTHeightUniform;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000498 GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
499 GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000500 GrGLUniformManager::UniformHandle fColorUniform;
501 GrGLUniformManager::UniformHandle fCoverageUniform;
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000502
bsalomon@google.comb5158812013-05-13 18:50:25 +0000503 bool fTopLeftFragPosRead;
504
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000505 SkAutoTDelete<VertexBuilder> fVertexBuilder;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000506};
507
508#endif