blob: 8d97b42329368171da6fd5808277e2049b31bcc1 [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"
kkinnunenec56e452014-08-25 22:21:16 -070012#include "gl/GrGLPathRendering.h"
13#include "gl/builders/GrGLProgramBuilder.h"
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000014#include "gl/GrGLVertexEffect.h"
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000015#include "gl/GrGpuGL.h"
16
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000017typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
18typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
19typedef GrGLProgramEffects::TextureSampler TextureSampler;
20typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
21
22/**
23 * We specialize the vertex code for each of these matrix types.
24 */
25enum MatrixType {
egdaniel4c6443e2014-06-24 13:43:12 -070026 kNoPersp_MatrixType = 0,
27 kGeneral_MatrixType = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000028};
29
30/**
31 * The key for an individual coord transform is made up of a matrix type and a bit that
32 * indicates the source of the input coords.
33 */
34enum {
egdaniel4c6443e2014-06-24 13:43:12 -070035 kMatrixTypeKeyBits = 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000036 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
37 kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
38 kTransformKeyBits = kMatrixTypeKeyBits + 1,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000039};
40
41namespace {
42
43/**
44 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
45 * present in the texture's config. swizzleComponentMask indicates the channels present in the
46 * shader swizzle.
47 */
48inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
49 uint32_t configComponentMask,
50 uint32_t swizzleComponentMask) {
51 if (caps.textureSwizzleSupport()) {
52 // Any remapping is handled using texture swizzling not shader modifications.
53 return false;
54 }
55 // check if the texture is alpha-only
56 if (kA_GrColorComponentFlag == configComponentMask) {
57 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
58 // we must map the swizzle 'a's to 'r'.
59 return true;
60 }
61 if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
62 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
63 // alpha-only textures smear alpha across all four channels when read.
64 return true;
65 }
66 }
67 return false;
68}
69
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000070/**
71 * Retrieves the matrix type from transformKey for the transform at transformIdx.
72 */
bsalomon63e99f72014-07-21 08:03:14 -070073MatrixType get_matrix_type(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000074 return static_cast<MatrixType>(
75 (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +000076}
77
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000078/**
79 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
80 * the same coordinate set as the original GrCoordTransform if the position and local coords are
81 * identical for this program.
82 */
bsalomon63e99f72014-07-21 08:03:14 -070083GrCoordSet get_source_coords(uint32_t transformKey, int transformIdx) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000084 return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
85 kPosition_GrCoordSet :
86 kLocal_GrCoordSet;
87}
88
89/**
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000090 * Retrieves the final matrix that a transform needs to apply to its source coords.
91 */
92SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
bsalomonf99f8842014-07-07 11:54:23 -070093 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(transformIdx);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000094 SkMatrix combined;
bsalomon06736762014-08-04 10:56:39 -070095
96 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
97 // If we have explicit local coords then we shouldn't need a coord change.
98 SkASSERT(!drawEffect.programHasExplicitLocalCoords() ||
99 drawEffect.getCoordChangeMatrix().isIdentity());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000100 combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
101 } else {
102 combined = coordTransform.getMatrix();
103 }
104 if (coordTransform.reverseY()) {
105 // combined.postScale(1,-1);
106 // combined.postTranslate(0,1);
107 combined.set(SkMatrix::kMSkewY,
108 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
109 combined.set(SkMatrix::kMScaleY,
110 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
111 combined.set(SkMatrix::kMTransY,
112 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
113 }
114 return combined;
115}
116
117}
118
119////////////////////////////////////////////////////////////////////////////////
120
bsalomon929f29a2014-07-17 07:55:11 -0700121bool GrGLProgramEffects::GenEffectMetaKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps,
122 GrEffectKeyBuilder* b) {
123
bsalomon63e99f72014-07-21 08:03:14 -0700124 uint32_t textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
125 uint32_t transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
126 uint32_t attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
bsalomon929f29a2014-07-17 07:55:11 -0700127 uint32_t classID = drawEffect.effect()->getFactory().effectClassID();
128
129 // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
130 // don't fit.
131 static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
132 if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
133 return false;
134 }
135
136 uint32_t* key = b->add32n(2);
137 key[0] = (textureKey << 16 | transformKey);
138 key[1] = (classID << 16 | attribKey);
139 return true;
140}
141
bsalomon63e99f72014-07-21 08:03:14 -0700142uint32_t GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
143 uint32_t key = 0;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000144 int numAttributes = drawEffect.getVertexAttribIndexCount();
145 SkASSERT(numAttributes <= 2);
146 const int* attributeIndices = drawEffect.getVertexAttribIndices();
147 for (int a = 0; a < numAttributes; ++a) {
bsalomon63e99f72014-07-21 08:03:14 -0700148 uint32_t value = attributeIndices[a] << 3 * a;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000149 SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
150 key |= value;
151 }
152 return key;
153}
154
bsalomon63e99f72014-07-21 08:03:14 -0700155uint32_t GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
156 uint32_t totalKey = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700157 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000158 for (int t = 0; t < numTransforms; ++t) {
bsalomon63e99f72014-07-21 08:03:14 -0700159 uint32_t key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700160 const GrCoordTransform& coordTransform = drawEffect.effect()->coordTransform(t);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000161 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
162 SkMatrix::TypeMask type1;
163 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
164 type1 = drawEffect.getCoordChangeMatrix().getType();
165 } else {
166 if (drawEffect.programHasExplicitLocalCoords()) {
167 // We only make the key indicate that device coords are referenced when the local coords
168 // are not actually determined by positions. Otherwise the local coords var and position
169 // var are identical.
170 key |= kPositionCoords_Flag;
171 }
172 type1 = SkMatrix::kIdentity_Mask;
173 }
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
bsalomon63e99f72014-07-21 08:03:14 -0700189uint32_t GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
190 uint32_t key = 0;
bsalomonf99f8842014-07-07 11:54:23 -0700191 int numTextures = drawEffect.effect()->numTextures();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000192 for (int t = 0; t < numTextures; ++t) {
bsalomonf99f8842014-07-07 11:54:23 -0700193 const GrTextureAccess& access = drawEffect.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,
bsalomonf99f8842014-07-07 11:54:23 -0700210 const GrEffect* effect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000211 TextureSamplerArray* outSamplers) {
212 SkTArray<Sampler, true>& samplers = fSamplers.push_back();
213 int numTextures = effect->numTextures();
214 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,
222 (samplers[t].fUniform, effect->textureAccess(t)));
223 }
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
bsalomonf99f8842014-07-07 11:54:23 -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();
243 SkASSERT(numSamplers == effect->numTextures());
244 for (int s = 0; s < numSamplers; ++s) {
245 SkASSERT(samplers[s].fTextureUnit >= 0);
246 const GrTextureAccess& textureAccess = effect->textureAccess(s);
247 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) {
261 GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
bsalomonf99f8842014-07-07 11:54:23 -0700262 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000263 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
264 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
265
joshualitt30ba4362014-08-21 20:18:45 -0700266 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
267 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
268 vsBuilder->emitAttributes(stage);
bsalomon848faf02014-07-11 10:01:02 -0700269 this->emitTransforms(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000270 this->emitSamplers(builder, effect, &samplers);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000271
272 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000273 fGLEffects.push_back(glEffect);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000274
275 // Enclose custom code in a block to avoid namespace conflicts
276 SkString openBrace;
277 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700278 fsBuilder->codeAppend(openBrace.c_str());
279 vsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000280
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000281 if (glEffect->isVertexEffect()) {
282 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000283 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000284 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000285 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000286 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000287
joshualitt30ba4362014-08-21 20:18:45 -0700288 vsBuilder->codeAppend("\t}\n");
289 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000290}
291
joshualitt30ba4362014-08-21 20:18:45 -0700292void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700293 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000294 TransformedCoordsArray* outCoords) {
295 SkTArray<Transform, true>& transforms = fTransforms.push_back();
bsalomon63e99f72014-07-21 08:03:14 -0700296 uint32_t totalKey = GenTransformKey(drawEffect);
bsalomon848faf02014-07-11 10:01:02 -0700297 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000298 transforms.push_back_n(numTransforms);
kkinnunenec56e452014-08-25 22:21:16 -0700299
300 SkTArray<PathTransform, true>* pathTransforms = NULL;
301 const GrGLCaps* glCaps = builder->ctxInfo().caps();
302 if (glCaps->pathRenderingSupport() &&
303 builder->gpu()->glPathRendering()->texturingMode() ==
304 GrGLPathRendering::SeparableShaders_TexturingMode) {
305 pathTransforms = &fPathTransforms.push_back();
306 pathTransforms->push_back_n(numTransforms);
307 }
308
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000309 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 }
joshualitt30ba4362014-08-21 20:18:45 -0700330 transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
egdaniel4c6443e2014-06-24 13:43:12 -0700331 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;
joshualitt30ba4362014-08-21 20:18:45 -0700344 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
kkinnunenec56e452014-08-25 22:21:16 -0700345 if (pathTransforms) {
346 (*pathTransforms)[t].fHandle =
347 builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
348 (*pathTransforms)[t].fType = varyingType;
349 } else {
350 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
351 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000352
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000353 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
joshualitt30ba4362014-08-21 20:18:45 -0700354 vsBuilder->positionAttribute() :
355 vsBuilder->localCoordsAttribute();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000356 // varying = matrix * coords (logically)
egdaniel4c6443e2014-06-24 13:43:12 -0700357 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
358 if (kVec2f_GrSLType == varyingType) {
joshualitt30ba4362014-08-21 20:18:45 -0700359 vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700360 vsVaryingName, uniName, coords.c_str());
361 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700362 vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n",
egdaniel4c6443e2014-06-24 13:43:12 -0700363 vsVaryingName, uniName, coords.c_str());
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000364 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000365 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
366 (SkString(fsVaryingName), varyingType));
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000367 }
368}
369
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000370void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
kkinnunenec56e452014-08-25 22:21:16 -0700371 GrGpu::DrawType drawType,
372 const GrGLProgramDataManager& programDataManager,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000373 const GrEffectStage* effectStages[]) {
374 int numEffects = fGLEffects.count();
375 SkASSERT(numEffects == fTransforms.count());
376 SkASSERT(numEffects == fSamplers.count());
377 for (int e = 0; e < numEffects; ++e) {
378 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
kkinnunenec56e452014-08-25 22:21:16 -0700379 fGLEffects[e]->setData(programDataManager, drawEffect);
380 if (GrGpu::IsPathRenderingDrawType(drawType)) {
381 this->setPathTransformData(gpu, programDataManager, drawEffect, e);
382 } else {
383 this->setTransformData(gpu, programDataManager, drawEffect, e);
384 }
385
bsalomonf99f8842014-07-07 11:54:23 -0700386 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000387 }
388}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000389
kkinnunenec56e452014-08-25 22:21:16 -0700390void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
391 const GrGLProgramDataManager& pdman,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000392 const GrDrawEffect& drawEffect,
393 int effectIdx) {
394 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
395 int numTransforms = transforms.count();
bsalomonf99f8842014-07-07 11:54:23 -0700396 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000397 for (int t = 0; t < numTransforms; ++t) {
egdaniel4c6443e2014-06-24 13:43:12 -0700398 SkASSERT(transforms[t].fHandle.isValid());
399 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
400 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
kkinnunenec56e452014-08-25 22:21:16 -0700401 pdman.setSkMatrix(transforms[t].fHandle, matrix);
egdaniel4c6443e2014-06-24 13:43:12 -0700402 transforms[t].fCurrentValue = matrix;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000403 }
404 }
405}
406
kkinnunenec56e452014-08-25 22:21:16 -0700407void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
408 const GrGLProgramDataManager& pdman,
409 const GrDrawEffect& drawEffect,
410 int effectIdx) {
411 SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
412 int numTransforms = transforms.count();
413 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
414 for (int t = 0; t < numTransforms; ++t) {
415 SkASSERT(transforms[t].fHandle.isValid());
416 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
417 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
418 continue;
419 }
420 transforms[t].fCurrentValue = transform;
421 switch (transforms[t].fType) {
422 case kVec2f_GrSLType:
423 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
424 break;
425 case kVec3f_GrSLType:
426 pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
427 break;
428 default:
429 SkFAIL("Unexpected matrix type.");
430 }
431 }
432}
433
joshualitt30ba4362014-08-21 20:18:45 -0700434GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000435 int reserveCount)
436 : fBuilder(builder)
437 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
joshualitt30ba4362014-08-21 20:18:45 -0700438 (reserveCount,
439 fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000440}
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000441void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700442 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000443 const char* outColor,
444 const char* inColor,
445 int stageIndex) {
446 SkASSERT(NULL != fProgramEffects.get());
447 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
448}
449
450////////////////////////////////////////////////////////////////////////////////
451
joshualitt30ba4362014-08-21 20:18:45 -0700452void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000453 const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700454 const GrEffectKey& key,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000455 const char* outColor,
456 const char* inColor,
457 int stageIndex) {
458 GrDrawEffect drawEffect(stage, false);
bsalomonf99f8842014-07-07 11:54:23 -0700459 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000460 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
461 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
462
463 SkASSERT(0 == stage.getVertexAttribIndexCount());
bsalomon848faf02014-07-11 10:01:02 -0700464 this->setupPathTexGen(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000465 this->emitSamplers(builder, effect, &samplers);
466
467 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
468 fGLEffects.push_back(glEffect);
469
joshualitt30ba4362014-08-21 20:18:45 -0700470 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000471 // Enclose custom code in a block to avoid namespace conflicts
472 SkString openBrace;
473 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700474 fsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000475
476 SkASSERT(!glEffect->isVertexEffect());
477 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
478
joshualitt30ba4362014-08-21 20:18:45 -0700479 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000480}
481
joshualitt30ba4362014-08-21 20:18:45 -0700482void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700483 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000484 TransformedCoordsArray* outCoords) {
bsalomon848faf02014-07-11 10:01:02 -0700485 int numTransforms = drawEffect.effect()->numTransforms();
bsalomon63e99f72014-07-21 08:03:14 -0700486 uint32_t totalKey = GenTransformKey(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000487 int texCoordIndex = builder->addTexCoordSets(numTransforms);
488 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
489 SkString name;
490 for (int t = 0; t < numTransforms; ++t) {
491 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
492 kVec3f_GrSLType :
493 kVec2f_GrSLType;
494 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
495 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
496 }
497}
498
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000499void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
kkinnunenec56e452014-08-25 22:21:16 -0700500 GrGpu::DrawType,
501 const GrGLProgramDataManager& pdman,
502 const GrEffectStage* effectStages[]) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000503 int numEffects = fGLEffects.count();
504 SkASSERT(numEffects == fTransforms.count());
505 SkASSERT(numEffects == fSamplers.count());
506 for (int e = 0; e < numEffects; ++e) {
507 GrDrawEffect drawEffect(*effectStages[e], false);
kkinnunenec56e452014-08-25 22:21:16 -0700508 fGLEffects[e]->setData(pdman, drawEffect);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000509 this->setPathTexGenState(gpu, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700510 this->bindTextures(gpu, drawEffect.effect(), e);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000511 }
512}
513
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000514void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000515 const GrDrawEffect& drawEffect,
516 int effectIdx) {
bsalomon63e99f72014-07-21 08:03:14 -0700517 uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000518 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
bsalomonf99f8842014-07-07 11:54:23 -0700519 int numTransforms = drawEffect.effect()->numTransforms();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000520 for (int t = 0; t < numTransforms; ++t) {
521 switch (get_matrix_type(totalKey, t)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000522 case kNoPersp_MatrixType: {
523 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700524 gpu->glPathRendering()->enablePathTexGen(
525 texCoordIndex++,
526 GrGLPathRendering::kST_PathTexGenComponents,
527 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000528 break;
529 }
530 case kGeneral_MatrixType: {
531 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
kkinnunenccdaa042014-08-20 01:36:23 -0700532 gpu->glPathRendering()->enablePathTexGen(
533 texCoordIndex++,
534 GrGLPathRendering::kSTR_PathTexGenComponents,
535 transform);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000536 break;
537 }
538 default:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000539 SkFAIL("Unexpected matrixs type.");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000540 }
541 }
542}
543
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000544GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
joshualitt30ba4362014-08-21 20:18:45 -0700545 GrGLFragmentOnlyProgramBuilder* builder,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000546 int reserveCount)
547 : fBuilder(builder)
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000548 , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000549}
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000550void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
bsalomon63e99f72014-07-21 08:03:14 -0700551 const GrEffectKey& key,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000552 const char* outColor,
553 const char* inColor,
554 int stageIndex) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000555 SkASSERT(NULL != fProgramEffects.get());
556 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
557}
joshualitt30ba4362014-08-21 20:18:45 -0700558