blob: 5a2fefd7d4d76672eb835f4b344a81654c83a56b [file] [log] [blame]
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +00001/*
2 * Copyright 2013 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 GrGLProgramEffects_DEFINED
9#define GrGLProgramEffects_DEFINED
10
11#include "GrBackendEffectFactory.h"
12#include "GrTexture.h"
13#include "GrTextureAccess.h"
mtklein79401002014-07-16 06:16:43 -070014#include "GrGLUniformManager.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000015
bsalomonf99f8842014-07-07 11:54:23 -070016class GrEffect;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000017class GrEffectStage;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000018class GrGLVertexProgramEffectsBuilder;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000019class GrGLShaderBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000020class GrGLFullShaderBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000021class GrGLFragmentOnlyShaderBuilder;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000022
23/**
24 * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms
25 * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
26 * state and shader uniforms.
27 */
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000028class GrGLProgramEffects : public SkRefCnt {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000029public:
30 typedef GrBackendEffectFactory::EffectKey EffectKey;
31 typedef GrGLUniformManager::UniformHandle UniformHandle;
32
33 /**
mtklein79401002014-07-16 06:16:43 -070034 * These methods generate different portions of an effect's final key.
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000035 */
mtklein79401002014-07-16 06:16:43 -070036 static EffectKey GenAttribKey(const GrDrawEffect&);
37 static EffectKey GenTransformKey(const GrDrawEffect&);
38 static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000039
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000040 virtual ~GrGLProgramEffects();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000041
42 /**
43 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
44 * available unit to *texUnitIdx when it returns.
45 */
46 void initSamplers(const GrGLUniformManager&, int* texUnitIdx);
47
48 /**
49 * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
50 */
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000051 virtual void setData(GrGpuGL*,
52 const GrGLUniformManager&,
53 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000054
55 /**
56 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
57 */
58 class TransformedCoords {
59 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000060 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000061 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000062 }
63
64 const char* c_str() const { return fName.c_str(); }
65 GrSLType type() const { return fType; }
66 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000067
68 private:
69 SkString fName;
70 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000071 };
72
73 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
74
75 /**
76 * Passed to GrGLEffects so they can add texture reads to their shader code.
77 */
78 class TextureSampler {
79 public:
80 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
81 : fSamplerUniform(uniform)
82 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
83 SkASSERT(0 != fConfigComponentMask);
84 memcpy(fSwizzle, access.getSwizzle(), 5);
85 }
86
87 UniformHandle samplerUniform() const { return fSamplerUniform; }
88 // bitfield of GrColorComponentFlags present in the texture's config.
89 uint32_t configComponentMask() const { return fConfigComponentMask; }
90 const char* swizzle() const { return fSwizzle; }
91
92 private:
93 UniformHandle fSamplerUniform;
94 uint32_t fConfigComponentMask;
95 char fSwizzle[5];
96 };
97
98 typedef SkTArray<TextureSampler> TextureSamplerArray;
99
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000100protected:
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000101 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000102 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000103 , fSamplers(reserveCount) {
104 }
105
106 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000107 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
108 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
109 * lookups to their code. This method is only meant to be called during the construction phase.
110 */
bsalomonf99f8842014-07-07 11:54:23 -0700111 void emitSamplers(GrGLShaderBuilder*, const GrEffect*, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000112
113 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000114 * Helper for setData(). Binds all the textures for an effect.
115 */
bsalomonf99f8842014-07-07 11:54:23 -0700116 void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000117
118 struct Sampler {
119 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
120 UniformHandle fUniform;
121 int fTextureUnit;
122 };
123
124 SkTArray<GrGLEffect*> fGLEffects;
125 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000126
127private:
128 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000129};
130
131/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000132 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
133 */
134class GrGLProgramEffectsBuilder {
135public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000136 virtual ~GrGLProgramEffectsBuilder() { }
137
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000138 /**
139 * Emits the effect's shader code, and stores the necessary uniforms internally.
140 */
141 virtual void emitEffect(const GrEffectStage&,
142 GrGLProgramEffects::EffectKey,
143 const char* outColor,
144 const char* inColor,
145 int stageIndex) = 0;
146};
147
148////////////////////////////////////////////////////////////////////////////////
149
150/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000151 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
152 */
153class GrGLVertexProgramEffects : public GrGLProgramEffects {
154public:
155 virtual void setData(GrGpuGL*,
156 const GrGLUniformManager&,
157 const GrEffectStage* effectStages[]) SK_OVERRIDE;
158
159private:
160 friend class GrGLVertexProgramEffectsBuilder;
161
162 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
163 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000164 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000165 , fHasExplicitLocalCoords(explicitLocalCoords) {
166 }
167
168 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000169 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
170 * during the construction phase.
171 */
172 void emitEffect(GrGLFullShaderBuilder*,
173 const GrEffectStage&,
174 GrGLProgramEffects::EffectKey,
175 const char* outColor,
176 const char* inColor,
177 int stageIndex);
178
179 /**
180 * Helper for emitEffect(). Emits any attributes an effect may have.
181 */
182 void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
183
184 /**
185 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
186 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
187 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
188 * of the varyings in the VS and FS as well their types are appended to the
189 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
190 */
191 void emitTransforms(GrGLFullShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700192 const GrDrawEffect&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000193 TransformedCoordsArray*);
194
195 /**
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000196 * Helper for setData(). Sets all the transform matrices for an effect.
197 */
198 void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
199
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000200 struct Transform {
201 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
202 UniformHandle fHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000203 SkMatrix fCurrentValue;
204 };
205
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000206 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000207 bool fHasExplicitLocalCoords;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000208
209 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000210};
211
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000212/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000213 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000214 */
215class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
216public:
217 GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000218 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000219
220 virtual void emitEffect(const GrEffectStage&,
221 GrGLProgramEffects::EffectKey,
222 const char* outColor,
223 const char* inColor,
224 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000225
226 /**
227 * Finalizes the building process and returns the effect array. After this call, the builder
228 * becomes invalid.
229 */
230 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
231
232private:
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000233 GrGLFullShaderBuilder* fBuilder;
234 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000235
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000236 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000237};
238
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000239////////////////////////////////////////////////////////////////////////////////
240
241/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000242 * This is a GrGLProgramEffects implementation that does coord transforms with
243 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000244 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000245class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000246public:
247 virtual void setData(GrGpuGL*,
248 const GrGLUniformManager&,
249 const GrEffectStage* effectStages[]) SK_OVERRIDE;
250
251private:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000252 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000253
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000254 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000255 : INHERITED(reserveCount)
256 , fTransforms(reserveCount) {
257 }
258
259 /**
260 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
261 * during the construction phase.
262 */
263 void emitEffect(GrGLFragmentOnlyShaderBuilder*,
264 const GrEffectStage&,
265 GrGLProgramEffects::EffectKey,
266 const char* outColor,
267 const char* inColor,
268 int stageIndex);
269
270 /**
271 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
272 * effect. The transforms all use adjacent texture units. They either use two or three of the
273 * coordinates at a given texture unit, depending on if they need perspective interpolation.
274 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
275 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
276 * effect's emitCode() function.
277 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000278 void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700279 const GrDrawEffect&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000280 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000281
282 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000283 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000284 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000285 void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000286
287 struct Transforms {
288 Transforms(EffectKey transformKey, int texCoordIndex)
289 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
290 EffectKey fTransformKey;
291 int fTexCoordIndex;
292 };
293
294 SkTArray<Transforms> fTransforms;
295
296 typedef GrGLProgramEffects INHERITED;
297};
298
299/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000300 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000301 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000302class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000303public:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000304 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
305 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000306
307 virtual void emitEffect(const GrEffectStage&,
308 GrGLProgramEffects::EffectKey,
309 const char* outColor,
310 const char* inColor,
311 int stageIndex) SK_OVERRIDE;
312
313 /**
314 * Finalizes the building process and returns the effect array. After this call, the builder
315 * becomes invalid.
316 */
317 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
318
319private:
320 GrGLFragmentOnlyShaderBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000321 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000322
323 typedef GrGLProgramEffectsBuilder INHERITED;
324};
325
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000326#endif