blob: c51dcbba9f3923ac273a7f9c14a019b6bf1484da [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
joshualitt30ba4362014-08-21 20:18:45 -070011#include "GrGLFragmentShaderBuilder.h"
12#include "GrGLGeometryShaderBuilder.h"
13#include "GrGLVertexShaderBuilder.h"
joshualittfe1233c2014-10-07 12:16:35 -070014#include "../GrGLProgramDataManager.h"
15#include "../GrGLUniformHandle.h"
joshualitt30ba4362014-08-21 20:18:45 -070016
joshualittfe1233c2014-10-07 12:16:35 -070017class GrGLInstalledProcessors;
joshualitt30ba4362014-08-21 20:18:45 -070018
joshualittfe1233c2014-10-07 12:16:35 -070019/*
20 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
21 * NO data members because it is used in multiple interface inheritance.
22 * Heirarchy:
23 * GrGLUniformBuilder
24 * / \
25 * GrGLFPBuilder GrGLGPBuilder
26 * \ /
27 * GrGLProgramBuilder(internal use only)
28 */
29class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070030public:
31 enum ShaderVisibility {
32 kVertex_Visibility = 0x1,
33 kGeometry_Visibility = 0x2,
34 kFragment_Visibility = 0x4,
35 };
36
joshualittfe1233c2014-10-07 12:16:35 -070037 virtual ~GrGLUniformBuilder() {}
38
joshualitt30ba4362014-08-21 20:18:45 -070039 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualittfe1233c2014-10-07 12:16:35 -070040
41 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
42 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
43 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
44 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
45 it will refer to the final uniform name after return. Use the addUniformArray variant to add
46 an array of uniforms. */
47 virtual UniformHandle addUniform(uint32_t visibility,
48 GrSLType type,
49 const char* name,
50 const char** outName = NULL) = 0;
51 virtual UniformHandle addUniformArray(uint32_t visibility,
52 GrSLType type,
53 const char* name,
54 int arrayCount,
55 const char** outName = NULL) = 0;
56
57 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
58
59 /**
60 * Shortcut for getUniformVariable(u).c_str()
61 */
62 virtual const char* getUniformCStr(UniformHandle u) const = 0;
63
64 virtual const GrGLContextInfo& ctxInfo() const = 0;
65
66 virtual GrGpuGL* gpu() const = 0;
67
68 /*
69 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
70 */
71};
72
73/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
74class GrGLGPBuilder : public virtual GrGLUniformBuilder {
75public:
76 virtual void addVarying(GrSLType type,
77 const char* name,
78 const char** vsOutName = NULL,
79 const char** fsInName = NULL,
80 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
81
82 // TODO rename getFragmentBuilder
83 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
84 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
85
86 /*
87 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
88 */
89};
90
91/* a specializations for FPs. Lets the user add uniforms and FS code */
92class GrGLFPBuilder : public virtual GrGLUniformBuilder {
93public:
94 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
95
96 /*
97 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
98 */
99};
100
101/*
102 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
103 * are pure virtual with no data members. This is the base class for program building.
104 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
105 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
106 * respective builders
107*/
108class GrGLProgramBuilder : public GrGLGPBuilder,
109 public GrGLFPBuilder {
110public:
111 /** Generates a shader program.
112 *
113 * The program implements what is specified in the stages given as input.
114 * After successful generation, the builder result objects are available
115 * to be used.
116 * @return true if generation was successful.
117 */
118 static GrGLProgram* CreateProgram(const GrOptDrawState&,
119 const GrGLProgramDesc&,
120 GrGpu::DrawType,
121 const GrGeometryStage* inGeometryProcessor,
122 const GrFragmentStage* inColorStages[],
123 const GrFragmentStage* inCoverageStages[],
124 GrGpuGL* gpu);
125
126 virtual UniformHandle addUniform(uint32_t visibility,
127 GrSLType type,
128 const char* name,
129 const char** outName = NULL) SK_OVERRIDE {
130 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
131 }
132 virtual UniformHandle addUniformArray(uint32_t visibility,
133 GrSLType type,
134 const char* name,
135 int arrayCount,
136 const char** outName = NULL) SK_OVERRIDE;
137
138 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
139 return fUniforms[u.toShaderBuilderIndex()].fVariable;
140 }
141
142 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
143 return this->getUniformVariable(u).c_str();
144 }
145
146 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
147
148 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
149
150 virtual GrGLFragmentShaderBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
151 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
152
153 virtual void addVarying(GrSLType type,
154 const char* name,
155 const char** vsOutName = NULL,
156 const char** fsInName = NULL,
157 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
joshualitt30ba4362014-08-21 20:18:45 -0700158
159 // Handles for program uniforms (other than per-effect uniforms)
160 struct BuiltinUniformHandles {
161 UniformHandle fViewMatrixUni;
162 UniformHandle fRTAdjustmentUni;
163 UniformHandle fColorUni;
164 UniformHandle fCoverageUni;
165
166 // We use the render target height to provide a y-down frag coord when specifying
167 // origin_upper_left is not supported.
168 UniformHandle fRTHeightUni;
169
170 // Uniforms for computing texture coords to do the dst-copy lookup
171 UniformHandle fDstCopyTopLeftUni;
172 UniformHandle fDstCopyScaleUni;
173 UniformHandle fDstCopySamplerUni;
174 };
175
joshualitt30ba4362014-08-21 20:18:45 -0700176protected:
joshualittfe1233c2014-10-07 12:16:35 -0700177 static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
178 const GrOptDrawState&,
179 GrGpu::DrawType,
180 bool hasGeometryProcessor,
181 GrGpuGL*);
182
egdaniel307796b2014-10-06 12:13:54 -0700183 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
joshualitt30ba4362014-08-21 20:18:45 -0700184
egdaniel307796b2014-10-06 12:13:54 -0700185 const GrOptDrawState& optState() const { return fOptState; }
joshualitt30ba4362014-08-21 20:18:45 -0700186 const GrGLProgramDesc& desc() const { return fDesc; }
joshualittfe1233c2014-10-07 12:16:35 -0700187 const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
joshualitt23e280d2014-09-18 12:26:38 -0700188
joshualitt30ba4362014-08-21 20:18:45 -0700189 // Generates a name for a variable. The generated string will be name prefixed by the prefix
190 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
191 // generating stage code.
192 void nameVariable(SkString* out, char prefix, const char* name);
joshualittfe1233c2014-10-07 12:16:35 -0700193 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
194 void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
195 const GrFragmentStage* colorStages[],
196 const GrFragmentStage* coverageStages[],
197 GrGLSLExpr4* inputColor,
198 GrGLSLExpr4* inputCoverage);
199 template <class ProcessorStage>
200 void createAndEmitProcessors(const ProcessorStage*[],
201 int effectCnt,
202 const GrGLProgramDesc::EffectKeyProvider&,
203 GrGLSLExpr4* fsInOutColor,
204 GrGLInstalledProcessors*);
205 void verify(const GrGeometryProcessor&);
206 void verify(const GrFragmentProcessor&);
207 void emitSamplers(const GrProcessor&,
208 GrGLProcessor::TextureSamplerArray* outSamplers,
209 GrGLInstalledProcessors*);
joshualitt30ba4362014-08-21 20:18:45 -0700210
joshualittfe1233c2014-10-07 12:16:35 -0700211 // each specific program builder has a distinct transform and must override this function
212 virtual void emitTransforms(const GrProcessorStage&,
213 GrGLProcessor::TransformedCoordsArray* outCoords,
214 GrGLInstalledProcessors*);
215 GrGLProgram* finalize();
216 void bindUniformLocations(GrGLuint programID);
217 bool checkLinkStatus(GrGLuint programID);
218 void resolveUniformLocations(GrGLuint programID);
joshualitt30ba4362014-08-21 20:18:45 -0700219
joshualittfe1233c2014-10-07 12:16:35 -0700220 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
221 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700222
joshualittfe1233c2014-10-07 12:16:35 -0700223 // Subclasses create different programs
224 virtual GrGLProgram* createProgram(GrGLuint programID);
225
joshualitt30ba4362014-08-21 20:18:45 -0700226 void appendUniformDecls(ShaderVisibility, SkString*) const;
227
joshualittfe1233c2014-10-07 12:16:35 -0700228 // reset is called by program creator between each processor's emit code. It increments the
229 // stage offset for variable name mangling, and also ensures verfication variables in the
230 // fragment shader are cleared.
231 void reset() {
232 this->enterStage();
233 this->addStage();
234 fFS.reset();
235 }
236 void addStage() { fStageIndex++; }
237
238 // This simple class exits the stage and then restores the stage when it goes out of scope
239 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700240 public:
joshualittfe1233c2014-10-07 12:16:35 -0700241 AutoStageRestore(GrGLProgramBuilder* pb)
242 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
243 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualitt30ba4362014-08-21 20:18:45 -0700244 private:
joshualittfe1233c2014-10-07 12:16:35 -0700245 GrGLProgramBuilder* fPB;
246 bool fOutOfStage;
247 };
248 void exitStage() { fOutOfStage = true; }
249 void enterStage() { fOutOfStage = false; }
250 int stageIndex() const { return fStageIndex; }
251
252 typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
253 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
254 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
255
256 // number of each input/output type in a single allocation block, used by many builders
257 static const int kVarsPerBlock;
258
259 BuiltinUniformHandles fUniformHandles;
260 GrGLVertexBuilder fVS;
261 GrGLGeometryBuilder fGS;
262 GrGLFragmentShaderBuilder fFS;
263 bool fOutOfStage;
264 int fStageIndex;
265
266 SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
267 SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
268 SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
269
270 const GrOptDrawState& fOptState;
271 const GrGLProgramDesc& fDesc;
272 GrGpuGL* fGpu;
273 UniformInfoArray fUniforms;
274
275 friend class GrGLShaderBuilder;
276 friend class GrGLVertexBuilder;
277 friend class GrGLFragmentShaderBuilder;
278 friend class GrGLGeometryBuilder;
279};
280
281/**
282 * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
283 * and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
284 * state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
285 *
286 * TODO We really don't need this class to have an array of processors. It makes sense for it
287 * to just have one, also break out the transforms
288 */
289class GrGLInstalledProcessors : public SkRefCnt {
290public:
291 GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
292 : fGLProcessors(reserveCount)
293 , fSamplers(reserveCount)
294 , fTransforms(reserveCount)
295 , fHasExplicitLocalCoords(hasExplicitLocalCoords) {
296 }
297
298 virtual ~GrGLInstalledProcessors();
299
300 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
301
302 struct Sampler {
303 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
304 UniformHandle fUniform;
305 int fTextureUnit;
joshualitt23e280d2014-09-18 12:26:38 -0700306 };
307
joshualittfe1233c2014-10-07 12:16:35 -0700308 class ShaderVarHandle {
joshualittb0a8a372014-09-23 09:50:21 -0700309 public:
joshualittfe1233c2014-10-07 12:16:35 -0700310 bool isValid() const { return fHandle > -1; }
311 ShaderVarHandle() : fHandle(-1) {}
312 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
313 int handle() const { SkASSERT(this->isValid()); return fHandle; }
314 UniformHandle convertToUniformHandle() {
315 SkASSERT(this->isValid());
316 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
joshualittb0a8a372014-09-23 09:50:21 -0700317 }
joshualittfe1233c2014-10-07 12:16:35 -0700318
joshualittb0a8a372014-09-23 09:50:21 -0700319 private:
joshualittfe1233c2014-10-07 12:16:35 -0700320 int fHandle;
joshualittb0a8a372014-09-23 09:50:21 -0700321 };
322
joshualittfe1233c2014-10-07 12:16:35 -0700323 struct Transform {
324 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
325 ShaderVarHandle fHandle;
326 SkMatrix fCurrentValue;
327 GrSLType fType;
328 };
joshualitt249af152014-09-15 11:41:13 -0700329
joshualittfe1233c2014-10-07 12:16:35 -0700330 void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
331 SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
332 SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
joshualittbd769d02014-09-04 08:56:46 -0700333
joshualittfe1233c2014-10-07 12:16:35 -0700334 SkTArray<GrGLProcessor*> fGLProcessors;
335 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
336 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
337 bool fHasExplicitLocalCoords;
joshualitt30ba4362014-08-21 20:18:45 -0700338
339 friend class GrGLShaderBuilder;
340 friend class GrGLVertexShaderBuilder;
341 friend class GrGLFragmentShaderBuilder;
342 friend class GrGLGeometryShaderBuilder;
343};
344
joshualitt30ba4362014-08-21 20:18:45 -0700345#endif