blob: e4d84a013b8c866be2da06d28cdd2e157c5cb454 [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"
kkinnunen7510b222014-07-30 00:04:16 -070012#include "GrGLProgramDataManager.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;
joshualitt30ba4362014-08-21 20:18:45 -070019class GrGLProgramBuilder;
20class GrGLFullProgramBuilder;
21class GrGLFragmentOnlyProgramBuilder;
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:
kkinnunen7510b222014-07-30 00:04:16 -070030 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000031
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 */
kkinnunen7510b222014-07-30 00:04:16 -070048 void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000049
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*,
kkinnunen7510b222014-07-30 00:04:16 -070054 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000055 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000056
joshualitt30ba4362014-08-21 20:18:45 -070057 void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
58
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000059 /**
60 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
61 */
62 class TransformedCoords {
63 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000064 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000065 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000066 }
67
68 const char* c_str() const { return fName.c_str(); }
69 GrSLType type() const { return fType; }
70 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000071
72 private:
73 SkString fName;
74 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000075 };
76
77 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
78
79 /**
80 * Passed to GrGLEffects so they can add texture reads to their shader code.
81 */
82 class TextureSampler {
83 public:
84 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
85 : fSamplerUniform(uniform)
86 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
87 SkASSERT(0 != fConfigComponentMask);
88 memcpy(fSwizzle, access.getSwizzle(), 5);
89 }
90
91 UniformHandle samplerUniform() const { return fSamplerUniform; }
92 // bitfield of GrColorComponentFlags present in the texture's config.
93 uint32_t configComponentMask() const { return fConfigComponentMask; }
94 const char* swizzle() const { return fSwizzle; }
95
96 private:
97 UniformHandle fSamplerUniform;
98 uint32_t fConfigComponentMask;
99 char fSwizzle[5];
100 };
101
102 typedef SkTArray<TextureSampler> TextureSamplerArray;
103
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000104protected:
joshualitt30ba4362014-08-21 20:18:45 -0700105
bsalomon929f29a2014-07-17 07:55:11 -0700106 /**
107 * Helpers for GenEffectMetaKey.
108 */
bsalomon63e99f72014-07-21 08:03:14 -0700109 static uint32_t GenAttribKey(const GrDrawEffect&);
110 static uint32_t GenTransformKey(const GrDrawEffect&);
111 static uint32_t GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
bsalomon929f29a2014-07-17 07:55:11 -0700112
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000113 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000114 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000115 , fSamplers(reserveCount) {
116 }
117
118 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000119 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
120 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
121 * lookups to their code. This method is only meant to be called during the construction phase.
122 */
joshualitt30ba4362014-08-21 20:18:45 -0700123 void emitSamplers(GrGLProgramBuilder*, const GrEffect*, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000124
125 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000126 * Helper for setData(). Binds all the textures for an effect.
127 */
bsalomonf99f8842014-07-07 11:54:23 -0700128 void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000129
130 struct Sampler {
131 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
132 UniformHandle fUniform;
133 int fTextureUnit;
134 };
135
136 SkTArray<GrGLEffect*> fGLEffects;
137 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000138
139private:
joshualitt30ba4362014-08-21 20:18:45 -0700140 friend class GrGLFragmentO;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000141 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000142};
143
144/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000145 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
146 */
147class GrGLProgramEffectsBuilder {
148public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000149 virtual ~GrGLProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000150 /**
151 * Emits the effect's shader code, and stores the necessary uniforms internally.
152 */
153 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700154 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000155 const char* outColor,
156 const char* inColor,
157 int stageIndex) = 0;
158};
159
160////////////////////////////////////////////////////////////////////////////////
161
162/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000163 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
164 */
165class GrGLVertexProgramEffects : public GrGLProgramEffects {
166public:
167 virtual void setData(GrGpuGL*,
kkinnunen7510b222014-07-30 00:04:16 -0700168 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000169 const GrEffectStage* effectStages[]) SK_OVERRIDE;
170
171private:
joshualitt30ba4362014-08-21 20:18:45 -0700172 friend class GrGLFullProgramBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000173
174 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
175 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000176 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000177 , fHasExplicitLocalCoords(explicitLocalCoords) {
178 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000179 /**
joshualitt30ba4362014-08-21 20:18:45 -0700180 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000181 */
joshualitt30ba4362014-08-21 20:18:45 -0700182 void emitEffect(GrGLFullProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000183 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700184 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000185 const char* outColor,
186 const char* inColor,
187 int stageIndex);
188
189 /**
190 * Helper for emitEffect(). Emits any attributes an effect may have.
191 */
joshualitt30ba4362014-08-21 20:18:45 -0700192 void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000193
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 */
joshualitt30ba4362014-08-21 20:18:45 -0700201 void emitTransforms(GrGLFullProgramBuilder*,
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 */
kkinnunen7510b222014-07-30 00:04:16 -0700208 void setTransformData(const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000209
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
joshualitt30ba4362014-08-21 20:18:45 -0700219 friend class GrGLVertexProgramEffectsBuilder;
220
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000221 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000222};
223
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000224/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000225 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000226 */
227class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
228public:
joshualitt30ba4362014-08-21 20:18:45 -0700229 GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000230 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000231 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700232 const GrEffectKey&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000233 const char* outColor,
234 const char* inColor,
235 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000236 /**
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(); }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000241private:
joshualitt30ba4362014-08-21 20:18:45 -0700242 GrGLFullProgramBuilder* fBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000243 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000244 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000245};
246
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000247////////////////////////////////////////////////////////////////////////////////
248
249/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000250 * This is a GrGLProgramEffects implementation that does coord transforms with
251 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000252 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000253class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000254public:
255 virtual void setData(GrGpuGL*,
kkinnunen7510b222014-07-30 00:04:16 -0700256 const GrGLProgramDataManager&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000257 const GrEffectStage* effectStages[]) SK_OVERRIDE;
258
259private:
joshualitt30ba4362014-08-21 20:18:45 -0700260 friend class GrGLFragmentOnlyProgramBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000261
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000262 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000263 : INHERITED(reserveCount)
264 , fTransforms(reserveCount) {
265 }
266
267 /**
joshualitt30ba4362014-08-21 20:18:45 -0700268 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000269 */
joshualitt30ba4362014-08-21 20:18:45 -0700270 void emitEffect(GrGLFragmentOnlyProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000271 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700272 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000273 const char* outColor,
274 const char* inColor,
275 int stageIndex);
276
277 /**
278 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
279 * effect. The transforms all use adjacent texture units. They either use two or three of the
280 * coordinates at a given texture unit, depending on if they need perspective interpolation.
281 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
282 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
283 * effect's emitCode() function.
284 */
joshualitt30ba4362014-08-21 20:18:45 -0700285 void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700286 const GrDrawEffect&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000287 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000288
289 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000290 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000291 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000292 void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000293
294 struct Transforms {
bsalomon63e99f72014-07-21 08:03:14 -0700295 Transforms(uint32_t transformKey, int texCoordIndex)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000296 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
bsalomon63e99f72014-07-21 08:03:14 -0700297 uint32_t fTransformKey;
298 int fTexCoordIndex;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000299 };
300
301 SkTArray<Transforms> fTransforms;
302
joshualitt30ba4362014-08-21 20:18:45 -0700303 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000304 typedef GrGLProgramEffects INHERITED;
305};
306
307/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000308 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000309 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000310class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000311public:
joshualitt30ba4362014-08-21 20:18:45 -0700312 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000313 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000314 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700315 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000316 const char* outColor,
317 const char* inColor,
318 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000319 /**
320 * Finalizes the building process and returns the effect array. After this call, the builder
321 * becomes invalid.
322 */
323 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000324private:
joshualitt30ba4362014-08-21 20:18:45 -0700325 GrGLFragmentOnlyProgramBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000326 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000327 typedef GrGLProgramEffectsBuilder INHERITED;
328};
329
joshualitt30ba4362014-08-21 20:18:45 -0700330
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000331#endif