blob: 9936aa54ad975897143549bc624a0272ebe25879 [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#include "GrGLProgramEffects.h"
9#include "GrDrawEffect.h"
10#include "gl/GrGLEffect.h"
11#include "gl/GrGLShaderBuilder.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
15typedef GrGLProgramEffects::EffectKey EffectKey;
16typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
17typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
18typedef GrGLProgramEffects::TextureSampler TextureSampler;
19typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
20
21/**
22 * We specialize the vertex code for each of these matrix types.
23 */
24enum MatrixType {
egdaniel4c6443e2014-06-24 13:43:12 -070025 kNoPersp_MatrixType = 0,
26 kGeneral_MatrixType = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000027};
28
29/**
30 * The key for an individual coord transform is made up of a matrix type and a bit that
31 * indicates the source of the input coords.
32 */
33enum {
egdaniel4c6443e2014-06-24 13:43:12 -070034 kMatrixTypeKeyBits = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000035 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
36 kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
37 kTransformKeyBits = kMatrixTypeKeyBits + 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000038};
39
40namespace {
41
42/**
43 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
44 * present in the texture's config. swizzleComponentMask indicates the channels present in the
45 * shader swizzle.
46 */
47inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
48 uint32_t configComponentMask,
49 uint32_t swizzleComponentMask) {
50 if (caps.textureSwizzleSupport()) {
51 // Any remapping is handled using texture swizzling not shader modifications.
52 return false;
53 }
54 // check if the texture is alpha-only
55 if (kA_GrColorComponentFlag == configComponentMask) {
56 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
57 // we must map the swizzle 'a's to 'r'.
58 return true;
59 }
60 if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
61 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
62 // alpha-only textures smear alpha across all four channels when read.
63 return true;
64 }
65 }
66 return false;
67}
68
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000069/**
70 * Retrieves the matrix type from transformKey for the transform at transformIdx.
71 */
72MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
73 return static_cast<MatrixType>(
74 (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000075}
76
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000077/**
78 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
79 * the same coordinate set as the original GrCoordTransform if the position and local coords are
80 * identical for this program.
81 */
82GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
83 return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
84 kPosition_GrCoordSet :
85 kLocal_GrCoordSet;
86}
87
88/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000089 * Retrieves the final matrix that a transform needs to apply to its source coords.
90 */
91SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
bsalomonf99f8842014-07-07 11:54:23 -070092 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(transformIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000093 SkMatrix combined;
94 if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
95 !drawEffect.programHasExplicitLocalCoords()) {
96 combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
97 } else {
98 combined = coordTransform.getMatrix();
99 }
100 if (coordTransform.reverseY()) {
101 // combined.postScale(1,-1);
102 // combined.postTranslate(0,1);
103 combined.set(SkMatrix::kMSkewY,
104 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
105 combined.set(SkMatrix::kMScaleY,
106 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
107 combined.set(SkMatrix::kMTransY,
108 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
109 }
110 return combined;
111}
112
113}
114
115////////////////////////////////////////////////////////////////////////////////
116
bsalomon929f29a2014-07-17 07:55:11 -0700117bool GrGLProgramEffects::GenEffectMetaKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps,
118 GrEffectKeyBuilder* b) {
119
120 EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
121 EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
122 EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
123 uint32_t classID = drawEffect.effect()->getFactory().effectClassID();
124
125 // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
126 // don't fit.
127 static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
128 if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
129 return false;
130 }
131
132 uint32_t* key = b->add32n(2);
133 key[0] = (textureKey << 16 | transformKey);
134 key[1] = (classID << 16 | attribKey);
135 return true;
136}
137
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000138EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
139 EffectKey key = 0;
140 int numAttributes = drawEffect.getVertexAttribIndexCount();
141 SkASSERT(numAttributes <= 2);
142 const int* attributeIndices = drawEffect.getVertexAttribIndices();
143 for (int a = 0; a < numAttributes; ++a) {
144 EffectKey value = attributeIndices[a] << 3 * a;
145 SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
146 key |= value;
147 }
148 return key;
149}
150
151EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
152 EffectKey totalKey = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700153 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000154 for (int t = 0; t < numTransforms; ++t) {
155 EffectKey key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700156 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000157 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
158 SkMatrix::TypeMask type1;
159 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
160 type1 = drawEffect.getCoordChangeMatrix().getType();
161 } else {
162 if (drawEffect.programHasExplicitLocalCoords()) {
163 // We only make the key indicate that device coords are referenced when the local coords
164 // are not actually determined by positions. Otherwise the local coords var and position
165 // var are identical.
166 key |= kPositionCoords_Flag;
167 }
168 type1 = SkMatrix::kIdentity_Mask;
169 }
170
171 int combinedTypes = type0 | type1;
172
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000173 if (SkMatrix::kPerspective_Mask & combinedTypes) {
174 key |= kGeneral_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000175 } else {
egdaniel4c6443e2014-06-24 13:43:12 -0700176 key |= kNoPersp_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000177 }
178 key <<= kTransformKeyBits * t;
179 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
180 totalKey |= key;
181 }
182 return totalKey;
183}
184
185EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
186 EffectKey key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700187 int numTextures = drawEffect.effect()->numTextures();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000188 for (int t = 0; t < numTextures; ++t) {
bsalomonf99f8842014-07-07 11:54:23 -0700189 const GrTextureAccess& access = drawEffect.effect()->textureAccess(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000190 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
191 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
192 key |= 1 << t;
193 }
194 }
195 return key;
196}
197
198GrGLProgramEffects::~GrGLProgramEffects() {
199 int numEffects = fGLEffects.count();
200 for (int e = 0; e < numEffects; ++e) {
201 SkDELETE(fGLEffects[e]);
202 }
203}
204
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000205void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
bsalomonf99f8842014-07-07 11:54:23 -0700206 const GrEffect* effect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000207 TextureSamplerArray* outSamplers) {
208 SkTArray<Sampler, true>& samplers = fSamplers.push_back();
209 int numTextures = effect->numTextures();
210 samplers.push_back_n(numTextures);
211 SkString name;
212 for (int t = 0; t < numTextures; ++t) {
213 name.printf("Sampler%d", t);
214 samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
215 kSampler2D_GrSLType,
216 name.c_str());
217 SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
218 (samplers[t].fUniform, effect->textureAccess(t)));
219 }
220}
221
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000222void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
223 int numEffects = fGLEffects.count();
224 SkASSERT(numEffects == fSamplers.count());
225 for (int e = 0; e < numEffects; ++e) {
226 SkTArray<Sampler, true>& samplers = fSamplers[e];
227 int numSamplers = samplers.count();
228 for (int s = 0; s < numSamplers; ++s) {
229 SkASSERT(samplers[s].fUniform.isValid());
230 uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx);
231 samplers[s].fTextureUnit = (*texUnitIdx)++;
232 }
233 }
234}
235
bsalomonf99f8842014-07-07 11:54:23 -0700236void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffect* effect, int effectIdx) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000237 const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
238 int numSamplers = samplers.count();
239 SkASSERT(numSamplers == effect->numTextures());
240 for (int s = 0; s < numSamplers; ++s) {
241 SkASSERT(samplers[s].fTextureUnit >= 0);
242 const GrTextureAccess& textureAccess = effect->textureAccess(s);
243 gpu->bindTexture(samplers[s].fTextureUnit,
244 textureAccess.getParams(),
245 static_cast<GrGLTexture*>(textureAccess.getTexture()));
246 }
247}
248
249////////////////////////////////////////////////////////////////////////////////
250
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000251void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
252 const GrEffectStage& stage,
253 EffectKey key,
254 const char* outColor,
255 const char* inColor,
256 int stageIndex) {
257 GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
bsalomonf99f8842014-07-07 11:54:23 -0700258 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000259 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
260 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
261
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000262 this->emitAttributes(builder, stage);
bsalomon848faf02014-07-11 10:01:02 -0700263 this->emitTransforms(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000264 this->emitSamplers(builder, effect, &samplers);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000265
266 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000267 fGLEffects.push_back(glEffect);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000268
269 // Enclose custom code in a block to avoid namespace conflicts
270 SkString openBrace;
271 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000272 builder->vsCodeAppend(openBrace.c_str());
273 builder->fsCodeAppend(openBrace.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000274
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000275 if (glEffect->isVertexEffect()) {
276 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000277 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000278 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000279 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000280 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000281
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000282 builder->vsCodeAppend("\t}\n");
283 builder->fsCodeAppend("\t}\n");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000284}
285
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000286void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
287 const GrEffectStage& stage) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000288 int numAttributes = stage.getVertexAttribIndexCount();
289 const int* attributeIndices = stage.getVertexAttribIndices();
290 for (int a = 0; a < numAttributes; ++a) {
291 // TODO: Make addAttribute mangle the name.
292 SkString attributeName("aAttr");
293 attributeName.appendS32(attributeIndices[a]);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000294 builder->addEffectAttribute(attributeIndices[a],
bsalomonf99f8842014-07-07 11:54:23 -0700295 stage.getEffect()->vertexAttribType(a),
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000296 attributeName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000297 }
298}
299
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000300void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700301 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000302 TransformedCoordsArray* outCoords) {
303 SkTArray<Transform, true>& transforms = fTransforms.push_back();
bsalomon848faf02014-07-11 10:01:02 -0700304 EffectKey totalKey = GenTransformKey(drawEffect);
305 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000306 transforms.push_back_n(numTransforms);
307 for (int t = 0; t < numTransforms; t++) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000308 GrSLType varyingType = kVoid_GrSLType;
309 const char* uniName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000310 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000311 case kNoPersp_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000312 uniName = "StageMatrix";
313 varyingType = kVec2f_GrSLType;
314 break;
315 case kGeneral_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000316 uniName = "StageMatrix";
317 varyingType = kVec3f_GrSLType;
318 break;
319 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000320 SkFAIL("Unexpected key.");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000321 }
322 SkString suffixedUniName;
egdaniel4c6443e2014-06-24 13:43:12 -0700323 if (0 != t) {
324 suffixedUniName.append(uniName);
325 suffixedUniName.appendf("_%i", t);
326 uniName = suffixedUniName.c_str();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000327 }
egdaniel4c6443e2014-06-24 13:43:12 -0700328 transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
329 kMat33f_GrSLType,
330 uniName,
331 &uniName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000332
333 const char* varyingName = "MatrixCoord";
334 SkString suffixedVaryingName;
335 if (0 != t) {
336 suffixedVaryingName.append(varyingName);
337 suffixedVaryingName.appendf("_%i", t);
338 varyingName = suffixedVaryingName.c_str();
339 }
340 const char* vsVaryingName;
341 const char* fsVaryingName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000342 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000343
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000344 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
345 builder->positionAttribute() :
346 builder->localCoordsAttribute();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000347 // varying = matrix * coords (logically)
egdaniel4c6443e2014-06-24 13:43:12 -0700348 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
349 if (kVec2f_GrSLType == varyingType) {
350 builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
351 vsVaryingName, uniName, coords.c_str());
352 } else {
353 builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
354 vsVaryingName, uniName, coords.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000355 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000356 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
357 (SkString(fsVaryingName), varyingType));
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000358 }
359}
360
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000361void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
362 const GrGLUniformManager& uniformManager,
363 const GrEffectStage* effectStages[]) {
364 int numEffects = fGLEffects.count();
365 SkASSERT(numEffects == fTransforms.count());
366 SkASSERT(numEffects == fSamplers.count());
367 for (int e = 0; e < numEffects; ++e) {
368 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
369 fGLEffects[e]->setData(uniformManager, drawEffect);
370 this->setTransformData(uniformManager, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700371 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000372 }
373}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000374
375void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
376 const GrDrawEffect& drawEffect,
377 int effectIdx) {
378 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
379 int numTransforms = transforms.count();
bsalomonf99f8842014-07-07 11:54:23 -0700380 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000381 for (int t = 0; t < numTransforms; ++t) {
egdaniel4c6443e2014-06-24 13:43:12 -0700382 SkASSERT(transforms[t].fHandle.isValid());
383 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
384 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
385 uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
386 transforms[t].fCurrentValue = matrix;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000387 }
388 }
389}
390
391GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
392 int reserveCount)
393 : fBuilder(builder)
394 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
395 (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
396}
397
398void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
399 GrGLProgramEffects::EffectKey key,
400 const char* outColor,
401 const char* inColor,
402 int stageIndex) {
403 SkASSERT(NULL != fProgramEffects.get());
404 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
405}
406
407////////////////////////////////////////////////////////////////////////////////
408
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000409void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000410 const GrEffectStage& stage,
411 EffectKey key,
412 const char* outColor,
413 const char* inColor,
414 int stageIndex) {
415 GrDrawEffect drawEffect(stage, false);
bsalomonf99f8842014-07-07 11:54:23 -0700416 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000417 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
418 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
419
420 SkASSERT(0 == stage.getVertexAttribIndexCount());
bsalomon848faf02014-07-11 10:01:02 -0700421 this->setupPathTexGen(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000422 this->emitSamplers(builder, effect, &samplers);
423
424 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
425 fGLEffects.push_back(glEffect);
426
427 // Enclose custom code in a block to avoid namespace conflicts
428 SkString openBrace;
429 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
430 builder->fsCodeAppend(openBrace.c_str());
431
432 SkASSERT(!glEffect->isVertexEffect());
433 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
434
435 builder->fsCodeAppend("\t}\n");
436}
437
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000438void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700439 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000440 TransformedCoordsArray* outCoords) {
bsalomon848faf02014-07-11 10:01:02 -0700441 int numTransforms = drawEffect.effect()->numTransforms();
442 EffectKey totalKey = GenTransformKey(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000443 int texCoordIndex = builder->addTexCoordSets(numTransforms);
444 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
445 SkString name;
446 for (int t = 0; t < numTransforms; ++t) {
447 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
448 kVec3f_GrSLType :
449 kVec2f_GrSLType;
450 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
451 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
452 }
453}
454
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000455void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000456 const GrGLUniformManager& uniformManager,
457 const GrEffectStage* effectStages[]) {
458 int numEffects = fGLEffects.count();
459 SkASSERT(numEffects == fTransforms.count());
460 SkASSERT(numEffects == fSamplers.count());
461 for (int e = 0; e < numEffects; ++e) {
462 GrDrawEffect drawEffect(*effectStages[e], false);
463 fGLEffects[e]->setData(uniformManager, drawEffect);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000464 this->setPathTexGenState(gpu, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700465 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000466 }
467}
468
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000469void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000470 const GrDrawEffect& drawEffect,
471 int effectIdx) {
472 EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
473 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
bsalomonf99f8842014-07-07 11:54:23 -0700474 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000475 for (int t = 0; t < numTransforms; ++t) {
476 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000477 case kNoPersp_MatrixType: {
478 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000479 gpu->enablePathTexGen(texCoordIndex++,
480 GrGpuGL::kST_PathTexGenComponents,
481 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000482 break;
483 }
484 case kGeneral_MatrixType: {
485 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000486 gpu->enablePathTexGen(texCoordIndex++,
487 GrGpuGL::kSTR_PathTexGenComponents,
488 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000489 break;
490 }
491 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000492 SkFAIL("Unexpected matrixs type.");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000493 }
494 }
495}
496
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000497GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000498 GrGLFragmentOnlyShaderBuilder* builder,
499 int reserveCount)
500 : fBuilder(builder)
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000501 , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000502}
503
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000504void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
505 GrGLProgramEffects::EffectKey key,
506 const char* outColor,
507 const char* inColor,
508 int stageIndex) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000509 SkASSERT(NULL != fProgramEffects.get());
510 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
511}