blob: c28cd0999bf3c70f4824770b06478b327a12e5f3 [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"
bsalomon848faf02014-07-11 10:01:02 -070016#include "gl/GrGLProgramDesc.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000017#include "gl/GrGLProgramEffects.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000018#include "gl/GrGLSL.h"
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000019#include "gl/GrGLUniformManager.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000020
bsalomon@google.comf910d3b2013-03-07 17:06:57 +000021#include <stdarg.h>
22
bsalomon@google.comad5e9372012-07-11 18:11:27 +000023class GrGLContextInfo;
bsalomon@google.comc7818882013-03-20 19:19:53 +000024class GrEffectStage;
bsalomon@google.com26e18b52013-03-29 19:22:36 +000025class GrGLProgramDesc;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000026
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000027/**
bsalomon@google.comeb715c82012-07-11 15:03:31 +000028 Contains all the incremental state of a shader as it is being built,as well as helpers to
29 manipulate that state.
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000030*/
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000031class GrGLShaderBuilder {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000032public:
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +000033 typedef GrTAllocator<GrGLShaderVar> VarArray;
bsalomon@google.com77af6802013-10-02 13:04:56 +000034 typedef GrBackendEffectFactory::EffectKey EffectKey;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000035 typedef GrGLProgramEffects::TextureSampler TextureSampler;
36 typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000037 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000038
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +000039 enum ShaderVisibility {
40 kVertex_Visibility = 0x1,
41 kGeometry_Visibility = 0x2,
42 kFragment_Visibility = 0x4,
bsalomon@google.comeb715c82012-07-11 15:03:31 +000043 };
44
commit-bot@chromium.org03652612014-05-29 19:09:52 +000045 typedef GrGLUniformManager::UniformHandle UniformHandle;
46
47 // Handles for program uniforms (other than per-effect uniforms)
48 struct UniformHandles {
49 UniformHandle fViewMatrixUni;
50 UniformHandle fRTAdjustmentUni;
51 UniformHandle fColorUni;
52 UniformHandle fCoverageUni;
53
54 // We use the render target height to provide a y-down frag coord when specifying
55 // origin_upper_left is not supported.
56 UniformHandle fRTHeightUni;
57
58 // Uniforms for computing texture coords to do the dst-copy lookup
59 UniformHandle fDstCopyTopLeftUni;
60 UniformHandle fDstCopyScaleUni;
61 UniformHandle fDstCopySamplerUni;
62 };
63
64 struct GenProgramOutput {
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +000065 GenProgramOutput()
66 : fColorEffects(NULL)
67 , fCoverageEffects(NULL)
68 , fHasVertexShader(false)
69 , fTexCoordSetCnt(0)
70 , fProgramID(0) {}
71
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000072 GenProgramOutput(const GenProgramOutput& other) {
73 *this = other;
74 }
75
76 GenProgramOutput& operator=(const GenProgramOutput& other) {
77 fColorEffects.reset(SkRef(other.fColorEffects.get()));
78 fCoverageEffects.reset(SkRef(other.fCoverageEffects.get()));
79 fUniformHandles = other.fUniformHandles;
80 fHasVertexShader = other.fHasVertexShader;
81 fTexCoordSetCnt = other.fTexCoordSetCnt;
82 fProgramID = other.fProgramID;
83 return *this;
84 }
85
86 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
87 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
88 UniformHandles fUniformHandles;
89 bool fHasVertexShader;
90 int fTexCoordSetCnt;
91 GrGLuint fProgramID;
commit-bot@chromium.org03652612014-05-29 19:09:52 +000092 };
93
94 static bool GenProgram(GrGpuGL* gpu,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000095 GrGLUniformManager* uman,
commit-bot@chromium.org03652612014-05-29 19:09:52 +000096 const GrGLProgramDesc& desc,
97 const GrEffectStage* inColorStages[],
98 const GrEffectStage* inCoverageStages[],
99 GenProgramOutput* output);
100
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000101 virtual ~GrGLShaderBuilder() {}
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000102
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000103 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000104 * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
105 * if code is added that uses one of these features without calling enableFeature()
106 */
107 enum GLSLFeature {
108 kStandardDerivatives_GLSLFeature = 0,
109
110 kLastGLSLFeature = kStandardDerivatives_GLSLFeature
111 };
112
113 /**
114 * If the feature is supported then true is returned and any necessary #extension declarations
115 * are added to the shaders. If the feature is not supported then false will be returned.
116 */
117 bool enableFeature(GLSLFeature);
118
119 /**
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000120 * Called by GrGLEffects to add code the fragment shader.
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000121 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000122 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
123 va_list args;
124 va_start(args, format);
commit-bot@chromium.orgce0e4ef2013-11-21 17:20:17 +0000125 fFSCode.appendVAList(format, args);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000126 va_end(args);
127 }
128
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000129 void fsCodeAppend(const char* str) { fFSCode.append(str); }
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000130
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000131 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
132 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
133 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000134 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000135 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000136 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000137 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000138
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000139 /** Version of above that appends the result to the fragment shader code instead.*/
140 void fsAppendTextureLookup(const TextureSampler&,
141 const char* coordName,
142 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000143
144
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000145 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
146 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
147 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
148 called. */
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000149 void fsAppendTextureLookupAndModulate(const char* modulation,
150 const TextureSampler&,
151 const char* coordName,
152 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000153
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000154 /** Emits a helper function outside of main() in the fragment shader. */
155 void fsEmitFunction(GrSLType returnType,
156 const char* name,
157 int argCnt,
158 const GrGLShaderVar* args,
159 const char* body,
160 SkString* outName);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000161
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000162 typedef uint8_t DstReadKey;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000163 typedef uint8_t FragPosKey;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000164
165 /** Returns a key for adding code to read the copy-of-dst color in service of effects that
166 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 +0000167 copy read at all (in which case this function should not be called). */
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000168 static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
169
bsalomon@google.comb5158812013-05-13 18:50:25 +0000170 /** Returns a key for reading the fragment location. This should only be called if there is an
171 effect that will requires the fragment position. If the fragment position is not required,
172 the key is 0. */
173 static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);
174
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000175 /** If texture swizzling is available using tex parameters then it is preferred over mangling
176 the generated shader code. This potentially allows greater reuse of cached shaders. */
177 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
178
bsalomon@google.com706f6682012-10-23 14:53:55 +0000179 /** 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 +0000180 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
181 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000182 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
183 it will refer to the final uniform name after return. Use the addUniformArray variant to add
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000184 an array of uniforms. */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000185 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
186 GrSLType type,
187 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000188 const char** outName = NULL) {
189 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
190 }
191 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
192 GrSLType type,
193 const char* name,
194 int arrayCount,
195 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000196
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000197 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle u) const {
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000198 return fUniformManager->getBuilderUniform(fUniforms, u).fVariable;
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000199 }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000200
201 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000202 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000203 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000204 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000205 return this->getUniformVariable(u).c_str();
206 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000207
bsalomon@google.com77af6802013-10-02 13:04:56 +0000208 /**
209 * This returns a variable name to access the 2D, perspective correct version of the coords in
210 * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a
211 * perspective divide into the fragment shader (xy / z) to convert them to 2D.
212 */
213 SkString ensureFSCoords2D(const TransformedCoordsArray&, int index);
214
bsalomon@google.com706f6682012-10-23 14:53:55 +0000215 /** Returns a variable name that represents the position of the fragment in the FS. The position
216 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
217 const char* fragmentPosition();
218
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000219 /** Returns the variable name that holds the color of the destination pixel. This may be NULL if
220 no effect advertised that it will read the destination. */
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000221 const char* dstColor();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000222
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000223 const GrGLContextInfo& ctxInfo() const;
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000224
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000225 /**
226 * Helper for begining and ending a block in the fragment code. TODO: Make GrGLShaderBuilder
227 * aware of all blocks and turn single \t's into the correct number of tabs (or spaces) so that
228 * our shaders print pretty without effect writers tracking indentation.
229 */
230 class FSBlock {
231 public:
232 FSBlock(GrGLShaderBuilder* builder) : fBuilder(builder) {
233 SkASSERT(NULL != builder);
234 fBuilder->fsCodeAppend("\t{\n");
235 }
236
237 ~FSBlock() {
238 fBuilder->fsCodeAppend("\t}\n");
239 }
240 private:
241 GrGLShaderBuilder* fBuilder;
242 };
243
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000244protected:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000245 GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000246
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000247 GrGpuGL* gpu() const { return fGpu; }
248
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000249 const GrGLProgramDesc& desc() const { return fDesc; }
250
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000251 /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
252 GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
253
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000254 // Helper for emitEffects().
255 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
256 const GrEffectStage* effectStages[],
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000257 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700258 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000259 GrGLSLExpr4* inOutFSColor);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000260
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000261 // Generates a name for a variable. The generated string will be name prefixed by the prefix
262 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
263 // generating stage code.
264 void nameVariable(SkString* out, char prefix, const char* name);
265
commit-bot@chromium.orgd328fb62014-02-14 00:03:38 +0000266 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000267
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000268 virtual void bindProgramLocations(GrGLuint programId) const;
269
bsalomon@google.com032b2212012-07-16 13:36:18 +0000270 void appendDecls(const VarArray&, SkString*) const;
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000271 void appendUniformDecls(ShaderVisibility, SkString*) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000272
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000273 const GenProgramOutput& getOutput() const { return fOutput; }
274
275 GenProgramOutput fOutput;
276
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000277private:
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +0000278 class CodeStage : SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000279 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000280 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
bsalomon@google.com504976e2013-05-09 13:45:02 +0000281
282 bool inStageCode() const {
283 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000284 return NULL != fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000285 }
286
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000287 const GrEffectStage* effectStage() const {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000288 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000289 return fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000290 }
291
292 int stageIndex() const {
skia.committer@gmail.com0f20a3f2013-05-10 07:01:04 +0000293 this->validate();
bsalomon@google.com504976e2013-05-09 13:45:02 +0000294 return fCurrentIndex;
295 }
296
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +0000297 class AutoStageRestore : SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000298 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000299 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000300 SkASSERT(NULL != codeStage);
bsalomon@google.com504976e2013-05-09 13:45:02 +0000301 fSavedIndex = codeStage->fCurrentIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000302 fSavedEffectStage = codeStage->fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000303
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000304 if (NULL == newStage) {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000305 codeStage->fCurrentIndex = -1;
306 } else {
307 codeStage->fCurrentIndex = codeStage->fNextIndex++;
308 }
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000309 codeStage->fEffectStage = newStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000310
311 fCodeStage = codeStage;
312 }
313 ~AutoStageRestore() {
314 fCodeStage->fCurrentIndex = fSavedIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000315 fCodeStage->fEffectStage = fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000316 }
317 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000318 CodeStage* fCodeStage;
319 int fSavedIndex;
320 const GrEffectStage* fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000321 };
322 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000323 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
324 int fNextIndex;
325 int fCurrentIndex;
326 const GrEffectStage* fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000327 } fCodeStage;
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000328
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000329 bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000330
bsalomon@google.com42eff162013-04-02 12:50:49 +0000331 /**
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000332 * The base class will emit the fragment code that precedes the per-effect code and then call
333 * this function. The subclass can use it to insert additional fragment code that should
334 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
335 *
336 * The subclass can modify the initial color or coverage
337 */
338 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
339
340 /**
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000341 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
bsalomon848faf02014-07-11 10:01:02 -0700342 * deleting it when finished. effectStages contains the effects to add. The effect key provider
343 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
344 * specifies the input color to the first stage and is updated to be the output color of the
345 * last stage. The handles to texture samplers for effectStage[i] are added to
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000346 * effectSamplerHandles[i].
347 */
348 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000349 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700350 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000351 GrGLSLExpr4* inOutFSColor) = 0;
352
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000353 /**
354 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
355 */
356 virtual void emitCodeAfterEffects() = 0;
357
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000358 /** Enables using the secondary color output and returns the name of the var in which it is
359 to be stored */
360 const char* enableSecondaryOutput();
361 /** Gets the name of the primary color output. */
362 const char* getColorOutputName() const;
363
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000364 /**
365 * Compiles all the shaders, links them into a program, and writes the program id to the output
366 * struct.
367 **/
368 bool finish();
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000369
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000370 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000371 * Features that should only be enabled by GrGLShaderBuilder itself.
372 */
373 enum GLSLPrivateFeature {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000374 kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
375 kEXTShaderFramebufferFetch_GLSLPrivateFeature,
376 kNVShaderFramebufferFetch_GLSLPrivateFeature,
bsalomon@google.com42eff162013-04-02 12:50:49 +0000377 };
378 bool enablePrivateFeature(GLSLPrivateFeature);
379
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000380 // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and
381 // track the enables separately for each shader.
bsalomon@google.com42eff162013-04-02 12:50:49 +0000382 void addFSFeature(uint32_t featureBit, const char* extensionName);
383
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000384 // Interpretation of DstReadKey when generating code
385 enum {
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000386 kNoDstRead_DstReadKey = 0,
387 kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
388 kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
389 kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000390 };
391
bsalomon@google.comb5158812013-05-13 18:50:25 +0000392 enum {
393 kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
394 kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
395 kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
396 };
397
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000398 const GrGLProgramDesc& fDesc;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000399 GrGpuGL* fGpu;
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000400 SkAutoTUnref<GrGLUniformManager> fUniformManager;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000401 uint32_t fFSFeaturesAddedMask;
402 SkString fFSFunctions;
403 SkString fFSExtensions;
404 VarArray fFSInputs;
405 VarArray fFSOutputs;
406 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000407
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000408 SkString fFSCode;
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000409
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000410 bool fSetupFragPosition;
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000411 bool fTopLeftFragPosRead;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000412
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000413 bool fHasCustomColorOutput;
414 bool fHasSecondaryOutput;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000415};
bsalomon@google.comb5158812013-05-13 18:50:25 +0000416
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000417////////////////////////////////////////////////////////////////////////////////
418
419class GrGLFullShaderBuilder : public GrGLShaderBuilder {
420public:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000421 GrGLFullShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000422
423 /**
424 * Called by GrGLEffects to add code to one of the shaders.
425 */
426 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
427 va_list args;
428 va_start(args, format);
commit-bot@chromium.orgce0e4ef2013-11-21 17:20:17 +0000429 fVSCode.appendVAList(format, args);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000430 va_end(args);
431 }
432
433 void vsCodeAppend(const char* str) { fVSCode.append(str); }
434
435 /** Add a vertex attribute to the current program that is passed in from the vertex data.
436 Returns false if the attribute was already there, true otherwise. */
437 bool addAttribute(GrSLType type, const char* name);
438
439 /** Add a varying variable to the current program to pass values between vertex and fragment
440 shaders. If the last two parameters are non-NULL, they are filled in with the name
441 generated. */
442 void addVarying(GrSLType type,
443 const char* name,
444 const char** vsOutName = NULL,
445 const char** fsInName = NULL);
446
447 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
448 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
449 */
450 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
451
452 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
453 as positionAttribute() or it may not be. It depends upon whether the rendering code
454 specified explicit local coords or not in the GrDrawState. */
455 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
456
457 /**
458 * Are explicit local coordinates provided as input to the vertex shader.
459 */
460 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
461
462 bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
463 const SkString* getEffectAttributeName(int attributeIndex) const;
464
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000465private:
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000466 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
467
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000468 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000469 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700470 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000471 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000472
473 virtual void emitCodeAfterEffects() SK_OVERRIDE;
474
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000475 virtual bool compileAndAttachShaders(GrGLuint programId,
476 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
477
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000478 virtual void bindProgramLocations(GrGLuint programId) const SK_OVERRIDE;
479
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000480 VarArray fVSAttrs;
481 VarArray fVSOutputs;
482 VarArray fGSInputs;
483 VarArray fGSOutputs;
484
485 SkString fVSCode;
486
487 struct AttributePair {
488 void set(int index, const SkString& name) {
489 fIndex = index; fName = name;
490 }
491 int fIndex;
492 SkString fName;
493 };
494 SkSTArray<10, AttributePair, true> fEffectAttributes;
495
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000496 GrGLShaderVar* fPositionVar;
497 GrGLShaderVar* fLocalCoordsVar;
498
499 typedef GrGLShaderBuilder INHERITED;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000500};
501
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000502////////////////////////////////////////////////////////////////////////////////
503
504class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
505public:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000506 GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000507
commit-bot@chromium.org8e919ad2013-10-21 14:48:23 +0000508 int addTexCoordSets(int count);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000509
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000510private:
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000511 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000512
513 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000514 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700515 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000516 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
517
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000518 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
519
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000520 typedef GrGLShaderBuilder INHERITED;
521};
522
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000523#endif