blob: 9f8defb6dd5f11c3a57524e641bbe57de4d71132 [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().
joshualitt23e280d2014-09-18 12:26:38 -0700152 void createAndEmitEffects(const GrEffectStage* effectStages[],
joshualitt30ba4362014-08-21 20:18:45 -0700153 int effectCnt,
154 const GrGLProgramDesc::EffectKeyProvider&,
155 GrGLSLExpr4* inOutFSColor);
156
joshualitt23e280d2014-09-18 12:26:38 -0700157 /*
158 * A helper function called to emit the geometry processor as well as individual coverage
159 * and color stages. this will call into subclasses emit effect
160 */
161 void emitEffect(const GrEffectStage& effectStage,
162 int effectIndex,
163 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
164 GrGLSLExpr4* inColor,
165 GrGLSLExpr4* outColor);
166
167 /**
168 * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
169 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
170 * lookups to their code. This method is only meant to be called during the construction phase.
171 */
172 void emitSamplers(const GrEffect& effect, GrGLEffect::TextureSamplerArray* outSamplers);
173
joshualitt30ba4362014-08-21 20:18:45 -0700174 // Generates a name for a variable. The generated string will be name prefixed by the prefix
175 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
176 // generating stage code.
177 void nameVariable(SkString* out, char prefix, const char* name);
178
179 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
180
181 virtual void bindProgramLocations(GrGLuint programId);
182 void resolveProgramLocations(GrGLuint programId);
183
184 void appendDecls(const VarArray&, SkString*) const;
185 void appendUniformDecls(ShaderVisibility, SkString*) const;
186
joshualitt30ba4362014-08-21 20:18:45 -0700187 class CodeStage : SkNoncopyable {
188 public:
189 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
190
191 bool inStageCode() const {
192 this->validate();
bsalomon49f085d2014-09-05 13:34:00 -0700193 return SkToBool(fEffectStage);
joshualitt30ba4362014-08-21 20:18:45 -0700194 }
195
196 const GrEffectStage* effectStage() const {
197 this->validate();
198 return fEffectStage;
199 }
200
201 int stageIndex() const {
202 this->validate();
203 return fCurrentIndex;
204 }
205
206 class AutoStageRestore : SkNoncopyable {
207 public:
208 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
bsalomon49f085d2014-09-05 13:34:00 -0700209 SkASSERT(codeStage);
joshualitt30ba4362014-08-21 20:18:45 -0700210 fSavedIndex = codeStage->fCurrentIndex;
211 fSavedEffectStage = codeStage->fEffectStage;
212
213 if (NULL == newStage) {
214 codeStage->fCurrentIndex = -1;
215 } else {
216 codeStage->fCurrentIndex = codeStage->fNextIndex++;
217 }
218 codeStage->fEffectStage = newStage;
219
220 fCodeStage = codeStage;
221 }
222 ~AutoStageRestore() {
223 fCodeStage->fCurrentIndex = fSavedIndex;
224 fCodeStage->fEffectStage = fSavedEffectStage;
225 }
226 private:
227 CodeStage* fCodeStage;
228 int fSavedIndex;
229 const GrEffectStage* fSavedEffectStage;
230 };
231 private:
232 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
233 int fNextIndex;
234 int fCurrentIndex;
235 const GrEffectStage* fEffectStage;
joshualitt23e280d2014-09-18 12:26:38 -0700236 };
237
238 CodeStage fCodeStage;
239 SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
240 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
241 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
242 BuiltinUniformHandles fUniformHandles;
243 bool fFragOnly;
244 int fTexCoordSetCnt;
245 GrGLuint fProgramID;
246 GrGLFragmentShaderBuilder fFS;
247 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualitt249af152014-09-15 11:41:13 -0700248
joshualittbd769d02014-09-04 08:56:46 -0700249private:
joshualitt23e280d2014-09-18 12:26:38 -0700250 virtual void createAndEmitEffects(const GrEffectStage* geometryProcessor,
251 const GrEffectStage* colorStages[],
252 const GrEffectStage* coverageStages[],
253 GrGLSLExpr4* inputColor,
254 GrGLSLExpr4* inputCoverage) = 0;
255 /*
256 * Subclasses override emitEffect below to emit data and code for a specific single effect
joshualitt30ba4362014-08-21 20:18:45 -0700257 */
joshualitt23e280d2014-09-18 12:26:38 -0700258 virtual void emitEffect(const GrEffectStage&,
259 const GrEffectKey&,
260 const char* outColor,
261 const char* inColor,
262 int stageIndex) = 0;
joshualittbd769d02014-09-04 08:56:46 -0700263
264 /*
joshualitt23e280d2014-09-18 12:26:38 -0700265 * Because we have fragment only builders, and those builders need to implement a subclass
266 * of program effects, we have to have base classes overload the program effects here
joshualittbd769d02014-09-04 08:56:46 -0700267 */
joshualitt23e280d2014-09-18 12:26:38 -0700268 virtual GrGLProgramEffects* getProgramEffects() = 0;
joshualitt30ba4362014-08-21 20:18:45 -0700269
270 /**
271 * Compiles all the shaders, links them into a program, and writes the program id to the output
272 * struct.
273 **/
274 bool finish();
275
276 const GrGLProgramDesc& fDesc;
277 GrGpuGL* fGpu;
278 UniformInfoArray fUniforms;
279
280 friend class GrGLShaderBuilder;
281 friend class GrGLVertexShaderBuilder;
282 friend class GrGLFragmentShaderBuilder;
283 friend class GrGLGeometryShaderBuilder;
284};
285
joshualitt30ba4362014-08-21 20:18:45 -0700286#endif