blob: 30cec29a8e7d03c686ca6a2b12708ed8069875d3 [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"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +00009#include "gl/GrGLEffect.h"
kkinnunenec56e452014-08-25 22:21:16 -070010#include "gl/GrGLPathRendering.h"
joshualitt408d6122014-09-17 07:00:35 -070011#include "gl/builders/GrGLFullProgramBuilder.h"
12#include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
joshualitt249af152014-09-15 11:41:13 -070013#include "gl/GrGLGeometryProcessor.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000014#include "gl/GrGpuGL.h"
15
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000016typedef 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 */
bsalomon63e99f72014-07-21 08:03:14 -070072MatrixType get_matrix_type(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000073 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 */
bsalomon63e99f72014-07-21 08:03:14 -070082GrCoordSet get_source_coords(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000083 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 */
joshualitt49586be2014-09-16 08:21:41 -070091SkMatrix get_transform_matrix(const GrEffectStage& effectStage,
92 bool useExplicitLocalCoords,
93 int transformIdx) {
94 const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(transformIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000095 SkMatrix combined;
bsalomon06736762014-08-04 10:56:39 -070096
97 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
98 // If we have explicit local coords then we shouldn't need a coord change.
joshualitt49586be2014-09-16 08:21:41 -070099 const SkMatrix& ccm =
100 useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
101 combined.setConcat(coordTransform.getMatrix(), ccm);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000102 } else {
103 combined = coordTransform.getMatrix();
104 }
105 if (coordTransform.reverseY()) {
106 // combined.postScale(1,-1);
107 // combined.postTranslate(0,1);
108 combined.set(SkMatrix::kMSkewY,
109 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
110 combined.set(SkMatrix::kMScaleY,
111 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
112 combined.set(SkMatrix::kMTransY,
113 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
114 }
115 return combined;
116}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000117}
118
119////////////////////////////////////////////////////////////////////////////////
120
joshualitt49586be2014-09-16 08:21:41 -0700121bool GrGLProgramEffects::GenEffectMetaKey(const GrEffectStage& effectStage,
122 bool useExplicitLocalCoords,
123 const GrGLCaps& caps,
bsalomon929f29a2014-07-17 07:55:11 -0700124 GrEffectKeyBuilder* b) {
125
joshualitt49586be2014-09-16 08:21:41 -0700126 uint32_t textureKey = GrGLProgramEffects::GenTextureKey(effectStage.getEffect(), caps);
127 uint32_t transformKey = GrGLProgramEffects::GenTransformKey(effectStage,useExplicitLocalCoords);
128 uint32_t attribKey = GrGLProgramEffects::GenAttribKey(effectStage.getEffect());
129 uint32_t classID = effectStage.getEffect()->getFactory().effectClassID();
bsalomon929f29a2014-07-17 07:55:11 -0700130
131 // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
132 // don't fit.
133 static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
134 if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
135 return false;
136 }
137
138 uint32_t* key = b->add32n(2);
139 key[0] = (textureKey << 16 | transformKey);
140 key[1] = (classID << 16 | attribKey);
141 return true;
142}
143
joshualitt49586be2014-09-16 08:21:41 -0700144uint32_t GrGLProgramEffects::GenAttribKey(const GrEffect* effect) {
bsalomon63e99f72014-07-21 08:03:14 -0700145 uint32_t key = 0;
joshualitt249af152014-09-15 11:41:13 -0700146
joshualitt49586be2014-09-16 08:21:41 -0700147 const GrEffect::VertexAttribArray& vars = effect->getVertexAttribs();
joshualitt249af152014-09-15 11:41:13 -0700148 int numAttributes = vars.count();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000149 SkASSERT(numAttributes <= 2);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000150 for (int a = 0; a < numAttributes; ++a) {
joshualitt249af152014-09-15 11:41:13 -0700151 uint32_t value = 1 << a;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000152 key |= value;
153 }
154 return key;
155}
156
joshualitt49586be2014-09-16 08:21:41 -0700157uint32_t GrGLProgramEffects::GenTransformKey(const GrEffectStage& effectStage,
158 bool useExplicitLocalCoords) {
bsalomon63e99f72014-07-21 08:03:14 -0700159 uint32_t totalKey = 0;
joshualitt49586be2014-09-16 08:21:41 -0700160 int numTransforms = effectStage.getEffect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000161 for (int t = 0; t < numTransforms; ++t) {
bsalomon63e99f72014-07-21 08:03:14 -0700162 uint32_t key = 0;
joshualitt49586be2014-09-16 08:21:41 -0700163 const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000164 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
joshualitt49586be2014-09-16 08:21:41 -0700165 SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
166 if (kLocal_GrCoordSet == coordTransform.sourceCoords() && !useExplicitLocalCoords) {
167 type1 = effectStage.getCoordChangeMatrix().getType();
168 } else if (kPosition_GrCoordSet == coordTransform.sourceCoords() && useExplicitLocalCoords) {
169 // We only make the key indicate that device coords are referenced when the local coords
170 // are not actually determined by positions. Otherwise the local coords var and position
171 // var are identical.
172 key |= kPositionCoords_Flag;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000173 }
174
175 int combinedTypes = type0 | type1;
176
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000177 if (SkMatrix::kPerspective_Mask & combinedTypes) {
178 key |= kGeneral_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000179 } else {
egdaniel4c6443e2014-06-24 13:43:12 -0700180 key |= kNoPersp_MatrixType;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000181 }
182 key <<= kTransformKeyBits * t;
183 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
184 totalKey |= key;
185 }
186 return totalKey;
187}
188
joshualitt49586be2014-09-16 08:21:41 -0700189uint32_t GrGLProgramEffects::GenTextureKey(const GrEffect* effect, const GrGLCaps& caps) {
bsalomon63e99f72014-07-21 08:03:14 -0700190 uint32_t key = 0;
joshualitt49586be2014-09-16 08:21:41 -0700191 int numTextures = effect->numTextures();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000192 for (int t = 0; t < numTextures; ++t) {
joshualitt49586be2014-09-16 08:21:41 -0700193 const GrTextureAccess& access = effect->textureAccess(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000194 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
195 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
196 key |= 1 << t;
197 }
198 }
199 return key;
200}
201
202GrGLProgramEffects::~GrGLProgramEffects() {
203 int numEffects = fGLEffects.count();
204 for (int e = 0; e < numEffects; ++e) {
205 SkDELETE(fGLEffects[e]);
206 }
207}
208
joshualitt30ba4362014-08-21 20:18:45 -0700209void GrGLProgramEffects::emitSamplers(GrGLProgramBuilder* builder,
joshualitt49586be2014-09-16 08:21:41 -0700210 const GrEffect& effect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000211 TextureSamplerArray* outSamplers) {
212 SkTArray<Sampler, true>& samplers = fSamplers.push_back();
joshualitt49586be2014-09-16 08:21:41 -0700213 int numTextures = effect.numTextures();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000214 samplers.push_back_n(numTextures);
215 SkString name;
216 for (int t = 0; t < numTextures; ++t) {
217 name.printf("Sampler%d", t);
joshualitt30ba4362014-08-21 20:18:45 -0700218 samplers[t].fUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000219 kSampler2D_GrSLType,
220 name.c_str());
221 SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
joshualitt49586be2014-09-16 08:21:41 -0700222 (samplers[t].fUniform, effect.textureAccess(t)));
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000223 }
224}
225
kkinnunen7510b222014-07-30 00:04:16 -0700226void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000227 int numEffects = fGLEffects.count();
228 SkASSERT(numEffects == fSamplers.count());
229 for (int e = 0; e < numEffects; ++e) {
230 SkTArray<Sampler, true>& samplers = fSamplers[e];
231 int numSamplers = samplers.count();
232 for (int s = 0; s < numSamplers; ++s) {
233 SkASSERT(samplers[s].fUniform.isValid());
kkinnunen7510b222014-07-30 00:04:16 -0700234 programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000235 samplers[s].fTextureUnit = (*texUnitIdx)++;
236 }
237 }
238}
239
joshualitt49586be2014-09-16 08:21:41 -0700240void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffect& effect, int effectIdx) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000241 const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
242 int numSamplers = samplers.count();
joshualitt49586be2014-09-16 08:21:41 -0700243 SkASSERT(numSamplers == effect.numTextures());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000244 for (int s = 0; s < numSamplers; ++s) {
245 SkASSERT(samplers[s].fTextureUnit >= 0);
joshualitt49586be2014-09-16 08:21:41 -0700246 const GrTextureAccess& textureAccess = effect.textureAccess(s);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000247 gpu->bindTexture(samplers[s].fTextureUnit,
248 textureAccess.getParams(),
249 static_cast<GrGLTexture*>(textureAccess.getTexture()));
250 }
251}
252
253////////////////////////////////////////////////////////////////////////////////
254
joshualitt30ba4362014-08-21 20:18:45 -0700255void GrGLVertexProgramEffects::emitEffect(GrGLFullProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000256 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700257 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000258 const char* outColor,
259 const char* inColor,
260 int stageIndex) {
joshualitt49586be2014-09-16 08:21:41 -0700261 const GrEffect& effect = *stage.getEffect();
262 SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
263 SkSTArray<4, TextureSampler> samplers(effect.numTextures());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000264
joshualitt30ba4362014-08-21 20:18:45 -0700265 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
266 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
267 vsBuilder->emitAttributes(stage);
joshualitt49586be2014-09-16 08:21:41 -0700268 this->emitTransforms(builder, stage, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000269 this->emitSamplers(builder, effect, &samplers);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000270
joshualitt49586be2014-09-16 08:21:41 -0700271 GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000272 fGLEffects.push_back(glEffect);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000273
274 // Enclose custom code in a block to avoid namespace conflicts
275 SkString openBrace;
276 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700277 fsBuilder->codeAppend(openBrace.c_str());
278 vsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000279
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000280 if (glEffect->isVertexEffect()) {
joshualitt249af152014-09-15 11:41:13 -0700281 GrGLGeometryProcessor* vertexEffect = static_cast<GrGLGeometryProcessor*>(glEffect);
joshualitt49586be2014-09-16 08:21:41 -0700282 vertexEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000283 } else {
joshualitt49586be2014-09-16 08:21:41 -0700284 glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000285 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000286
joshualitt30ba4362014-08-21 20:18:45 -0700287 vsBuilder->codeAppend("\t}\n");
288 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000289}
290
joshualitt30ba4362014-08-21 20:18:45 -0700291void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
joshualitt49586be2014-09-16 08:21:41 -0700292 const GrEffectStage& effectStage,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000293 TransformedCoordsArray* outCoords) {
294 SkTArray<Transform, true>& transforms = fTransforms.push_back();
joshualitt49586be2014-09-16 08:21:41 -0700295 uint32_t totalKey = GenTransformKey(effectStage, fHasExplicitLocalCoords);
296 int numTransforms = effectStage.getEffect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000297 transforms.push_back_n(numTransforms);
kkinnunenec56e452014-08-25 22:21:16 -0700298
299 SkTArray<PathTransform, true>* pathTransforms = NULL;
300 const GrGLCaps* glCaps = builder->ctxInfo().caps();
301 if (glCaps->pathRenderingSupport() &&
302 builder->gpu()->glPathRendering()->texturingMode() ==
303 GrGLPathRendering::SeparableShaders_TexturingMode) {
304 pathTransforms = &fPathTransforms.push_back();
305 pathTransforms->push_back_n(numTransforms);
306 }
307
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000308 for (int t = 0; t < numTransforms; t++) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000309 GrSLType varyingType = kVoid_GrSLType;
310 const char* uniName;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000311 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000312 case kNoPersp_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000313 uniName = "StageMatrix";
314 varyingType = kVec2f_GrSLType;
315 break;
316 case kGeneral_MatrixType:
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000317 uniName = "StageMatrix";
318 varyingType = kVec3f_GrSLType;
319 break;
320 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000321 SkFAIL("Unexpected key.");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000322 }
323 SkString suffixedUniName;
egdaniel4c6443e2014-06-24 13:43:12 -0700324 if (0 != t) {
325 suffixedUniName.append(uniName);
326 suffixedUniName.appendf("_%i", t);
327 uniName = suffixedUniName.c_str();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000328 }
joshualitt30ba4362014-08-21 20:18:45 -0700329 transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
egdaniel4c6443e2014-06-24 13:43:12 -0700330 kMat33f_GrSLType,
331 uniName,
332 &uniName);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000333
334 const char* varyingName = "MatrixCoord";
335 SkString suffixedVaryingName;
336 if (0 != t) {
337 suffixedVaryingName.append(varyingName);
338 suffixedVaryingName.appendf("_%i", t);
339 varyingName = suffixedVaryingName.c_str();
340 }
341 const char* vsVaryingName;
342 const char* fsVaryingName;
joshualitt30ba4362014-08-21 20:18:45 -0700343 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
kkinnunenec56e452014-08-25 22:21:16 -0700344 if (pathTransforms) {
345 (*pathTransforms)[t].fHandle =
346 builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
347 (*pathTransforms)[t].fType = varyingType;
348 } else {
349 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
350 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000351
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000352 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
joshualitt30ba4362014-08-21 20:18:45 -0700353 vsBuilder->positionAttribute() :
354 vsBuilder->localCoordsAttribute();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000355 // varying = matrix * coords (logically)
egdaniel4c6443e2014-06-24 13:43:12 -0700356 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
357 if (kVec2f_GrSLType == varyingType) {
joshualitt30ba4362014-08-21 20:18:45 -0700358 vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700359 vsVaryingName, uniName, coords.c_str());
360 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700361 vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700362 vsVaryingName, uniName, coords.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000363 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000364 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
365 (SkString(fsVaryingName), varyingType));
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000366 }
367}
368
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000369void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
kkinnunenec56e452014-08-25 22:21:16 -0700370 GrGpu::DrawType drawType,
371 const GrGLProgramDataManager& programDataManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000372 const GrEffectStage* effectStages[]) {
373 int numEffects = fGLEffects.count();
374 SkASSERT(numEffects == fTransforms.count());
375 SkASSERT(numEffects == fSamplers.count());
376 for (int e = 0; e < numEffects; ++e) {
joshualitt49586be2014-09-16 08:21:41 -0700377 const GrEffectStage& effectStage = *effectStages[e];
378 const GrEffect& effect = *effectStage.getEffect();
379 fGLEffects[e]->setData(programDataManager, effect);
kkinnunenec56e452014-08-25 22:21:16 -0700380 if (GrGpu::IsPathRenderingDrawType(drawType)) {
joshualitt49586be2014-09-16 08:21:41 -0700381 this->setPathTransformData(gpu, programDataManager, effectStage, e);
kkinnunenec56e452014-08-25 22:21:16 -0700382 } else {
joshualitt49586be2014-09-16 08:21:41 -0700383 this->setTransformData(gpu, programDataManager, effectStage, e);
kkinnunenec56e452014-08-25 22:21:16 -0700384 }
385
joshualitt49586be2014-09-16 08:21:41 -0700386 this->bindTextures(gpu, effect, e);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000387 }
388}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000389
joshualittbd769d02014-09-04 08:56:46 -0700390void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
391 GrGpu::DrawType drawType,
392 const GrGLProgramDataManager& programDataManager,
393 const GrEffectStage* effectStage) {
394 SkASSERT(1 == fTransforms.count());
395 SkASSERT(1 == fSamplers.count());
396 SkASSERT(1 == fGLEffects.count());
joshualitt49586be2014-09-16 08:21:41 -0700397 const GrEffect& effect = *effectStage->getEffect();
398 fGLEffects[0]->setData(programDataManager, effect);
joshualittbd769d02014-09-04 08:56:46 -0700399 if (GrGpu::IsPathRenderingDrawType(drawType)) {
joshualitt49586be2014-09-16 08:21:41 -0700400 this->setPathTransformData(gpu, programDataManager, *effectStage, 0);
joshualittbd769d02014-09-04 08:56:46 -0700401 } else {
joshualitt49586be2014-09-16 08:21:41 -0700402 this->setTransformData(gpu, programDataManager, *effectStage, 0);
joshualittbd769d02014-09-04 08:56:46 -0700403 }
404
joshualitt49586be2014-09-16 08:21:41 -0700405 this->bindTextures(gpu, effect, 0);
joshualittbd769d02014-09-04 08:56:46 -0700406}
407
kkinnunenec56e452014-08-25 22:21:16 -0700408void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
409 const GrGLProgramDataManager& pdman,
joshualitt49586be2014-09-16 08:21:41 -0700410 const GrEffectStage& effectStage,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000411 int effectIdx) {
412 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
413 int numTransforms = transforms.count();
joshualitt49586be2014-09-16 08:21:41 -0700414 SkASSERT(numTransforms == effectStage.getEffect()->numTransforms());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000415 for (int t = 0; t < numTransforms; ++t) {
egdaniel4c6443e2014-06-24 13:43:12 -0700416 SkASSERT(transforms[t].fHandle.isValid());
joshualitt49586be2014-09-16 08:21:41 -0700417 const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
egdaniel4c6443e2014-06-24 13:43:12 -0700418 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
kkinnunenec56e452014-08-25 22:21:16 -0700419 pdman.setSkMatrix(transforms[t].fHandle, matrix);
egdaniel4c6443e2014-06-24 13:43:12 -0700420 transforms[t].fCurrentValue = matrix;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000421 }
422 }
423}
424
kkinnunenec56e452014-08-25 22:21:16 -0700425void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
426 const GrGLProgramDataManager& pdman,
joshualitt49586be2014-09-16 08:21:41 -0700427 const GrEffectStage& effectStage,
kkinnunenec56e452014-08-25 22:21:16 -0700428 int effectIdx) {
429 SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
430 int numTransforms = transforms.count();
joshualitt49586be2014-09-16 08:21:41 -0700431 SkASSERT(numTransforms == effectStage.getEffect()->numTransforms());
kkinnunenec56e452014-08-25 22:21:16 -0700432 for (int t = 0; t < numTransforms; ++t) {
433 SkASSERT(transforms[t].fHandle.isValid());
joshualitt49586be2014-09-16 08:21:41 -0700434 const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
kkinnunenec56e452014-08-25 22:21:16 -0700435 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
436 continue;
437 }
438 transforms[t].fCurrentValue = transform;
439 switch (transforms[t].fType) {
440 case kVec2f_GrSLType:
441 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
442 break;
443 case kVec3f_GrSLType:
444 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
445 break;
446 default:
447 SkFAIL("Unexpected matrix type.");
448 }
449 }
450}
451
joshualitt30ba4362014-08-21 20:18:45 -0700452GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000453 int reserveCount)
454 : fBuilder(builder)
455 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
joshualitt30ba4362014-08-21 20:18:45 -0700456 (reserveCount,
457 fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000458}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000459void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700460 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000461 const char* outColor,
462 const char* inColor,
463 int stageIndex) {
bsalomon49f085d2014-09-05 13:34:00 -0700464 SkASSERT(fProgramEffects.get());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000465 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
466}
467
468////////////////////////////////////////////////////////////////////////////////
469
joshualitt30ba4362014-08-21 20:18:45 -0700470void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000471 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700472 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000473 const char* outColor,
474 const char* inColor,
475 int stageIndex) {
joshualitt49586be2014-09-16 08:21:41 -0700476 const GrEffect& effect = *stage.getEffect();
477 SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
478 SkSTArray<4, TextureSampler> samplers(effect.numTextures());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000479
joshualitt49586be2014-09-16 08:21:41 -0700480 SkASSERT(0 == effect.getVertexAttribs().count());
481 this->setupPathTexGen(builder, stage, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000482 this->emitSamplers(builder, effect, &samplers);
483
joshualitt49586be2014-09-16 08:21:41 -0700484 GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000485 fGLEffects.push_back(glEffect);
486
joshualitt30ba4362014-08-21 20:18:45 -0700487 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000488 // Enclose custom code in a block to avoid namespace conflicts
489 SkString openBrace;
490 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700491 fsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000492
493 SkASSERT(!glEffect->isVertexEffect());
joshualitt49586be2014-09-16 08:21:41 -0700494 glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000495
joshualitt30ba4362014-08-21 20:18:45 -0700496 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000497}
498
joshualitt30ba4362014-08-21 20:18:45 -0700499void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
joshualitt49586be2014-09-16 08:21:41 -0700500 const GrEffectStage& effectStage,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000501 TransformedCoordsArray* outCoords) {
joshualitt49586be2014-09-16 08:21:41 -0700502 int numTransforms = effectStage.getEffect()->numTransforms();
503 uint32_t totalKey = GenTransformKey(effectStage, false);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000504 int texCoordIndex = builder->addTexCoordSets(numTransforms);
505 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
506 SkString name;
507 for (int t = 0; t < numTransforms; ++t) {
508 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
509 kVec3f_GrSLType :
510 kVec2f_GrSLType;
511 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
512 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
513 }
514}
515
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000516void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
kkinnunenec56e452014-08-25 22:21:16 -0700517 GrGpu::DrawType,
518 const GrGLProgramDataManager& pdman,
519 const GrEffectStage* effectStages[]) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000520 int numEffects = fGLEffects.count();
521 SkASSERT(numEffects == fTransforms.count());
522 SkASSERT(numEffects == fSamplers.count());
523 for (int e = 0; e < numEffects; ++e) {
joshualitt49586be2014-09-16 08:21:41 -0700524 const GrEffectStage& effectStage = *effectStages[e];
525 const GrEffect& effect = *effectStage.getEffect();
526 fGLEffects[e]->setData(pdman, effect);
527 this->setPathTexGenState(gpu, effectStage, e);
528 this->bindTextures(gpu, effect, e);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000529 }
530}
531
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000532void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
joshualitt49586be2014-09-16 08:21:41 -0700533 const GrEffectStage& effectStage,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000534 int effectIdx) {
bsalomon63e99f72014-07-21 08:03:14 -0700535 uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000536 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
joshualitt49586be2014-09-16 08:21:41 -0700537 int numTransforms = effectStage.getEffect()->numTransforms();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000538 for (int t = 0; t < numTransforms; ++t) {
539 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000540 case kNoPersp_MatrixType: {
joshualitt49586be2014-09-16 08:21:41 -0700541 const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700542 gpu->glPathRendering()->enablePathTexGen(
543 texCoordIndex++,
544 GrGLPathRendering::kST_PathTexGenComponents,
545 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000546 break;
547 }
548 case kGeneral_MatrixType: {
joshualitt49586be2014-09-16 08:21:41 -0700549 const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700550 gpu->glPathRendering()->enablePathTexGen(
551 texCoordIndex++,
552 GrGLPathRendering::kSTR_PathTexGenComponents,
553 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000554 break;
555 }
556 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000557 SkFAIL("Unexpected matrixs type.");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000558 }
559 }
560}
561
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000562GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
joshualitt30ba4362014-08-21 20:18:45 -0700563 GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000564 int reserveCount)
565 : fBuilder(builder)
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000566 , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000567}
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000568void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700569 const GrEffectKey& key,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000570 const char* outColor,
571 const char* inColor,
572 int stageIndex) {
bsalomon49f085d2014-09-05 13:34:00 -0700573 SkASSERT(fProgramEffects.get());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000574 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
575}
joshualitt30ba4362014-08-21 20:18:45 -0700576