blob: 0eaff53b76894f4c5da12b6c5f2eb2b4f699c99e [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 */
bsalomon929f29a2014-07-17 07:55:11 -070042 static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000043
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000044 virtual ~GrGLProgramEffects();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000045
46 /**
47 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
48 * available unit to *texUnitIdx when it returns.
49 */
kkinnunen7510b222014-07-30 00:04:16 -070050 void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000051
52 /**
53 * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
54 */
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000055 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -070056 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -070057 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000058 const GrEffectStage* effectStages[]) = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000059
joshualitt30ba4362014-08-21 20:18:45 -070060 void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
61
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000062 /**
63 * Passed to GrGLEffects so they can add transformed coordinates to their shader code.
64 */
65 class TransformedCoords {
66 public:
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000067 TransformedCoords(const SkString& name, GrSLType type)
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +000068 : fName(name), fType(type) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000069 }
70
71 const char* c_str() const { return fName.c_str(); }
72 GrSLType type() const { return fType; }
73 const SkString& getName() const { return fName; }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000074
75 private:
76 SkString fName;
77 GrSLType fType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000078 };
79
80 typedef SkTArray<TransformedCoords> TransformedCoordsArray;
81
82 /**
83 * Passed to GrGLEffects so they can add texture reads to their shader code.
84 */
85 class TextureSampler {
86 public:
87 TextureSampler(UniformHandle uniform, const GrTextureAccess& access)
88 : fSamplerUniform(uniform)
89 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) {
90 SkASSERT(0 != fConfigComponentMask);
91 memcpy(fSwizzle, access.getSwizzle(), 5);
92 }
93
94 UniformHandle samplerUniform() const { return fSamplerUniform; }
95 // bitfield of GrColorComponentFlags present in the texture's config.
96 uint32_t configComponentMask() const { return fConfigComponentMask; }
97 const char* swizzle() const { return fSwizzle; }
98
99 private:
100 UniformHandle fSamplerUniform;
101 uint32_t fConfigComponentMask;
102 char fSwizzle[5];
103 };
104
105 typedef SkTArray<TextureSampler> TextureSamplerArray;
106
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000107protected:
joshualitt30ba4362014-08-21 20:18:45 -0700108
bsalomon929f29a2014-07-17 07:55:11 -0700109 /**
110 * Helpers for GenEffectMetaKey.
111 */
bsalomon63e99f72014-07-21 08:03:14 -0700112 static uint32_t GenAttribKey(const GrDrawEffect&);
113 static uint32_t GenTransformKey(const GrDrawEffect&);
114 static uint32_t GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
bsalomon929f29a2014-07-17 07:55:11 -0700115
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000116 GrGLProgramEffects(int reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000117 : fGLEffects(reserveCount)
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000118 , fSamplers(reserveCount) {
119 }
120
121 /**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000122 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
123 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
124 * lookups to their code. This method is only meant to be called during the construction phase.
125 */
joshualitt30ba4362014-08-21 20:18:45 -0700126 void emitSamplers(GrGLProgramBuilder*, const GrEffect*, TextureSamplerArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000127
128 /**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000129 * Helper for setData(). Binds all the textures for an effect.
130 */
bsalomonf99f8842014-07-07 11:54:23 -0700131 void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000132
133 struct Sampler {
134 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
135 UniformHandle fUniform;
136 int fTextureUnit;
137 };
138
139 SkTArray<GrGLEffect*> fGLEffects;
140 SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000141
142private:
joshualitt30ba4362014-08-21 20:18:45 -0700143 friend class GrGLFragmentO;
commit-bot@chromium.orga05fa062014-05-30 18:55:03 +0000144 typedef SkRefCnt INHERITED;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000145};
146
147/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000148 * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
149 */
150class GrGLProgramEffectsBuilder {
151public:
mtklein@google.comf1077f92013-11-20 15:13:49 +0000152 virtual ~GrGLProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000153 /**
154 * Emits the effect's shader code, and stores the necessary uniforms internally.
155 */
156 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700157 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000158 const char* outColor,
159 const char* inColor,
160 int stageIndex) = 0;
161};
162
163////////////////////////////////////////////////////////////////////////////////
164
165/**
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000166 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
167 */
168class GrGLVertexProgramEffects : public GrGLProgramEffects {
169public:
170 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -0700171 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -0700172 const GrGLProgramDataManager&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000173 const GrEffectStage* effectStages[]) SK_OVERRIDE;
174
175private:
joshualitt30ba4362014-08-21 20:18:45 -0700176 friend class GrGLFullProgramBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000177
178 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
179 : INHERITED(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000180 , fTransforms(reserveCount)
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000181 , fHasExplicitLocalCoords(explicitLocalCoords) {
182 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000183 /**
joshualitt30ba4362014-08-21 20:18:45 -0700184 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000185 */
joshualitt30ba4362014-08-21 20:18:45 -0700186 void emitEffect(GrGLFullProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000187 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700188 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000189 const char* outColor,
190 const char* inColor,
191 int stageIndex);
192
193 /**
194 * Helper for emitEffect(). Emits any attributes an effect may have.
195 */
joshualitt30ba4362014-08-21 20:18:45 -0700196 void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000197
198 /**
199 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
200 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
201 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
202 * of the varyings in the VS and FS as well their types are appended to the
203 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
204 */
joshualitt30ba4362014-08-21 20:18:45 -0700205 void emitTransforms(GrGLFullProgramBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700206 const GrDrawEffect&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000207 TransformedCoordsArray*);
208
209 /**
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000210 * Helper for setData(). Sets all the transform matrices for an effect.
211 */
kkinnunenec56e452014-08-25 22:21:16 -0700212 void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx);
213 void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&,
214 int effectIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000215
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000216 struct Transform {
217 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
218 UniformHandle fHandle;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000219 SkMatrix fCurrentValue;
220 };
221
kkinnunenec56e452014-08-25 22:21:16 -0700222 struct PathTransform {
223 PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
224 VaryingHandle fHandle;
225 SkMatrix fCurrentValue;
226 GrSLType fType;
227 };
228
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000229 SkTArray<SkSTArray<2, Transform, true> > fTransforms;
kkinnunenec56e452014-08-25 22:21:16 -0700230 SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000231 bool fHasExplicitLocalCoords;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000232
joshualitt30ba4362014-08-21 20:18:45 -0700233 friend class GrGLVertexProgramEffectsBuilder;
234
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000235 typedef GrGLProgramEffects INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000236};
237
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000238/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000239 * This class is used to construct a GrGLVertexProgramEffects* object.
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000240 */
241class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
242public:
joshualitt30ba4362014-08-21 20:18:45 -0700243 GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount);
mtklein@google.comf1077f92013-11-20 15:13:49 +0000244 virtual ~GrGLVertexProgramEffectsBuilder() { }
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000245 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700246 const GrEffectKey&,
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000247 const char* outColor,
248 const char* inColor,
249 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000250 /**
251 * Finalizes the building process and returns the effect array. After this call, the builder
252 * becomes invalid.
253 */
254 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000255private:
joshualitt30ba4362014-08-21 20:18:45 -0700256 GrGLFullProgramBuilder* fBuilder;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000257 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000258 typedef GrGLProgramEffectsBuilder INHERITED;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000259};
260
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000261////////////////////////////////////////////////////////////////////////////////
262
263/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000264 * This is a GrGLProgramEffects implementation that does coord transforms with
265 * the the NV_path_rendering PathTexGen functionality.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000266 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000267class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000268public:
269 virtual void setData(GrGpuGL*,
kkinnunenec56e452014-08-25 22:21:16 -0700270 GrGpu::DrawType,
kkinnunen7510b222014-07-30 00:04:16 -0700271 const GrGLProgramDataManager&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000272 const GrEffectStage* effectStages[]) SK_OVERRIDE;
273
274private:
joshualitt30ba4362014-08-21 20:18:45 -0700275 friend class GrGLFragmentOnlyProgramBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000276
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000277 GrGLPathTexGenProgramEffects(int reserveCount)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000278 : INHERITED(reserveCount)
279 , fTransforms(reserveCount) {
280 }
281
282 /**
joshualitt30ba4362014-08-21 20:18:45 -0700283 * This method is meant to only be called during the construction phase.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000284 */
joshualitt30ba4362014-08-21 20:18:45 -0700285 void emitEffect(GrGLFragmentOnlyProgramBuilder*,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000286 const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700287 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000288 const char* outColor,
289 const char* inColor,
290 int stageIndex);
291
292 /**
293 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
294 * effect. The transforms all use adjacent texture units. They either use two or three of the
295 * coordinates at a given texture unit, depending on if they need perspective interpolation.
296 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
297 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
298 * effect's emitCode() function.
299 */
joshualitt30ba4362014-08-21 20:18:45 -0700300 void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*,
bsalomon848faf02014-07-11 10:01:02 -0700301 const GrDrawEffect&,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000302 TransformedCoordsArray*);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000303
304 /**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000305 * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000306 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000307 void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000308
309 struct Transforms {
bsalomon63e99f72014-07-21 08:03:14 -0700310 Transforms(uint32_t transformKey, int texCoordIndex)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000311 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
bsalomon63e99f72014-07-21 08:03:14 -0700312 uint32_t fTransformKey;
313 int fTexCoordIndex;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000314 };
315
316 SkTArray<Transforms> fTransforms;
317
joshualitt30ba4362014-08-21 20:18:45 -0700318 friend class GrGLPathTexGenProgramEffectsBuilder;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000319 typedef GrGLProgramEffects INHERITED;
320};
321
322/**
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000323 * This class is used to construct a GrGLPathTexGenProgramEffects* object.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000324 */
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000325class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000326public:
joshualitt30ba4362014-08-21 20:18:45 -0700327 GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000328 virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000329 virtual void emitEffect(const GrEffectStage&,
bsalomon63e99f72014-07-21 08:03:14 -0700330 const GrEffectKey&,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000331 const char* outColor,
332 const char* inColor,
333 int stageIndex) SK_OVERRIDE;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000334 /**
335 * Finalizes the building process and returns the effect array. After this call, the builder
336 * becomes invalid.
337 */
338 GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000339private:
joshualitt30ba4362014-08-21 20:18:45 -0700340 GrGLFragmentOnlyProgramBuilder* fBuilder;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000341 SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000342 typedef GrGLProgramEffectsBuilder INHERITED;
343};
344
joshualitt30ba4362014-08-21 20:18:45 -0700345
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000346#endif