blob: deb3708bd16e96e39824e0249309178f1ba35cca [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
2 * Copyright 2014 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 GrGLProgramBuilder_DEFINED
9#define GrGLProgramBuilder_DEFINED
10
11#include "GrAllocator.h"
12#include "GrBackendEffectFactory.h"
13#include "GrColor.h"
14#include "GrEffect.h"
15#include "GrGLFragmentShaderBuilder.h"
16#include "GrGLGeometryShaderBuilder.h"
17#include "GrGLVertexShaderBuilder.h"
18#include "SkTypes.h"
19#include "gl/GrGLProgramDesc.h"
20#include "gl/GrGLProgramEffects.h"
21#include "gl/GrGLSL.h"
22#include "gl/GrGLProgramDataManager.h"
23
24#include <stdarg.h>
25
26class GrGLContextInfo;
27class GrEffectStage;
28class GrGLProgramDesc;
29
30/**
31 Contains all the incremental state of a shader as it is being built,as well as helpers to
32 manipulate that state.
33*/
34class GrGLProgramBuilder {
35public:
36 enum ShaderVisibility {
37 kVertex_Visibility = 0x1,
38 kGeometry_Visibility = 0x2,
39 kFragment_Visibility = 0x4,
40 };
41
42 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
kkinnunenec56e452014-08-25 22:21:16 -070043 typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
joshualitt30ba4362014-08-21 20:18:45 -070044
45 // Handles for program uniforms (other than per-effect uniforms)
46 struct BuiltinUniformHandles {
47 UniformHandle fViewMatrixUni;
48 UniformHandle fRTAdjustmentUni;
49 UniformHandle fColorUni;
50 UniformHandle fCoverageUni;
51
52 // We use the render target height to provide a y-down frag coord when specifying
53 // origin_upper_left is not supported.
54 UniformHandle fRTHeightUni;
55
56 // Uniforms for computing texture coords to do the dst-copy lookup
57 UniformHandle fDstCopyTopLeftUni;
58 UniformHandle fDstCopyScaleUni;
59 UniformHandle fDstCopySamplerUni;
60 };
61
62 struct UniformInfo {
63 GrGLShaderVar fVariable;
64 uint32_t fVisibility;
65 GrGLint fLocation;
66 };
67
68 // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
69 // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
70 // name strings. Otherwise, we'd have to hand out copies.
71 typedef GrTAllocator<UniformInfo> UniformInfoArray;
72
kkinnunenec56e452014-08-25 22:21:16 -070073 struct SeparableVaryingInfo {
74 GrGLShaderVar fVariable;
75 GrGLint fLocation;
76 };
77
78 typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
79
joshualitt30ba4362014-08-21 20:18:45 -070080 /** Generates a shader program.
81 *
82 * The program implements what is specified in the stages given as input.
83 * After successful generation, the builder result objects are available
84 * to be used.
85 * @return true if generation was successful.
86 */
joshualittbd769d02014-09-04 08:56:46 -070087
88 bool genProgram(const GrEffectStage* inGeometryProcessor,
89 const GrEffectStage* inColorStages[],
joshualitt30ba4362014-08-21 20:18:45 -070090 const GrEffectStage* inCoverageStages[]);
91
joshualittbd769d02014-09-04 08:56:46 -070092 GrGLProgramEffects* getGeometryProcessor() const {
93 SkASSERT(fProgramID); return fGeometryProcessor.get();
94 }
joshualitt30ba4362014-08-21 20:18:45 -070095 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
96 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
97 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
98 SkASSERT(fProgramID);
99 return fUniformHandles;
100 }
101 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
102 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
103 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
104 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
kkinnunenec56e452014-08-25 22:21:16 -0700105 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
106 return fSeparableVaryingInfos;
107 }
joshualitt30ba4362014-08-21 20:18:45 -0700108
109 virtual ~GrGLProgramBuilder() {}
110
111 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
112 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
113 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
114 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
115 it will refer to the final uniform name after return. Use the addUniformArray variant to add
116 an array of uniforms. */
117 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
118 GrSLType type,
119 const char* name,
120 const char** outName = NULL) {
121 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
122 }
123 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
124 GrSLType type,
125 const char* name,
126 int arrayCount,
127 const char** outName = NULL);
128
129 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
130 return fUniforms[u.toShaderBuilderIndex()].fVariable;
131 }
132
133 /**
134 * Shortcut for getUniformVariable(u).c_str()
135 */
136 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
137 return this->getUniformVariable(u).c_str();
138 }
139
140 const GrGLContextInfo& ctxInfo() const;
141
142 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
kkinnunenec56e452014-08-25 22:21:16 -0700143 GrGpuGL* gpu() const { return fGpu; }
joshualitt30ba4362014-08-21 20:18:45 -0700144
145protected:
146 typedef GrTAllocator<GrGLShaderVar> VarArray;
147 GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
148
joshualitt30ba4362014-08-21 20:18:45 -0700149 const GrGLProgramDesc& desc() const { return fDesc; }
150
151 // Helper for emitEffects().
152 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
153 const GrEffectStage* effectStages[],
154 int effectCnt,
155 const GrGLProgramDesc::EffectKeyProvider&,
156 GrGLSLExpr4* inOutFSColor);
157
158 // Generates a name for a variable. The generated string will be name prefixed by the prefix
159 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
160 // generating stage code.
161 void nameVariable(SkString* out, char prefix, const char* name);
162
163 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
164
165 virtual void bindProgramLocations(GrGLuint programId);
166 void resolveProgramLocations(GrGLuint programId);
167
168 void appendDecls(const VarArray&, SkString*) const;
169 void appendUniformDecls(ShaderVisibility, SkString*) const;
170
joshualittbd769d02014-09-04 08:56:46 -0700171 SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
joshualitt30ba4362014-08-21 20:18:45 -0700172 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
173 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
174 BuiltinUniformHandles fUniformHandles;
175 bool fFragOnly;
176 int fTexCoordSetCnt;
177 GrGLuint fProgramID;
178 GrGLFragmentShaderBuilder fFS;
kkinnunenec56e452014-08-25 22:21:16 -0700179 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualittbd769d02014-09-04 08:56:46 -0700180
joshualitt30ba4362014-08-21 20:18:45 -0700181 class CodeStage : SkNoncopyable {
182 public:
183 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
184
185 bool inStageCode() const {
186 this->validate();
187 return NULL != fEffectStage;
188 }
189
190 const GrEffectStage* effectStage() const {
191 this->validate();
192 return fEffectStage;
193 }
194
195 int stageIndex() const {
196 this->validate();
197 return fCurrentIndex;
198 }
199
200 class AutoStageRestore : SkNoncopyable {
201 public:
202 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
203 SkASSERT(NULL != codeStage);
204 fSavedIndex = codeStage->fCurrentIndex;
205 fSavedEffectStage = codeStage->fEffectStage;
206
207 if (NULL == newStage) {
208 codeStage->fCurrentIndex = -1;
209 } else {
210 codeStage->fCurrentIndex = codeStage->fNextIndex++;
211 }
212 codeStage->fEffectStage = newStage;
213
214 fCodeStage = codeStage;
215 }
216 ~AutoStageRestore() {
217 fCodeStage->fCurrentIndex = fSavedIndex;
218 fCodeStage->fEffectStage = fSavedEffectStage;
219 }
220 private:
221 CodeStage* fCodeStage;
222 int fSavedIndex;
223 const GrEffectStage* fSavedEffectStage;
224 };
225 private:
226 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
227 int fNextIndex;
228 int fCurrentIndex;
229 const GrEffectStage* fEffectStage;
230 } fCodeStage;
joshualittbd769d02014-09-04 08:56:46 -0700231private:
joshualitt30ba4362014-08-21 20:18:45 -0700232
233 /**
234 * The base class will emit the fragment code that precedes the per-effect code and then call
235 * this function. The subclass can use it to insert additional fragment code that should
236 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
237 *
238 * The subclass can modify the initial color or coverage
239 */
joshualittbd769d02014-09-04 08:56:46 -0700240 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
241 GrGLSLExpr4* coverage) = 0;
242
243 /*
244 * Full shader builder needs to emit code after the color stages and before the coverage stages
245 */
246 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
247 GrGLSLExpr4* coverage) = 0;
joshualitt30ba4362014-08-21 20:18:45 -0700248
249 /**
250 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
251 * deleting it when finished. effectStages contains the effects to add. The effect key provider
252 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
253 * specifies the input color to the first stage and is updated to be the output color of the
254 * last stage. The handles to texture samplers for effectStage[i] are added to
255 * effectSamplerHandles[i].
256 */
257 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
258 int effectCnt,
259 const GrGLProgramDesc::EffectKeyProvider&,
260 GrGLSLExpr4* inOutFSColor) = 0;
261
262 /**
263 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
264 */
265 virtual void emitCodeAfterEffects() = 0;
266
267 /**
268 * Compiles all the shaders, links them into a program, and writes the program id to the output
269 * struct.
270 **/
271 bool finish();
272
273 const GrGLProgramDesc& fDesc;
274 GrGpuGL* fGpu;
275 UniformInfoArray fUniforms;
276
277 friend class GrGLShaderBuilder;
278 friend class GrGLVertexShaderBuilder;
279 friend class GrGLFragmentShaderBuilder;
280 friend class GrGLGeometryShaderBuilder;
281};
282
283////////////////////////////////////////////////////////////////////////////////
284
285class GrGLFullProgramBuilder : public GrGLProgramBuilder {
286public:
287 GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
288
289 /** Add a varying variable to the current program to pass values between vertex and fragment
290 shaders. If the last two parameters are non-NULL, they are filled in with the name
291 generated. */
292 void addVarying(GrSLType type,
293 const char* name,
294 const char** vsOutName = NULL,
egdaniel6db91282014-09-02 08:02:38 -0700295 const char** fsInName = NULL,
296 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
joshualitt30ba4362014-08-21 20:18:45 -0700297
kkinnunenec56e452014-08-25 22:21:16 -0700298 /** Add a separable varying input variable to the current program.
299 * A separable varying (fragment shader input) is a varying that can be used also when vertex
300 * shaders are not used. With a vertex shader, the operation is same as with other
301 * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
302 * populate the variable. The APIs can refer to the variable through the returned handle.
303 */
304 VaryingHandle addSeparableVarying(GrSLType type,
305 const char* name,
306 const char** vsOutName,
307 const char** fsInName);
308
joshualitt30ba4362014-08-21 20:18:45 -0700309 GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
310
311private:
joshualittbd769d02014-09-04 08:56:46 -0700312 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
313 GrGLSLExpr4* coverage) SK_OVERRIDE;
314
315 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
316 GrGLSLExpr4* coverage) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700317
318 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
319 int effectCnt,
320 const GrGLProgramDesc::EffectKeyProvider&,
321 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
322
joshualittbd769d02014-09-04 08:56:46 -0700323 /*
324 * These functions are temporary and will eventually operate not on effects but on
325 * geometry processors
326 */
327 void createAndEmitEffect(GrGLProgramEffectsBuilder*,
328 const GrEffectStage* effectStage,
329 const GrGLProgramDesc::EffectKeyProvider&,
330 GrGLSLExpr4* inOutFSColor);
331
332 GrGLProgramEffects* createAndEmitEffect(const GrEffectStage* geometryProcessor,
333 const GrGLProgramDesc::EffectKeyProvider&,
334 GrGLSLExpr4* inOutFSColor);
335
joshualitt30ba4362014-08-21 20:18:45 -0700336 virtual void emitCodeAfterEffects() SK_OVERRIDE;
337
338 virtual bool compileAndAttachShaders(GrGLuint programId,
339 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
340
341 virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
342
343 GrGLGeometryShaderBuilder fGS;
344 GrGLVertexShaderBuilder fVS;
345
346 typedef GrGLProgramBuilder INHERITED;
347};
348
349////////////////////////////////////////////////////////////////////////////////
350
351class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
352public:
353 GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
354
355 int addTexCoordSets(int count);
356
357private:
joshualittbd769d02014-09-04 08:56:46 -0700358 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
359 GrGLSLExpr4* coverage) SK_OVERRIDE {}
360
361 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
362 GrGLSLExpr4* coverage) SK_OVERRIDE {
363 SkASSERT(NULL == geometryProcessor);
364 }
joshualitt30ba4362014-08-21 20:18:45 -0700365
366 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
367 int effectCnt,
368 const GrGLProgramDesc::EffectKeyProvider&,
369 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
370
371 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
372
373 typedef GrGLProgramBuilder INHERITED;
374};
375
376#endif