blob: efb64fe64029c2fde2bf750e52c1f314d1c676ec [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
joshualitt30ba4362014-08-21 20:18:45 -07008#include "gl/builders/GrGLProgramBuilder.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +00009#include "GrGLProgramEffects.h"
10#include "GrDrawEffect.h"
11#include "gl/GrGLEffect.h"
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000012#include "gl/GrGLVertexEffect.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000013#include "gl/GrGpuGL.h"
14
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000015typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
16typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
17typedef GrGLProgramEffects::TextureSampler TextureSampler;
18typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
19
20/**
21 * We specialize the vertex code for each of these matrix types.
22 */
23enum MatrixType {
egdaniel4c6443e2014-06-24 13:43:12 -070024 kNoPersp_MatrixType = 0,
25 kGeneral_MatrixType = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000026};
27
28/**
29 * The key for an individual coord transform is made up of a matrix type and a bit that
30 * indicates the source of the input coords.
31 */
32enum {
egdaniel4c6443e2014-06-24 13:43:12 -070033 kMatrixTypeKeyBits = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000034 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
35 kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
36 kTransformKeyBits = kMatrixTypeKeyBits + 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000037};
38
39namespace {
40
41/**
42 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
43 * present in the texture's config. swizzleComponentMask indicates the channels present in the
44 * shader swizzle.
45 */
46inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
47 uint32_t configComponentMask,
48 uint32_t swizzleComponentMask) {
49 if (caps.textureSwizzleSupport()) {
50 // Any remapping is handled using texture swizzling not shader modifications.
51 return false;
52 }
53 // check if the texture is alpha-only
54 if (kA_GrColorComponentFlag == configComponentMask) {
55 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
56 // we must map the swizzle 'a's to 'r'.
57 return true;
58 }
59 if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
60 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
61 // alpha-only textures smear alpha across all four channels when read.
62 return true;
63 }
64 }
65 return false;
66}
67
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000068/**
69 * Retrieves the matrix type from transformKey for the transform at transformIdx.
70 */
bsalomon63e99f72014-07-21 08:03:14 -070071MatrixType get_matrix_type(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000072 return static_cast<MatrixType>(
73 (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000074}
75
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000076/**
77 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
78 * the same coordinate set as the original GrCoordTransform if the position and local coords are
79 * identical for this program.
80 */
bsalomon63e99f72014-07-21 08:03:14 -070081GrCoordSet get_source_coords(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000082 return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
83 kPosition_GrCoordSet :
84 kLocal_GrCoordSet;
85}
86
87/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000088 * Retrieves the final matrix that a transform needs to apply to its source coords.
89 */
90SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
bsalomonf99f8842014-07-07 11:54:23 -070091 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(transformIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000092 SkMatrix combined;
bsalomon06736762014-08-04 10:56:39 -070093
94 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
95 // If we have explicit local coords then we shouldn't need a coord change.
96 SkASSERT(!drawEffect.programHasExplicitLocalCoords() ||
97 drawEffect.getCoordChangeMatrix().isIdentity());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000098 combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
99 } else {
100 combined = coordTransform.getMatrix();
101 }
102 if (coordTransform.reverseY()) {
103 // combined.postScale(1,-1);
104 // combined.postTranslate(0,1);
105 combined.set(SkMatrix::kMSkewY,
106 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
107 combined.set(SkMatrix::kMScaleY,
108 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
109 combined.set(SkMatrix::kMTransY,
110 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
111 }
112 return combined;
113}
114
115}
116
117////////////////////////////////////////////////////////////////////////////////
118
bsalomon929f29a2014-07-17 07:55:11 -0700119bool GrGLProgramEffects::GenEffectMetaKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps,
120 GrEffectKeyBuilder* b) {
121
bsalomon63e99f72014-07-21 08:03:14 -0700122 uint32_t textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
123 uint32_t transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
124 uint32_t attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
bsalomon929f29a2014-07-17 07:55:11 -0700125 uint32_t classID = drawEffect.effect()->getFactory().effectClassID();
126
127 // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
128 // don't fit.
129 static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
130 if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
131 return false;
132 }
133
134 uint32_t* key = b->add32n(2);
135 key[0] = (textureKey << 16 | transformKey);
136 key[1] = (classID << 16 | attribKey);
137 return true;
138}
139
bsalomon63e99f72014-07-21 08:03:14 -0700140uint32_t GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
141 uint32_t key = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000142 int numAttributes = drawEffect.getVertexAttribIndexCount();
143 SkASSERT(numAttributes <= 2);
144 const int* attributeIndices = drawEffect.getVertexAttribIndices();
145 for (int a = 0; a < numAttributes; ++a) {
bsalomon63e99f72014-07-21 08:03:14 -0700146 uint32_t value = attributeIndices[a] << 3 * a;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000147 SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
148 key |= value;
149 }
150 return key;
151}
152
bsalomon63e99f72014-07-21 08:03:14 -0700153uint32_t GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
154 uint32_t totalKey = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700155 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000156 for (int t = 0; t < numTransforms; ++t) {
bsalomon63e99f72014-07-21 08:03:14 -0700157 uint32_t key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700158 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000159 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
160 SkMatrix::TypeMask type1;
161 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
162 type1 = drawEffect.getCoordChangeMatrix().getType();
163 } else {
164 if (drawEffect.programHasExplicitLocalCoords()) {
165 // We only make the key indicate that device coords are referenced when the local coords
166 // are not actually determined by positions. Otherwise the local coords var and position
167 // var are identical.
168 key |= kPositionCoords_Flag;
169 }
170 type1 = SkMatrix::kIdentity_Mask;
171 }
172
173 int combinedTypes = type0 | type1;
174
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000175 if (SkMatrix::kPerspective_Mask & combinedTypes) {
176 key |= kGeneral_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000177 } else {
egdaniel4c6443e2014-06-24 13:43:12 -0700178 key |= kNoPersp_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000179 }
180 key <<= kTransformKeyBits * t;
181 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
182 totalKey |= key;
183 }
184 return totalKey;
185}
186
bsalomon63e99f72014-07-21 08:03:14 -0700187uint32_t GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
188 uint32_t key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700189 int numTextures = drawEffect.effect()->numTextures();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000190 for (int t = 0; t < numTextures; ++t) {
bsalomonf99f8842014-07-07 11:54:23 -0700191 const GrTextureAccess& access = drawEffect.effect()->textureAccess(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000192 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
193 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
194 key |= 1 << t;
195 }
196 }
197 return key;
198}
199
200GrGLProgramEffects::~GrGLProgramEffects() {
201 int numEffects = fGLEffects.count();
202 for (int e = 0; e < numEffects; ++e) {
203 SkDELETE(fGLEffects[e]);
204 }
205}
206
joshualitt30ba4362014-08-21 20:18:45 -0700207void GrGLProgramEffects::emitSamplers(GrGLProgramBuilder* builder,
bsalomonf99f8842014-07-07 11:54:23 -0700208 const GrEffect* effect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000209 TextureSamplerArray* outSamplers) {
210 SkTArray<Sampler, true>& samplers = fSamplers.push_back();
211 int numTextures = effect->numTextures();
212 samplers.push_back_n(numTextures);
213 SkString name;
214 for (int t = 0; t < numTextures; ++t) {
215 name.printf("Sampler%d", t);
joshualitt30ba4362014-08-21 20:18:45 -0700216 samplers[t].fUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000217 kSampler2D_GrSLType,
218 name.c_str());
219 SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
220 (samplers[t].fUniform, effect->textureAccess(t)));
221 }
222}
223
kkinnunen7510b222014-07-30 00:04:16 -0700224void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000225 int numEffects = fGLEffects.count();
226 SkASSERT(numEffects == fSamplers.count());
227 for (int e = 0; e < numEffects; ++e) {
228 SkTArray<Sampler, true>& samplers = fSamplers[e];
229 int numSamplers = samplers.count();
230 for (int s = 0; s < numSamplers; ++s) {
231 SkASSERT(samplers[s].fUniform.isValid());
kkinnunen7510b222014-07-30 00:04:16 -0700232 programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000233 samplers[s].fTextureUnit = (*texUnitIdx)++;
234 }
235 }
236}
237
bsalomonf99f8842014-07-07 11:54:23 -0700238void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffect* effect, int effectIdx) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000239 const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
240 int numSamplers = samplers.count();
241 SkASSERT(numSamplers == effect->numTextures());
242 for (int s = 0; s < numSamplers; ++s) {
243 SkASSERT(samplers[s].fTextureUnit >= 0);
244 const GrTextureAccess& textureAccess = effect->textureAccess(s);
245 gpu->bindTexture(samplers[s].fTextureUnit,
246 textureAccess.getParams(),
247 static_cast<GrGLTexture*>(textureAccess.getTexture()));
248 }
249}
250
251////////////////////////////////////////////////////////////////////////////////
252
joshualitt30ba4362014-08-21 20:18:45 -0700253void GrGLVertexProgramEffects::emitEffect(GrGLFullProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000254 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700255 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000256 const char* outColor,
257 const char* inColor,
258 int stageIndex) {
259 GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
bsalomonf99f8842014-07-07 11:54:23 -0700260 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000261 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
262 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
263
joshualitt30ba4362014-08-21 20:18:45 -0700264 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
265 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
266 vsBuilder->emitAttributes(stage);
bsalomon848faf02014-07-11 10:01:02 -0700267 this->emitTransforms(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000268 this->emitSamplers(builder, effect, &samplers);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000269
270 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000271 fGLEffects.push_back(glEffect);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000272
273 // Enclose custom code in a block to avoid namespace conflicts
274 SkString openBrace;
275 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700276 fsBuilder->codeAppend(openBrace.c_str());
277 vsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000278
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000279 if (glEffect->isVertexEffect()) {
280 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000281 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000282 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000283 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000284 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000285
joshualitt30ba4362014-08-21 20:18:45 -0700286 vsBuilder->codeAppend("\t}\n");
287 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000288}
289
joshualitt30ba4362014-08-21 20:18:45 -0700290void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700291 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000292 TransformedCoordsArray* outCoords) {
293 SkTArray<Transform, true>& transforms = fTransforms.push_back();
bsalomon63e99f72014-07-21 08:03:14 -0700294 uint32_t totalKey = GenTransformKey(drawEffect);
bsalomon848faf02014-07-11 10:01:02 -0700295 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000296 transforms.push_back_n(numTransforms);
297 for (int t = 0; t < numTransforms; t++) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000298 GrSLType varyingType = kVoid_GrSLType;
299 const char* uniName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000300 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000301 case kNoPersp_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000302 uniName = "StageMatrix";
303 varyingType = kVec2f_GrSLType;
304 break;
305 case kGeneral_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000306 uniName = "StageMatrix";
307 varyingType = kVec3f_GrSLType;
308 break;
309 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000310 SkFAIL("Unexpected key.");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000311 }
312 SkString suffixedUniName;
egdaniel4c6443e2014-06-24 13:43:12 -0700313 if (0 != t) {
314 suffixedUniName.append(uniName);
315 suffixedUniName.appendf("_%i", t);
316 uniName = suffixedUniName.c_str();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000317 }
joshualitt30ba4362014-08-21 20:18:45 -0700318 transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
egdaniel4c6443e2014-06-24 13:43:12 -0700319 kMat33f_GrSLType,
320 uniName,
321 &uniName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000322
323 const char* varyingName = "MatrixCoord";
324 SkString suffixedVaryingName;
325 if (0 != t) {
326 suffixedVaryingName.append(varyingName);
327 suffixedVaryingName.appendf("_%i", t);
328 varyingName = suffixedVaryingName.c_str();
329 }
330 const char* vsVaryingName;
331 const char* fsVaryingName;
joshualitt30ba4362014-08-21 20:18:45 -0700332 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000333 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000334
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000335 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
joshualitt30ba4362014-08-21 20:18:45 -0700336 vsBuilder->positionAttribute() :
337 vsBuilder->localCoordsAttribute();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000338 // varying = matrix * coords (logically)
egdaniel4c6443e2014-06-24 13:43:12 -0700339 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
340 if (kVec2f_GrSLType == varyingType) {
joshualitt30ba4362014-08-21 20:18:45 -0700341 vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700342 vsVaryingName, uniName, coords.c_str());
343 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700344 vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700345 vsVaryingName, uniName, coords.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000346 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000347 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
348 (SkString(fsVaryingName), varyingType));
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000349 }
350}
351
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000352void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
kkinnunen7510b222014-07-30 00:04:16 -0700353 const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000354 const GrEffectStage* effectStages[]) {
355 int numEffects = fGLEffects.count();
356 SkASSERT(numEffects == fTransforms.count());
357 SkASSERT(numEffects == fSamplers.count());
358 for (int e = 0; e < numEffects; ++e) {
359 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
kkinnunen7510b222014-07-30 00:04:16 -0700360 fGLEffects[e]->setData(programResourceManager, drawEffect);
361 this->setTransformData(programResourceManager, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700362 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000363 }
364}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000365
kkinnunen7510b222014-07-30 00:04:16 -0700366void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000367 const GrDrawEffect& drawEffect,
368 int effectIdx) {
369 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
370 int numTransforms = transforms.count();
bsalomonf99f8842014-07-07 11:54:23 -0700371 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000372 for (int t = 0; t < numTransforms; ++t) {
egdaniel4c6443e2014-06-24 13:43:12 -0700373 SkASSERT(transforms[t].fHandle.isValid());
374 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
375 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
kkinnunen7510b222014-07-30 00:04:16 -0700376 programResourceManager.setSkMatrix(transforms[t].fHandle, matrix);
egdaniel4c6443e2014-06-24 13:43:12 -0700377 transforms[t].fCurrentValue = matrix;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000378 }
379 }
380}
381
joshualitt30ba4362014-08-21 20:18:45 -0700382GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000383 int reserveCount)
384 : fBuilder(builder)
385 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
joshualitt30ba4362014-08-21 20:18:45 -0700386 (reserveCount,
387 fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000388}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000389void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700390 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000391 const char* outColor,
392 const char* inColor,
393 int stageIndex) {
394 SkASSERT(NULL != fProgramEffects.get());
395 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
396}
397
398////////////////////////////////////////////////////////////////////////////////
399
joshualitt30ba4362014-08-21 20:18:45 -0700400void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000401 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700402 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000403 const char* outColor,
404 const char* inColor,
405 int stageIndex) {
406 GrDrawEffect drawEffect(stage, false);
bsalomonf99f8842014-07-07 11:54:23 -0700407 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000408 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
409 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
410
411 SkASSERT(0 == stage.getVertexAttribIndexCount());
bsalomon848faf02014-07-11 10:01:02 -0700412 this->setupPathTexGen(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000413 this->emitSamplers(builder, effect, &samplers);
414
415 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
416 fGLEffects.push_back(glEffect);
417
joshualitt30ba4362014-08-21 20:18:45 -0700418 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000419 // Enclose custom code in a block to avoid namespace conflicts
420 SkString openBrace;
421 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700422 fsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000423
424 SkASSERT(!glEffect->isVertexEffect());
425 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
426
joshualitt30ba4362014-08-21 20:18:45 -0700427 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000428}
429
joshualitt30ba4362014-08-21 20:18:45 -0700430void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700431 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000432 TransformedCoordsArray* outCoords) {
bsalomon848faf02014-07-11 10:01:02 -0700433 int numTransforms = drawEffect.effect()->numTransforms();
bsalomon63e99f72014-07-21 08:03:14 -0700434 uint32_t totalKey = GenTransformKey(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000435 int texCoordIndex = builder->addTexCoordSets(numTransforms);
436 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
437 SkString name;
438 for (int t = 0; t < numTransforms; ++t) {
439 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
440 kVec3f_GrSLType :
441 kVec2f_GrSLType;
442 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
443 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
444 }
445}
446
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000447void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
kkinnunen7510b222014-07-30 00:04:16 -0700448 const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000449 const GrEffectStage* effectStages[]) {
450 int numEffects = fGLEffects.count();
451 SkASSERT(numEffects == fTransforms.count());
452 SkASSERT(numEffects == fSamplers.count());
453 for (int e = 0; e < numEffects; ++e) {
454 GrDrawEffect drawEffect(*effectStages[e], false);
kkinnunen7510b222014-07-30 00:04:16 -0700455 fGLEffects[e]->setData(programResourceManager, drawEffect);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000456 this->setPathTexGenState(gpu, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700457 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000458 }
459}
460
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000461void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000462 const GrDrawEffect& drawEffect,
463 int effectIdx) {
bsalomon63e99f72014-07-21 08:03:14 -0700464 uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000465 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
bsalomonf99f8842014-07-07 11:54:23 -0700466 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000467 for (int t = 0; t < numTransforms; ++t) {
468 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000469 case kNoPersp_MatrixType: {
470 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700471 gpu->glPathRendering()->enablePathTexGen(
472 texCoordIndex++,
473 GrGLPathRendering::kST_PathTexGenComponents,
474 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000475 break;
476 }
477 case kGeneral_MatrixType: {
478 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700479 gpu->glPathRendering()->enablePathTexGen(
480 texCoordIndex++,
481 GrGLPathRendering::kSTR_PathTexGenComponents,
482 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000483 break;
484 }
485 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000486 SkFAIL("Unexpected matrixs type.");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000487 }
488 }
489}
490
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000491GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
joshualitt30ba4362014-08-21 20:18:45 -0700492 GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000493 int reserveCount)
494 : fBuilder(builder)
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000495 , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000496}
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000497void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700498 const GrEffectKey& key,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000499 const char* outColor,
500 const char* inColor,
501 int stageIndex) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000502 SkASSERT(NULL != fProgramEffects.get());
503 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
504}
joshualitt30ba4362014-08-21 20:18:45 -0700505