blob: 3fa4f15ac80f13fe55de0be6b18155f3b607f3ad [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
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
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000207void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* 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);
216 samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
217 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
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000253void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
254 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
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000264 this->emitAttributes(builder, stage);
bsalomon848faf02014-07-11 10:01:02 -0700265 this->emitTransforms(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000266 this->emitSamplers(builder, effect, &samplers);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000267
268 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000269 fGLEffects.push_back(glEffect);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000270
271 // Enclose custom code in a block to avoid namespace conflicts
272 SkString openBrace;
273 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000274 builder->vsCodeAppend(openBrace.c_str());
275 builder->fsCodeAppend(openBrace.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000276
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000277 if (glEffect->isVertexEffect()) {
278 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000279 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000280 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000281 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000282 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000283
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000284 builder->vsCodeAppend("\t}\n");
285 builder->fsCodeAppend("\t}\n");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000286}
287
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000288void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
289 const GrEffectStage& stage) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000290 int numAttributes = stage.getVertexAttribIndexCount();
291 const int* attributeIndices = stage.getVertexAttribIndices();
292 for (int a = 0; a < numAttributes; ++a) {
293 // TODO: Make addAttribute mangle the name.
294 SkString attributeName("aAttr");
295 attributeName.appendS32(attributeIndices[a]);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000296 builder->addEffectAttribute(attributeIndices[a],
bsalomonf99f8842014-07-07 11:54:23 -0700297 stage.getEffect()->vertexAttribType(a),
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000298 attributeName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000299 }
300}
301
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000302void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700303 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000304 TransformedCoordsArray* outCoords) {
305 SkTArray<Transform, true>& transforms = fTransforms.push_back();
bsalomon63e99f72014-07-21 08:03:14 -0700306 uint32_t totalKey = GenTransformKey(drawEffect);
bsalomon848faf02014-07-11 10:01:02 -0700307 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000308 transforms.push_back_n(numTransforms);
309 for (int t = 0; t < numTransforms; t++) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000310 GrSLType varyingType = kVoid_GrSLType;
311 const char* uniName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000312 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000313 case kNoPersp_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000314 uniName = "StageMatrix";
315 varyingType = kVec2f_GrSLType;
316 break;
317 case kGeneral_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000318 uniName = "StageMatrix";
319 varyingType = kVec3f_GrSLType;
320 break;
321 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000322 SkFAIL("Unexpected key.");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000323 }
324 SkString suffixedUniName;
egdaniel4c6443e2014-06-24 13:43:12 -0700325 if (0 != t) {
326 suffixedUniName.append(uniName);
327 suffixedUniName.appendf("_%i", t);
328 uniName = suffixedUniName.c_str();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000329 }
egdaniel4c6443e2014-06-24 13:43:12 -0700330 transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
331 kMat33f_GrSLType,
332 uniName,
333 &uniName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000334
335 const char* varyingName = "MatrixCoord";
336 SkString suffixedVaryingName;
337 if (0 != t) {
338 suffixedVaryingName.append(varyingName);
339 suffixedVaryingName.appendf("_%i", t);
340 varyingName = suffixedVaryingName.c_str();
341 }
342 const char* vsVaryingName;
343 const char* fsVaryingName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000344 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000345
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000346 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
347 builder->positionAttribute() :
348 builder->localCoordsAttribute();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000349 // varying = matrix * coords (logically)
egdaniel4c6443e2014-06-24 13:43:12 -0700350 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
351 if (kVec2f_GrSLType == varyingType) {
352 builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
353 vsVaryingName, uniName, coords.c_str());
354 } else {
355 builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
356 vsVaryingName, uniName, coords.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000357 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000358 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
359 (SkString(fsVaryingName), varyingType));
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000360 }
361}
362
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000363void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
kkinnunen7510b222014-07-30 00:04:16 -0700364 const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000365 const GrEffectStage* effectStages[]) {
366 int numEffects = fGLEffects.count();
367 SkASSERT(numEffects == fTransforms.count());
368 SkASSERT(numEffects == fSamplers.count());
369 for (int e = 0; e < numEffects; ++e) {
370 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
kkinnunen7510b222014-07-30 00:04:16 -0700371 fGLEffects[e]->setData(programResourceManager, drawEffect);
372 this->setTransformData(programResourceManager, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700373 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000374 }
375}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000376
kkinnunen7510b222014-07-30 00:04:16 -0700377void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000378 const GrDrawEffect& drawEffect,
379 int effectIdx) {
380 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
381 int numTransforms = transforms.count();
bsalomonf99f8842014-07-07 11:54:23 -0700382 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000383 for (int t = 0; t < numTransforms; ++t) {
egdaniel4c6443e2014-06-24 13:43:12 -0700384 SkASSERT(transforms[t].fHandle.isValid());
385 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
386 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
kkinnunen7510b222014-07-30 00:04:16 -0700387 programResourceManager.setSkMatrix(transforms[t].fHandle, matrix);
egdaniel4c6443e2014-06-24 13:43:12 -0700388 transforms[t].fCurrentValue = matrix;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000389 }
390 }
391}
392
393GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
394 int reserveCount)
395 : fBuilder(builder)
396 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
397 (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
398}
399
400void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700401 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000402 const char* outColor,
403 const char* inColor,
404 int stageIndex) {
405 SkASSERT(NULL != fProgramEffects.get());
406 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
407}
408
409////////////////////////////////////////////////////////////////////////////////
410
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000411void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000412 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700413 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000414 const char* outColor,
415 const char* inColor,
416 int stageIndex) {
417 GrDrawEffect drawEffect(stage, false);
bsalomonf99f8842014-07-07 11:54:23 -0700418 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000419 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
420 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
421
422 SkASSERT(0 == stage.getVertexAttribIndexCount());
bsalomon848faf02014-07-11 10:01:02 -0700423 this->setupPathTexGen(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000424 this->emitSamplers(builder, effect, &samplers);
425
426 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
427 fGLEffects.push_back(glEffect);
428
429 // Enclose custom code in a block to avoid namespace conflicts
430 SkString openBrace;
431 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
432 builder->fsCodeAppend(openBrace.c_str());
433
434 SkASSERT(!glEffect->isVertexEffect());
435 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
436
437 builder->fsCodeAppend("\t}\n");
438}
439
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000440void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700441 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000442 TransformedCoordsArray* outCoords) {
bsalomon848faf02014-07-11 10:01:02 -0700443 int numTransforms = drawEffect.effect()->numTransforms();
bsalomon63e99f72014-07-21 08:03:14 -0700444 uint32_t totalKey = GenTransformKey(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000445 int texCoordIndex = builder->addTexCoordSets(numTransforms);
446 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
447 SkString name;
448 for (int t = 0; t < numTransforms; ++t) {
449 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
450 kVec3f_GrSLType :
451 kVec2f_GrSLType;
452 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
453 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
454 }
455}
456
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000457void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
kkinnunen7510b222014-07-30 00:04:16 -0700458 const GrGLProgramDataManager& programResourceManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000459 const GrEffectStage* effectStages[]) {
460 int numEffects = fGLEffects.count();
461 SkASSERT(numEffects == fTransforms.count());
462 SkASSERT(numEffects == fSamplers.count());
463 for (int e = 0; e < numEffects; ++e) {
464 GrDrawEffect drawEffect(*effectStages[e], false);
kkinnunen7510b222014-07-30 00:04:16 -0700465 fGLEffects[e]->setData(programResourceManager, drawEffect);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000466 this->setPathTexGenState(gpu, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700467 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000468 }
469}
470
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000471void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000472 const GrDrawEffect& drawEffect,
473 int effectIdx) {
bsalomon63e99f72014-07-21 08:03:14 -0700474 uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000475 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
bsalomonf99f8842014-07-07 11:54:23 -0700476 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000477 for (int t = 0; t < numTransforms; ++t) {
478 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000479 case kNoPersp_MatrixType: {
480 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000481 gpu->enablePathTexGen(texCoordIndex++,
482 GrGpuGL::kST_PathTexGenComponents,
483 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000484 break;
485 }
486 case kGeneral_MatrixType: {
487 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000488 gpu->enablePathTexGen(texCoordIndex++,
489 GrGpuGL::kSTR_PathTexGenComponents,
490 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000491 break;
492 }
493 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000494 SkFAIL("Unexpected matrixs type.");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000495 }
496 }
497}
498
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000499GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000500 GrGLFragmentOnlyShaderBuilder* builder,
501 int reserveCount)
502 : fBuilder(builder)
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000503 , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000504}
505
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000506void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700507 const GrEffectKey& key,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000508 const char* outColor,
509 const char* inColor,
510 int stageIndex) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000511 SkASSERT(NULL != fProgramEffects.get());
512 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
513}