blob: dd3feab8435147f1aebc99572ffc573901349948 [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"
kkinnunenec56e452014-08-25 22:21:16 -070013#include "GrGpu.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000014#include "GrTexture.h"
15#include "GrTextureAccess.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000016
bsalomonf99f8842014-07-07 11:54:23 -070017class GrEffect;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000018class GrEffectStage;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000019class GrGLVertexProgramEffectsBuilder;
joshualitt30ba4362014-08-21 20:18:45 -070020class GrGLProgramBuilder;
21class GrGLFullProgramBuilder;
22class GrGLFragmentOnlyProgramBuilder;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000023
24/**
25 * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms
26 * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
27 * state and shader uniforms.
28 */
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +000029class GrGLProgramEffects : public SkRefCnt {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000030public:
kkinnunen7510b222014-07-30 00:04:16 -070031 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
kkinnunenec56e452014-08-25 22:21:16 -070032 typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000033
34 /**
bsalomon929f29a2014-07-17 07:55:11 -070035 * This class emits some of the code inserted into the shaders for an effect. The code it
36 * creates may be dependent on properties of the effect that the effect itself doesn't use
37 * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
38 * every effect using this function. It is also responsible for inserting the effect's class ID
39 * which must be different for every GrEffect subclass. It can fail if an effect uses too many
40 * textures, attributes, etc for the space allotted in the meta-key.
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000041 */
joshualitt49586be2014-09-16 08:21:41 -070042 static bool GenEffectMetaKey(const GrEffectStage&,
43 bool,
44 const GrGLCaps&,
45 GrEffectKeyBuilder*);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000046
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000047 virtual ~GrGLProgramEffects();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000048
49 /**
50 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
51 * available unit to *texUnitIdx when it returns.
52 */
kkinnunen7510b222014-07-30 00:04:16 -070053 void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000054
55 /**
56 * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
57 */
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000058 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -070059 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -070060 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000061 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000062
joshualittbd769d02014-09-04 08:56:46 -070063 virtual void setData(GrGpuGL*,
64 GrGpu::DrawType,
65 const GrGLProgramDataManager&,
66 const GrEffectStage* effectStages) { SkFAIL("DO NOT USE"); }
67
joshualitt30ba4362014-08-21 20:18:45 -070068 void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
69
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000070 /**
71 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
72 */
73 class TransformedCoords {
74 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000075 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000076 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000077 }
78
79 const char* c_str() const { return fName.c_str(); }
80 GrSLType type() const { return fType; }
81 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000082
83 private:
84 SkString fName;
85 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000086 };
87
88 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
89
90 /**
91 * Passed to GrGLEffects so they can add texture reads to their shader code.
92 */
93 class TextureSampler {
94 public:
95 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
96 : fSamplerUniform(uniform)
97 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
98 SkASSERT(0 != fConfigComponentMask);
99 memcpy(fSwizzle, access.getSwizzle(), 5);
100 }
101
102 UniformHandle samplerUniform() const { return fSamplerUniform; }
103 // bitfield of GrColorComponentFlags present in the texture's config.
104 uint32_t configComponentMask() const { return fConfigComponentMask; }
105 const char* swizzle() const { return fSwizzle; }
106
107 private:
108 UniformHandle fSamplerUniform;
109 uint32_t fConfigComponentMask;
110 char fSwizzle[5];
111 };
112
113 typedef SkTArray<TextureSampler> TextureSamplerArray;
114
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000115protected:
joshualitt30ba4362014-08-21 20:18:45 -0700116
bsalomon929f29a2014-07-17 07:55:11 -0700117 /**
118 * Helpers for GenEffectMetaKey.
119 */
joshualitt49586be2014-09-16 08:21:41 -0700120 static uint32_t GenAttribKey(const GrEffect*);
121 static uint32_t GenTransformKey(const GrEffectStage&, bool useExplicitLocalCoords);
122 static uint32_t GenTextureKey(const GrEffect*, const GrGLCaps&);
bsalomon929f29a2014-07-17 07:55:11 -0700123
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000124 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000125 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000126 , fSamplers(reserveCount) {
127 }
128
129 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000130 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
131 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
132 * lookups to their code. This method is only meant to be called during the construction phase.
133 */
joshualitt49586be2014-09-16 08:21:41 -0700134 void emitSamplers(GrGLProgramBuilder*, const GrEffect&, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000135
136 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000137 * Helper for setData(). Binds all the textures for an effect.
138 */
joshualitt49586be2014-09-16 08:21:41 -0700139 void bindTextures(GrGpuGL*, const GrEffect&, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000140
141 struct Sampler {
142 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
143 UniformHandle fUniform;
144 int fTextureUnit;
145 };
146
147 SkTArray<GrGLEffect*> fGLEffects;
148 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000149
150private:
151 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000152};
153
154/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000155 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
156 */
157class GrGLProgramEffectsBuilder {
158public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000159 virtual ~GrGLProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000160 /**
161 * Emits the effect's shader code, and stores the necessary uniforms internally.
162 */
163 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700164 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000165 const char* outColor,
166 const char* inColor,
167 int stageIndex) = 0;
168};
169
170////////////////////////////////////////////////////////////////////////////////
171
172/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000173 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
174 */
175class GrGLVertexProgramEffects : public GrGLProgramEffects {
176public:
177 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -0700178 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -0700179 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000180 const GrEffectStage* effectStages[]) SK_OVERRIDE;
181
joshualittbd769d02014-09-04 08:56:46 -0700182 virtual void setData(GrGpuGL*,
183 GrGpu::DrawType,
184 const GrGLProgramDataManager&,
185 const GrEffectStage* effectStages) SK_OVERRIDE;
186
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000187private:
joshualitt30ba4362014-08-21 20:18:45 -0700188 friend class GrGLFullProgramBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000189
190 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
191 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000192 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000193 , fHasExplicitLocalCoords(explicitLocalCoords) {
194 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000195 /**
joshualitt30ba4362014-08-21 20:18:45 -0700196 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000197 */
joshualitt30ba4362014-08-21 20:18:45 -0700198 void emitEffect(GrGLFullProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000199 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700200 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000201 const char* outColor,
202 const char* inColor,
203 int stageIndex);
204
205 /**
206 * Helper for emitEffect(). Emits any attributes an effect may have.
207 */
joshualitt30ba4362014-08-21 20:18:45 -0700208 void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000209
210 /**
211 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
212 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
213 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
214 * of the varyings in the VS and FS as well their types are appended to the
215 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
216 */
joshualitt30ba4362014-08-21 20:18:45 -0700217 void emitTransforms(GrGLFullProgramBuilder*,
joshualitt49586be2014-09-16 08:21:41 -0700218 const GrEffectStage&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000219 TransformedCoordsArray*);
220
221 /**
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000222 * Helper for setData(). Sets all the transform matrices for an effect.
223 */
joshualitt49586be2014-09-16 08:21:41 -0700224 void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
225 int effectIdx);
226 void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&,
kkinnunenec56e452014-08-25 22:21:16 -0700227 int effectIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000228
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000229 struct Transform {
230 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
231 UniformHandle fHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000232 SkMatrix fCurrentValue;
233 };
234
kkinnunenec56e452014-08-25 22:21:16 -0700235 struct PathTransform {
236 PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
237 VaryingHandle fHandle;
238 SkMatrix fCurrentValue;
239 GrSLType fType;
240 };
241
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000242 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
kkinnunenec56e452014-08-25 22:21:16 -0700243 SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000244 bool fHasExplicitLocalCoords;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000245
joshualitt30ba4362014-08-21 20:18:45 -0700246 friend class GrGLVertexProgramEffectsBuilder;
247
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000248 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000249};
250
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000251/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000252 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000253 */
254class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
255public:
joshualitt30ba4362014-08-21 20:18:45 -0700256 GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000257 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000258 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700259 const GrEffectKey&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000260 const char* outColor,
261 const char* inColor,
262 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000263 /**
264 * Finalizes the building process and returns the effect array. After this call, the builder
265 * becomes invalid.
266 */
267 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000268private:
joshualitt30ba4362014-08-21 20:18:45 -0700269 GrGLFullProgramBuilder* fBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000270 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000271 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000272};
273
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000274////////////////////////////////////////////////////////////////////////////////
275
276/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000277 * This is a GrGLProgramEffects implementation that does coord transforms with
278 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000279 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000280class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000281public:
282 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -0700283 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -0700284 const GrGLProgramDataManager&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000285 const GrEffectStage* effectStages[]) SK_OVERRIDE;
286
287private:
joshualitt30ba4362014-08-21 20:18:45 -0700288 friend class GrGLFragmentOnlyProgramBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000289
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000290 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000291 : INHERITED(reserveCount)
292 , fTransforms(reserveCount) {
293 }
294
295 /**
joshualitt30ba4362014-08-21 20:18:45 -0700296 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000297 */
joshualitt30ba4362014-08-21 20:18:45 -0700298 void emitEffect(GrGLFragmentOnlyProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000299 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700300 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000301 const char* outColor,
302 const char* inColor,
303 int stageIndex);
304
305 /**
306 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
307 * effect. The transforms all use adjacent texture units. They either use two or three of the
308 * coordinates at a given texture unit, depending on if they need perspective interpolation.
309 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
310 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
311 * effect's emitCode() function.
312 */
joshualitt30ba4362014-08-21 20:18:45 -0700313 void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*,
joshualitt49586be2014-09-16 08:21:41 -0700314 const GrEffectStage&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000315 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000316
317 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000318 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000319 */
joshualitt49586be2014-09-16 08:21:41 -0700320 void setPathTexGenState(GrGpuGL*, const GrEffectStage&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000321
322 struct Transforms {
bsalomon63e99f72014-07-21 08:03:14 -0700323 Transforms(uint32_t transformKey, int texCoordIndex)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000324 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
bsalomon63e99f72014-07-21 08:03:14 -0700325 uint32_t fTransformKey;
326 int fTexCoordIndex;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000327 };
328
329 SkTArray<Transforms> fTransforms;
330
joshualitt30ba4362014-08-21 20:18:45 -0700331 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000332 typedef GrGLProgramEffects INHERITED;
333};
334
335/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000336 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000337 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000338class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000339public:
joshualitt30ba4362014-08-21 20:18:45 -0700340 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000341 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000342 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700343 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000344 const char* outColor,
345 const char* inColor,
346 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000347 /**
348 * Finalizes the building process and returns the effect array. After this call, the builder
349 * becomes invalid.
350 */
351 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000352private:
joshualitt30ba4362014-08-21 20:18:45 -0700353 GrGLFragmentOnlyProgramBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000354 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000355 typedef GrGLProgramEffectsBuilder INHERITED;
356};
357
joshualitt30ba4362014-08-21 20:18:45 -0700358
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000359#endif