blob: c9ba9135a9bcc4d11ebaa069cf10ad86ff4672cd [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"
bsalomon929f29a2014-07-17 07:55:11 -070012#include "GrGLUniformManager.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000013#include "GrTexture.h"
14#include "GrTextureAccess.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:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000030 typedef GrGLUniformManager::UniformHandle UniformHandle;
31
32 /**
bsalomon929f29a2014-07-17 07:55:11 -070033 * This class emits some of the code inserted into the shaders for an effect. The code it
34 * creates may be dependent on properties of the effect that the effect itself doesn't use
35 * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
36 * every effect using this function. It is also responsible for inserting the effect's class ID
37 * which must be different for every GrEffect subclass. It can fail if an effect uses too many
38 * textures, attributes, etc for the space allotted in the meta-key.
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000039 */
bsalomon929f29a2014-07-17 07:55:11 -070040 static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000041
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000042 virtual ~GrGLProgramEffects();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000043
44 /**
45 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
46 * available unit to *texUnitIdx when it returns.
47 */
48 void initSamplers(const GrGLUniformManager&, int* texUnitIdx);
49
50 /**
51 * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
52 */
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000053 virtual void setData(GrGpuGL*,
54 const GrGLUniformManager&,
55 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000056
57 /**
58 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
59 */
60 class TransformedCoords {
61 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000062 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000063 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000064 }
65
66 const char* c_str() const { return fName.c_str(); }
67 GrSLType type() const { return fType; }
68 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000069
70 private:
71 SkString fName;
72 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000073 };
74
75 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
76
77 /**
78 * Passed to GrGLEffects so they can add texture reads to their shader code.
79 */
80 class TextureSampler {
81 public:
82 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
83 : fSamplerUniform(uniform)
84 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
85 SkASSERT(0 != fConfigComponentMask);
86 memcpy(fSwizzle, access.getSwizzle(), 5);
87 }
88
89 UniformHandle samplerUniform() const { return fSamplerUniform; }
90 // bitfield of GrColorComponentFlags present in the texture's config.
91 uint32_t configComponentMask() const { return fConfigComponentMask; }
92 const char* swizzle() const { return fSwizzle; }
93
94 private:
95 UniformHandle fSamplerUniform;
96 uint32_t fConfigComponentMask;
97 char fSwizzle[5];
98 };
99
100 typedef SkTArray<TextureSampler> TextureSamplerArray;
101
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000102protected:
bsalomon929f29a2014-07-17 07:55:11 -0700103 /**
104 * Helpers for GenEffectMetaKey.
105 */
bsalomon63e99f72014-07-21 08:03:14 -0700106 static uint32_t GenAttribKey(const GrDrawEffect&);
107 static uint32_t GenTransformKey(const GrDrawEffect&);
108 static uint32_t GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
bsalomon929f29a2014-07-17 07:55:11 -0700109
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000110 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000111 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000112 , fSamplers(reserveCount) {
113 }
114
115 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000116 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
117 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
118 * lookups to their code. This method is only meant to be called during the construction phase.
119 */
bsalomonf99f8842014-07-07 11:54:23 -0700120 void emitSamplers(GrGLShaderBuilder*, const GrEffect*, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000121
122 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000123 * Helper for setData(). Binds all the textures for an effect.
124 */
bsalomonf99f8842014-07-07 11:54:23 -0700125 void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000126
127 struct Sampler {
128 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
129 UniformHandle fUniform;
130 int fTextureUnit;
131 };
132
133 SkTArray<GrGLEffect*> fGLEffects;
134 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000135
136private:
137 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000138};
139
140/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000141 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
142 */
143class GrGLProgramEffectsBuilder {
144public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000145 virtual ~GrGLProgramEffectsBuilder() { }
146
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000147 /**
148 * Emits the effect's shader code, and stores the necessary uniforms internally.
149 */
150 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700151 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000152 const char* outColor,
153 const char* inColor,
154 int stageIndex) = 0;
155};
156
157////////////////////////////////////////////////////////////////////////////////
158
159/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000160 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
161 */
162class GrGLVertexProgramEffects : public GrGLProgramEffects {
163public:
164 virtual void setData(GrGpuGL*,
165 const GrGLUniformManager&,
166 const GrEffectStage* effectStages[]) SK_OVERRIDE;
167
168private:
169 friend class GrGLVertexProgramEffectsBuilder;
170
171 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
172 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000173 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000174 , fHasExplicitLocalCoords(explicitLocalCoords) {
175 }
176
177 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000178 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
179 * during the construction phase.
180 */
181 void emitEffect(GrGLFullShaderBuilder*,
182 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700183 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000184 const char* outColor,
185 const char* inColor,
186 int stageIndex);
187
188 /**
189 * Helper for emitEffect(). Emits any attributes an effect may have.
190 */
191 void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
192
193 /**
194 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
195 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
196 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
197 * of the varyings in the VS and FS as well their types are appended to the
198 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
199 */
200 void emitTransforms(GrGLFullShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700201 const GrDrawEffect&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000202 TransformedCoordsArray*);
203
204 /**
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000205 * Helper for setData(). Sets all the transform matrices for an effect.
206 */
207 void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
208
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000209 struct Transform {
210 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
211 UniformHandle fHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000212 SkMatrix fCurrentValue;
213 };
214
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000215 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000216 bool fHasExplicitLocalCoords;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000217
218 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000219};
220
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000221/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000222 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000223 */
224class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
225public:
226 GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000227 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000228
229 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700230 const GrEffectKey&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000231 const char* outColor,
232 const char* inColor,
233 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000234
235 /**
236 * Finalizes the building process and returns the effect array. After this call, the builder
237 * becomes invalid.
238 */
239 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
240
241private:
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000242 GrGLFullShaderBuilder* fBuilder;
243 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000244
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000245 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000246};
247
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000248////////////////////////////////////////////////////////////////////////////////
249
250/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000251 * This is a GrGLProgramEffects implementation that does coord transforms with
252 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000253 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000254class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000255public:
256 virtual void setData(GrGpuGL*,
257 const GrGLUniformManager&,
258 const GrEffectStage* effectStages[]) SK_OVERRIDE;
259
260private:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000261 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000262
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000263 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000264 : INHERITED(reserveCount)
265 , fTransforms(reserveCount) {
266 }
267
268 /**
269 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
270 * during the construction phase.
271 */
272 void emitEffect(GrGLFragmentOnlyShaderBuilder*,
273 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700274 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000275 const char* outColor,
276 const char* inColor,
277 int stageIndex);
278
279 /**
280 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
281 * effect. The transforms all use adjacent texture units. They either use two or three of the
282 * coordinates at a given texture unit, depending on if they need perspective interpolation.
283 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
284 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
285 * effect's emitCode() function.
286 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000287 void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700288 const GrDrawEffect&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000289 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000290
291 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000292 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000293 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000294 void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000295
296 struct Transforms {
bsalomon63e99f72014-07-21 08:03:14 -0700297 Transforms(uint32_t transformKey, int texCoordIndex)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000298 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
bsalomon63e99f72014-07-21 08:03:14 -0700299 uint32_t fTransformKey;
300 int fTexCoordIndex;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000301 };
302
303 SkTArray<Transforms> fTransforms;
304
305 typedef GrGLProgramEffects INHERITED;
306};
307
308/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000309 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000310 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000311class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000312public:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000313 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
314 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000315
316 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700317 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000318 const char* outColor,
319 const char* inColor,
320 int stageIndex) SK_OVERRIDE;
321
322 /**
323 * Finalizes the building process and returns the effect array. After this call, the builder
324 * becomes invalid.
325 */
326 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
327
328private:
329 GrGLFragmentOnlyShaderBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000330 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000331
332 typedef GrGLProgramEffectsBuilder INHERITED;
333};
334
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000335#endif