blob: 09f7eba511ce8c6877ecc7de0b2a2daecc34d864 [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;
43
44 // Handles for program uniforms (other than per-effect uniforms)
45 struct BuiltinUniformHandles {
46 UniformHandle fViewMatrixUni;
47 UniformHandle fRTAdjustmentUni;
48 UniformHandle fColorUni;
49 UniformHandle fCoverageUni;
50
51 // We use the render target height to provide a y-down frag coord when specifying
52 // origin_upper_left is not supported.
53 UniformHandle fRTHeightUni;
54
55 // Uniforms for computing texture coords to do the dst-copy lookup
56 UniformHandle fDstCopyTopLeftUni;
57 UniformHandle fDstCopyScaleUni;
58 UniformHandle fDstCopySamplerUni;
59 };
60
61 struct UniformInfo {
62 GrGLShaderVar fVariable;
63 uint32_t fVisibility;
64 GrGLint fLocation;
65 };
66
67 // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
68 // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
69 // name strings. Otherwise, we'd have to hand out copies.
70 typedef GrTAllocator<UniformInfo> UniformInfoArray;
71
72 /** Generates a shader program.
73 *
74 * The program implements what is specified in the stages given as input.
75 * After successful generation, the builder result objects are available
76 * to be used.
77 * @return true if generation was successful.
78 */
79 bool genProgram(const GrEffectStage* inColorStages[],
80 const GrEffectStage* inCoverageStages[]);
81
82 // Below are the results of the shader generation.
83
84 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
85 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
86 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
87 SkASSERT(fProgramID);
88 return fUniformHandles;
89 }
90 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
91 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
92 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
93 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
94
95 virtual ~GrGLProgramBuilder() {}
96
97 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
98 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
99 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
100 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
101 it will refer to the final uniform name after return. Use the addUniformArray variant to add
102 an array of uniforms. */
103 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
104 GrSLType type,
105 const char* name,
106 const char** outName = NULL) {
107 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
108 }
109 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
110 GrSLType type,
111 const char* name,
112 int arrayCount,
113 const char** outName = NULL);
114
115 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
116 return fUniforms[u.toShaderBuilderIndex()].fVariable;
117 }
118
119 /**
120 * Shortcut for getUniformVariable(u).c_str()
121 */
122 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
123 return this->getUniformVariable(u).c_str();
124 }
125
126 const GrGLContextInfo& ctxInfo() const;
127
128 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
129
130protected:
131 typedef GrTAllocator<GrGLShaderVar> VarArray;
132 GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
133
134 GrGpuGL* gpu() const { return fGpu; }
135
136 const GrGLProgramDesc& desc() const { return fDesc; }
137
138 // Helper for emitEffects().
139 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
140 const GrEffectStage* effectStages[],
141 int effectCnt,
142 const GrGLProgramDesc::EffectKeyProvider&,
143 GrGLSLExpr4* inOutFSColor);
144
145 // Generates a name for a variable. The generated string will be name prefixed by the prefix
146 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
147 // generating stage code.
148 void nameVariable(SkString* out, char prefix, const char* name);
149
150 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
151
152 virtual void bindProgramLocations(GrGLuint programId);
153 void resolveProgramLocations(GrGLuint programId);
154
155 void appendDecls(const VarArray&, SkString*) const;
156 void appendUniformDecls(ShaderVisibility, SkString*) const;
157
158 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
159 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
160 BuiltinUniformHandles fUniformHandles;
161 bool fFragOnly;
162 int fTexCoordSetCnt;
163 GrGLuint fProgramID;
164 GrGLFragmentShaderBuilder fFS;
165private:
166 class CodeStage : SkNoncopyable {
167 public:
168 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
169
170 bool inStageCode() const {
171 this->validate();
172 return NULL != fEffectStage;
173 }
174
175 const GrEffectStage* effectStage() const {
176 this->validate();
177 return fEffectStage;
178 }
179
180 int stageIndex() const {
181 this->validate();
182 return fCurrentIndex;
183 }
184
185 class AutoStageRestore : SkNoncopyable {
186 public:
187 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
188 SkASSERT(NULL != codeStage);
189 fSavedIndex = codeStage->fCurrentIndex;
190 fSavedEffectStage = codeStage->fEffectStage;
191
192 if (NULL == newStage) {
193 codeStage->fCurrentIndex = -1;
194 } else {
195 codeStage->fCurrentIndex = codeStage->fNextIndex++;
196 }
197 codeStage->fEffectStage = newStage;
198
199 fCodeStage = codeStage;
200 }
201 ~AutoStageRestore() {
202 fCodeStage->fCurrentIndex = fSavedIndex;
203 fCodeStage->fEffectStage = fSavedEffectStage;
204 }
205 private:
206 CodeStage* fCodeStage;
207 int fSavedIndex;
208 const GrEffectStage* fSavedEffectStage;
209 };
210 private:
211 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
212 int fNextIndex;
213 int fCurrentIndex;
214 const GrEffectStage* fEffectStage;
215 } fCodeStage;
216
217 /**
218 * The base class will emit the fragment code that precedes the per-effect code and then call
219 * this function. The subclass can use it to insert additional fragment code that should
220 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
221 *
222 * The subclass can modify the initial color or coverage
223 */
224 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
225
226 /**
227 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
228 * deleting it when finished. effectStages contains the effects to add. The effect key provider
229 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
230 * specifies the input color to the first stage and is updated to be the output color of the
231 * last stage. The handles to texture samplers for effectStage[i] are added to
232 * effectSamplerHandles[i].
233 */
234 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
235 int effectCnt,
236 const GrGLProgramDesc::EffectKeyProvider&,
237 GrGLSLExpr4* inOutFSColor) = 0;
238
239 /**
240 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
241 */
242 virtual void emitCodeAfterEffects() = 0;
243
244 /**
245 * Compiles all the shaders, links them into a program, and writes the program id to the output
246 * struct.
247 **/
248 bool finish();
249
250 const GrGLProgramDesc& fDesc;
251 GrGpuGL* fGpu;
252 UniformInfoArray fUniforms;
253
254 friend class GrGLShaderBuilder;
255 friend class GrGLVertexShaderBuilder;
256 friend class GrGLFragmentShaderBuilder;
257 friend class GrGLGeometryShaderBuilder;
258};
259
260////////////////////////////////////////////////////////////////////////////////
261
262class GrGLFullProgramBuilder : public GrGLProgramBuilder {
263public:
264 GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
265
266 /** Add a varying variable to the current program to pass values between vertex and fragment
267 shaders. If the last two parameters are non-NULL, they are filled in with the name
268 generated. */
269 void addVarying(GrSLType type,
270 const char* name,
271 const char** vsOutName = NULL,
272 const char** fsInName = NULL);
273
274 GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
275
276private:
277 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
278
279 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
280 int effectCnt,
281 const GrGLProgramDesc::EffectKeyProvider&,
282 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
283
284 virtual void emitCodeAfterEffects() SK_OVERRIDE;
285
286 virtual bool compileAndAttachShaders(GrGLuint programId,
287 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
288
289 virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
290
291 GrGLGeometryShaderBuilder fGS;
292 GrGLVertexShaderBuilder fVS;
293
294 typedef GrGLProgramBuilder INHERITED;
295};
296
297////////////////////////////////////////////////////////////////////////////////
298
299class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
300public:
301 GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
302
303 int addTexCoordSets(int count);
304
305private:
306 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
307
308 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
309 int effectCnt,
310 const GrGLProgramDesc::EffectKeyProvider&,
311 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
312
313 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
314
315 typedef GrGLProgramBuilder INHERITED;
316};
317
318#endif