blob: 73e9a8f8032fe861691f32474b881de377f7621a [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;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000034 typedef GrGLProgramEffects::TextureSampler TextureSampler;
35 typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000036 typedef GrGLUniformManager::BuilderUniform BuilderUniform;
bsalomon@google.comf06df1b2012-09-06 20:22:31 +000037
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +000038 enum ShaderVisibility {
39 kVertex_Visibility = 0x1,
40 kGeometry_Visibility = 0x2,
41 kFragment_Visibility = 0x4,
bsalomon@google.comeb715c82012-07-11 15:03:31 +000042 };
43
commit-bot@chromium.org03652612014-05-29 19:09:52 +000044 typedef GrGLUniformManager::UniformHandle UniformHandle;
45
46 // Handles for program uniforms (other than per-effect uniforms)
47 struct UniformHandles {
48 UniformHandle fViewMatrixUni;
49 UniformHandle fRTAdjustmentUni;
50 UniformHandle fColorUni;
51 UniformHandle fCoverageUni;
52
53 // We use the render target height to provide a y-down frag coord when specifying
54 // origin_upper_left is not supported.
55 UniformHandle fRTHeightUni;
56
57 // Uniforms for computing texture coords to do the dst-copy lookup
58 UniformHandle fDstCopyTopLeftUni;
59 UniformHandle fDstCopyScaleUni;
60 UniformHandle fDstCopySamplerUni;
61 };
62
63 struct GenProgramOutput {
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +000064 GenProgramOutput()
65 : fColorEffects(NULL)
66 , fCoverageEffects(NULL)
67 , fHasVertexShader(false)
68 , fTexCoordSetCnt(0)
69 , fProgramID(0) {}
70
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000071 GenProgramOutput(const GenProgramOutput& other) {
72 *this = other;
73 }
74
75 GenProgramOutput& operator=(const GenProgramOutput& other) {
76 fColorEffects.reset(SkRef(other.fColorEffects.get()));
77 fCoverageEffects.reset(SkRef(other.fCoverageEffects.get()));
78 fUniformHandles = other.fUniformHandles;
79 fHasVertexShader = other.fHasVertexShader;
80 fTexCoordSetCnt = other.fTexCoordSetCnt;
81 fProgramID = other.fProgramID;
82 return *this;
83 }
84
85 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
86 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
87 UniformHandles fUniformHandles;
88 bool fHasVertexShader;
89 int fTexCoordSetCnt;
90 GrGLuint fProgramID;
commit-bot@chromium.org03652612014-05-29 19:09:52 +000091 };
92
93 static bool GenProgram(GrGpuGL* gpu,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +000094 GrGLUniformManager* uman,
commit-bot@chromium.org03652612014-05-29 19:09:52 +000095 const GrGLProgramDesc& desc,
96 const GrEffectStage* inColorStages[],
97 const GrEffectStage* inCoverageStages[],
98 GenProgramOutput* output);
99
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000100 virtual ~GrGLShaderBuilder() {}
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000101
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000102 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000103 * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
104 * if code is added that uses one of these features without calling enableFeature()
105 */
106 enum GLSLFeature {
107 kStandardDerivatives_GLSLFeature = 0,
108
109 kLastGLSLFeature = kStandardDerivatives_GLSLFeature
110 };
111
112 /**
113 * If the feature is supported then true is returned and any necessary #extension declarations
114 * are added to the shaders. If the feature is not supported then false will be returned.
115 */
116 bool enableFeature(GLSLFeature);
117
118 /**
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000119 * Called by GrGLEffects to add code the fragment shader.
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000120 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000121 void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
122 va_list args;
123 va_start(args, format);
commit-bot@chromium.orgce0e4ef2013-11-21 17:20:17 +0000124 fFSCode.appendVAList(format, args);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000125 va_end(args);
126 }
127
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000128 void fsCodeAppend(const char* str) { fFSCode.append(str); }
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000129
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000130 /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
131 Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
132 order of the result depends on the GrTextureAccess associated with the TextureSampler. */
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000133 void appendTextureLookup(SkString* out,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000134 const TextureSampler&,
bsalomon@google.comdbe49f72012-11-05 16:36:02 +0000135 const char* coordName,
bsalomon@google.com868a8e72012-08-30 19:11:34 +0000136 GrSLType coordType = kVec2f_GrSLType) const;
tomhudson@google.com52598142012-05-24 17:44:30 +0000137
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000138 /** Version of above that appends the result to the fragment shader code instead.*/
139 void fsAppendTextureLookup(const TextureSampler&,
140 const char* coordName,
141 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000142
143
bsalomon@google.com2d8edaf2012-09-07 14:47:31 +0000144 /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
145 always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
146 float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
147 called. */
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000148 void fsAppendTextureLookupAndModulate(const char* modulation,
149 const TextureSampler&,
150 const char* coordName,
151 GrSLType coordType = kVec2f_GrSLType);
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +0000152
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000153 /** Emits a helper function outside of main() in the fragment shader. */
154 void fsEmitFunction(GrSLType returnType,
155 const char* name,
156 int argCnt,
157 const GrGLShaderVar* args,
158 const char* body,
159 SkString* outName);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000160
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000161 typedef uint8_t DstReadKey;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000162 typedef uint8_t FragPosKey;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000163
164 /** Returns a key for adding code to read the copy-of-dst color in service of effects that
165 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 +0000166 copy read at all (in which case this function should not be called). */
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000167 static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
168
bsalomon@google.comb5158812013-05-13 18:50:25 +0000169 /** Returns a key for reading the fragment location. This should only be called if there is an
170 effect that will requires the fragment position. If the fragment position is not required,
171 the key is 0. */
172 static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);
173
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000174 /** If texture swizzling is available using tex parameters then it is preferred over mangling
175 the generated shader code. This potentially allows greater reuse of cached shaders. */
176 static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
177
bsalomon@google.com706f6682012-10-23 14:53:55 +0000178 /** 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 +0000179 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
180 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000181 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
182 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 +0000183 an array of uniforms. */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000184 GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
185 GrSLType type,
186 const char* name,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000187 const char** outName = NULL) {
188 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
189 }
190 GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
191 GrSLType type,
192 const char* name,
193 int arrayCount,
194 const char** outName = NULL);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000195
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000196 const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle u) const {
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000197 return fUniformManager->getBuilderUniform(fUniforms, u).fVariable;
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000198 }
bsalomon@google.com032b2212012-07-16 13:36:18 +0000199
200 /**
bsalomon@google.com706f6682012-10-23 14:53:55 +0000201 * Shortcut for getUniformVariable(u).c_str()
bsalomon@google.com032b2212012-07-16 13:36:18 +0000202 */
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000203 const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +0000204 return this->getUniformVariable(u).c_str();
205 }
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000206
bsalomon@google.com77af6802013-10-02 13:04:56 +0000207 /**
208 * This returns a variable name to access the 2D, perspective correct version of the coords in
209 * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a
210 * perspective divide into the fragment shader (xy / z) to convert them to 2D.
211 */
212 SkString ensureFSCoords2D(const TransformedCoordsArray&, int index);
213
bsalomon@google.com706f6682012-10-23 14:53:55 +0000214 /** Returns a variable name that represents the position of the fragment in the FS. The position
215 is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
216 const char* fragmentPosition();
217
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000218 /** Returns the variable name that holds the color of the destination pixel. This may be NULL if
219 no effect advertised that it will read the destination. */
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000220 const char* dstColor();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000221
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000222 const GrGLContextInfo& ctxInfo() const;
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000223
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000224 /**
225 * Helper for begining and ending a block in the fragment code. TODO: Make GrGLShaderBuilder
226 * aware of all blocks and turn single \t's into the correct number of tabs (or spaces) so that
227 * our shaders print pretty without effect writers tracking indentation.
228 */
229 class FSBlock {
230 public:
231 FSBlock(GrGLShaderBuilder* builder) : fBuilder(builder) {
232 SkASSERT(NULL != builder);
233 fBuilder->fsCodeAppend("\t{\n");
234 }
235
236 ~FSBlock() {
237 fBuilder->fsCodeAppend("\t}\n");
238 }
239 private:
240 GrGLShaderBuilder* fBuilder;
241 };
242
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000243protected:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000244 GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000245
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000246 GrGpuGL* gpu() const { return fGpu; }
247
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000248 const GrGLProgramDesc& desc() const { return fDesc; }
249
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000250 /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
251 GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
252
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000253 // Helper for emitEffects().
254 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
255 const GrEffectStage* effectStages[],
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000256 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700257 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000258 GrGLSLExpr4* inOutFSColor);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000259
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000260 // Generates a name for a variable. The generated string will be name prefixed by the prefix
261 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
262 // generating stage code.
263 void nameVariable(SkString* out, char prefix, const char* name);
264
commit-bot@chromium.orgd328fb62014-02-14 00:03:38 +0000265 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000266
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000267 virtual void bindProgramLocations(GrGLuint programId) const;
268
bsalomon@google.com032b2212012-07-16 13:36:18 +0000269 void appendDecls(const VarArray&, SkString*) const;
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000270 void appendUniformDecls(ShaderVisibility, SkString*) const;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000271
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000272 const GenProgramOutput& getOutput() const { return fOutput; }
273
274 GenProgramOutput fOutput;
275
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000276private:
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +0000277 class CodeStage : SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000278 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000279 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
bsalomon@google.com504976e2013-05-09 13:45:02 +0000280
281 bool inStageCode() const {
282 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000283 return NULL != fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000284 }
285
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000286 const GrEffectStage* effectStage() const {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000287 this->validate();
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000288 return fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000289 }
290
291 int stageIndex() const {
skia.committer@gmail.com0f20a3f2013-05-10 07:01:04 +0000292 this->validate();
bsalomon@google.com504976e2013-05-09 13:45:02 +0000293 return fCurrentIndex;
294 }
295
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +0000296 class AutoStageRestore : SkNoncopyable {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000297 public:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000298 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000299 SkASSERT(NULL != codeStage);
bsalomon@google.com504976e2013-05-09 13:45:02 +0000300 fSavedIndex = codeStage->fCurrentIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000301 fSavedEffectStage = codeStage->fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000302
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000303 if (NULL == newStage) {
bsalomon@google.com504976e2013-05-09 13:45:02 +0000304 codeStage->fCurrentIndex = -1;
305 } else {
306 codeStage->fCurrentIndex = codeStage->fNextIndex++;
307 }
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000308 codeStage->fEffectStage = newStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000309
310 fCodeStage = codeStage;
311 }
312 ~AutoStageRestore() {
313 fCodeStage->fCurrentIndex = fSavedIndex;
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000314 fCodeStage->fEffectStage = fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000315 }
316 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000317 CodeStage* fCodeStage;
318 int fSavedIndex;
319 const GrEffectStage* fSavedEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000320 };
321 private:
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000322 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
323 int fNextIndex;
324 int fCurrentIndex;
325 const GrEffectStage* fEffectStage;
bsalomon@google.com504976e2013-05-09 13:45:02 +0000326 } fCodeStage;
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000327
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000328 bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000329
bsalomon@google.com42eff162013-04-02 12:50:49 +0000330 /**
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000331 * The base class will emit the fragment code that precedes the per-effect code and then call
332 * this function. The subclass can use it to insert additional fragment code that should
333 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
334 *
335 * The subclass can modify the initial color or coverage
336 */
337 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
338
339 /**
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000340 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
bsalomon848faf02014-07-11 10:01:02 -0700341 * deleting it when finished. effectStages contains the effects to add. The effect key provider
342 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
343 * specifies the input color to the first stage and is updated to be the output color of the
344 * last stage. The handles to texture samplers for effectStage[i] are added to
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000345 * effectSamplerHandles[i].
346 */
347 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000348 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700349 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000350 GrGLSLExpr4* inOutFSColor) = 0;
351
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000352 /**
353 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
354 */
355 virtual void emitCodeAfterEffects() = 0;
356
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000357 /** Enables using the secondary color output and returns the name of the var in which it is
358 to be stored */
359 const char* enableSecondaryOutput();
360 /** Gets the name of the primary color output. */
361 const char* getColorOutputName() const;
362
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000363 /**
364 * Compiles all the shaders, links them into a program, and writes the program id to the output
365 * struct.
366 **/
367 bool finish();
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000368
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000369 /**
bsalomon@google.com42eff162013-04-02 12:50:49 +0000370 * Features that should only be enabled by GrGLShaderBuilder itself.
371 */
372 enum GLSLPrivateFeature {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000373 kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
374 kEXTShaderFramebufferFetch_GLSLPrivateFeature,
375 kNVShaderFramebufferFetch_GLSLPrivateFeature,
bsalomon@google.com42eff162013-04-02 12:50:49 +0000376 };
377 bool enablePrivateFeature(GLSLPrivateFeature);
378
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000379 // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and
380 // track the enables separately for each shader.
bsalomon@google.com42eff162013-04-02 12:50:49 +0000381 void addFSFeature(uint32_t featureBit, const char* extensionName);
382
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000383 // Interpretation of DstReadKey when generating code
384 enum {
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000385 kNoDstRead_DstReadKey = 0,
386 kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
387 kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
388 kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000389 };
390
bsalomon@google.comb5158812013-05-13 18:50:25 +0000391 enum {
392 kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
393 kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
394 kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
395 };
396
commit-bot@chromium.org03652612014-05-29 19:09:52 +0000397 const GrGLProgramDesc& fDesc;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000398 GrGpuGL* fGpu;
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000399 SkAutoTUnref<GrGLUniformManager> fUniformManager;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000400 uint32_t fFSFeaturesAddedMask;
401 SkString fFSFunctions;
402 SkString fFSExtensions;
403 VarArray fFSInputs;
404 VarArray fFSOutputs;
405 GrGLUniformManager::BuilderUniformArray fUniforms;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000406
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000407 SkString fFSCode;
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000408
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000409 bool fSetupFragPosition;
commit-bot@chromium.orgfacad132014-05-29 22:20:03 +0000410 bool fTopLeftFragPosRead;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000411
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000412 bool fHasCustomColorOutput;
413 bool fHasSecondaryOutput;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000414};
bsalomon@google.comb5158812013-05-13 18:50:25 +0000415
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000416////////////////////////////////////////////////////////////////////////////////
417
418class GrGLFullShaderBuilder : public GrGLShaderBuilder {
419public:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000420 GrGLFullShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000421
422 /**
423 * Called by GrGLEffects to add code to one of the shaders.
424 */
425 void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
426 va_list args;
427 va_start(args, format);
commit-bot@chromium.orgce0e4ef2013-11-21 17:20:17 +0000428 fVSCode.appendVAList(format, args);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000429 va_end(args);
430 }
431
432 void vsCodeAppend(const char* str) { fVSCode.append(str); }
433
434 /** Add a vertex attribute to the current program that is passed in from the vertex data.
435 Returns false if the attribute was already there, true otherwise. */
436 bool addAttribute(GrSLType type, const char* name);
437
438 /** Add a varying variable to the current program to pass values between vertex and fragment
439 shaders. If the last two parameters are non-NULL, they are filled in with the name
440 generated. */
441 void addVarying(GrSLType type,
442 const char* name,
443 const char** vsOutName = NULL,
444 const char** fsInName = NULL);
445
446 /** Returns a vertex attribute that represents the vertex position in the VS. This is the
447 pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
448 */
449 const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
450
451 /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
452 as positionAttribute() or it may not be. It depends upon whether the rendering code
453 specified explicit local coords or not in the GrDrawState. */
454 const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
455
456 /**
457 * Are explicit local coordinates provided as input to the vertex shader.
458 */
459 bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
460
461 bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
462 const SkString* getEffectAttributeName(int attributeIndex) const;
463
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000464private:
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000465 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
466
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000467 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000468 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700469 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000470 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000471
472 virtual void emitCodeAfterEffects() SK_OVERRIDE;
473
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000474 virtual bool compileAndAttachShaders(GrGLuint programId,
475 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
476
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000477 virtual void bindProgramLocations(GrGLuint programId) const SK_OVERRIDE;
478
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000479 VarArray fVSAttrs;
480 VarArray fVSOutputs;
481 VarArray fGSInputs;
482 VarArray fGSOutputs;
483
484 SkString fVSCode;
485
486 struct AttributePair {
487 void set(int index, const SkString& name) {
488 fIndex = index; fName = name;
489 }
490 int fIndex;
491 SkString fName;
492 };
493 SkSTArray<10, AttributePair, true> fEffectAttributes;
494
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000495 GrGLShaderVar* fPositionVar;
496 GrGLShaderVar* fLocalCoordsVar;
497
498 typedef GrGLShaderBuilder INHERITED;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000499};
500
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000501////////////////////////////////////////////////////////////////////////////////
502
503class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
504public:
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000505 GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000506
commit-bot@chromium.org8e919ad2013-10-21 14:48:23 +0000507 int addTexCoordSets(int count);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000508
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000509private:
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000510 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000511
512 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000513 int effectCnt,
bsalomon848faf02014-07-11 10:01:02 -0700514 const GrGLProgramDesc::EffectKeyProvider&,
commit-bot@chromium.org6eac42e2014-05-29 21:29:51 +0000515 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
516
commit-bot@chromium.orgf7f9aa02014-05-30 15:14:56 +0000517 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
518
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000519 typedef GrGLShaderBuilder INHERITED;
520};
521
tomhudson@google.comf9ad8862012-05-11 20:38:48 +0000522#endif