blob: c4d884392a26c23488bd459789eccca1a716f170 [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:
30 typedef GrBackendEffectFactory::EffectKey EffectKey;
31 typedef GrGLUniformManager::UniformHandle UniformHandle;
32
33 /**
bsalomon929f29a2014-07-17 07:55:11 -070034 * This class emits some of the code inserted into the shaders for an effect. The code it
35 * creates may be dependent on properties of the effect that the effect itself doesn't use
36 * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
37 * every effect using this function. It is also responsible for inserting the effect's class ID
38 * which must be different for every GrEffect subclass. It can fail if an effect uses too many
39 * textures, attributes, etc for the space allotted in the meta-key.
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000040 */
bsalomon929f29a2014-07-17 07:55:11 -070041 static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000042
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000043 virtual ~GrGLProgramEffects();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000044
45 /**
46 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
47 * available unit to *texUnitIdx when it returns.
48 */
49 void initSamplers(const GrGLUniformManager&, int* texUnitIdx);
50
51 /**
52 * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
53 */
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000054 virtual void setData(GrGpuGL*,
55 const GrGLUniformManager&,
56 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000057
58 /**
59 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
60 */
61 class TransformedCoords {
62 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000063 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000064 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000065 }
66
67 const char* c_str() const { return fName.c_str(); }
68 GrSLType type() const { return fType; }
69 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000070
71 private:
72 SkString fName;
73 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000074 };
75
76 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
77
78 /**
79 * Passed to GrGLEffects so they can add texture reads to their shader code.
80 */
81 class TextureSampler {
82 public:
83 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
84 : fSamplerUniform(uniform)
85 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
86 SkASSERT(0 != fConfigComponentMask);
87 memcpy(fSwizzle, access.getSwizzle(), 5);
88 }
89
90 UniformHandle samplerUniform() const { return fSamplerUniform; }
91 // bitfield of GrColorComponentFlags present in the texture's config.
92 uint32_t configComponentMask() const { return fConfigComponentMask; }
93 const char* swizzle() const { return fSwizzle; }
94
95 private:
96 UniformHandle fSamplerUniform;
97 uint32_t fConfigComponentMask;
98 char fSwizzle[5];
99 };
100
101 typedef SkTArray<TextureSampler> TextureSamplerArray;
102
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000103protected:
bsalomon929f29a2014-07-17 07:55:11 -0700104 /**
105 * Helpers for GenEffectMetaKey.
106 */
107 static EffectKey GenAttribKey(const GrDrawEffect&);
108 static EffectKey GenTransformKey(const GrDrawEffect&);
109 static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
110
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000111 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000112 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000113 , fSamplers(reserveCount) {
114 }
115
116 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000117 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
118 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
119 * lookups to their code. This method is only meant to be called during the construction phase.
120 */
bsalomonf99f8842014-07-07 11:54:23 -0700121 void emitSamplers(GrGLShaderBuilder*, const GrEffect*, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000122
123 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000124 * Helper for setData(). Binds all the textures for an effect.
125 */
bsalomonf99f8842014-07-07 11:54:23 -0700126 void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000127
128 struct Sampler {
129 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
130 UniformHandle fUniform;
131 int fTextureUnit;
132 };
133
134 SkTArray<GrGLEffect*> fGLEffects;
135 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000136
137private:
138 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000139};
140
141/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000142 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
143 */
144class GrGLProgramEffectsBuilder {
145public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000146 virtual ~GrGLProgramEffectsBuilder() { }
147
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000148 /**
149 * Emits the effect's shader code, and stores the necessary uniforms internally.
150 */
151 virtual void emitEffect(const GrEffectStage&,
152 GrGLProgramEffects::EffectKey,
153 const char* outColor,
154 const char* inColor,
155 int stageIndex) = 0;
156};
157
158////////////////////////////////////////////////////////////////////////////////
159
160/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000161 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
162 */
163class GrGLVertexProgramEffects : public GrGLProgramEffects {
164public:
165 virtual void setData(GrGpuGL*,
166 const GrGLUniformManager&,
167 const GrEffectStage* effectStages[]) SK_OVERRIDE;
168
169private:
170 friend class GrGLVertexProgramEffectsBuilder;
171
172 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
173 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000174 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000175 , fHasExplicitLocalCoords(explicitLocalCoords) {
176 }
177
178 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000179 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
180 * during the construction phase.
181 */
182 void emitEffect(GrGLFullShaderBuilder*,
183 const GrEffectStage&,
184 GrGLProgramEffects::EffectKey,
185 const char* outColor,
186 const char* inColor,
187 int stageIndex);
188
189 /**
190 * Helper for emitEffect(). Emits any attributes an effect may have.
191 */
192 void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
193
194 /**
195 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
196 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
197 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
198 * of the varyings in the VS and FS as well their types are appended to the
199 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
200 */
201 void emitTransforms(GrGLFullShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700202 const GrDrawEffect&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000203 TransformedCoordsArray*);
204
205 /**
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000206 * Helper for setData(). Sets all the transform matrices for an effect.
207 */
208 void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
209
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000210 struct Transform {
211 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
212 UniformHandle fHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000213 SkMatrix fCurrentValue;
214 };
215
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000216 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000217 bool fHasExplicitLocalCoords;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000218
219 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000220};
221
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000222/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000223 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000224 */
225class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
226public:
227 GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000228 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000229
230 virtual void emitEffect(const GrEffectStage&,
231 GrGLProgramEffects::EffectKey,
232 const char* outColor,
233 const char* inColor,
234 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000235
236 /**
237 * Finalizes the building process and returns the effect array. After this call, the builder
238 * becomes invalid.
239 */
240 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
241
242private:
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000243 GrGLFullShaderBuilder* fBuilder;
244 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000245
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000246 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000247};
248
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000249////////////////////////////////////////////////////////////////////////////////
250
251/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000252 * This is a GrGLProgramEffects implementation that does coord transforms with
253 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000254 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000255class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000256public:
257 virtual void setData(GrGpuGL*,
258 const GrGLUniformManager&,
259 const GrEffectStage* effectStages[]) SK_OVERRIDE;
260
261private:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000262 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000263
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000264 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000265 : INHERITED(reserveCount)
266 , fTransforms(reserveCount) {
267 }
268
269 /**
270 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
271 * during the construction phase.
272 */
273 void emitEffect(GrGLFragmentOnlyShaderBuilder*,
274 const GrEffectStage&,
275 GrGLProgramEffects::EffectKey,
276 const char* outColor,
277 const char* inColor,
278 int stageIndex);
279
280 /**
281 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
282 * effect. The transforms all use adjacent texture units. They either use two or three of the
283 * coordinates at a given texture unit, depending on if they need perspective interpolation.
284 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
285 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
286 * effect's emitCode() function.
287 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000288 void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700289 const GrDrawEffect&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000290 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000291
292 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000293 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000294 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000295 void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000296
297 struct Transforms {
298 Transforms(EffectKey transformKey, int texCoordIndex)
299 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
300 EffectKey fTransformKey;
301 int fTexCoordIndex;
302 };
303
304 SkTArray<Transforms> fTransforms;
305
306 typedef GrGLProgramEffects INHERITED;
307};
308
309/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000310 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000311 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000312class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000313public:
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000314 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
315 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000316
317 virtual void emitEffect(const GrEffectStage&,
318 GrGLProgramEffects::EffectKey,
319 const char* outColor,
320 const char* inColor,
321 int stageIndex) SK_OVERRIDE;
322
323 /**
324 * Finalizes the building process and returns the effect array. After this call, the builder
325 * becomes invalid.
326 */
327 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
328
329private:
330 GrGLFragmentOnlyShaderBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000331 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000332
333 typedef GrGLProgramEffectsBuilder INHERITED;
334};
335
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000336#endif