blob: 369ec1076030f25e8abccf694006692abb1fbf3a [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"
joshualitt249af152014-09-15 11:41:13 -070014#include "gl/GrGLGeometryProcessor.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);
joshualitt249af152014-09-15 11:41:13 -0700126 uint32_t attribKey = GrGLProgramEffects::GenAttribKey(drawEffect.castEffect<GrEffect>());
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
joshualitt249af152014-09-15 11:41:13 -0700142uint32_t GrGLProgramEffects::GenAttribKey(const GrEffect& effect) {
bsalomon63e99f72014-07-21 08:03:14 -0700143 uint32_t key = 0;
joshualitt249af152014-09-15 11:41:13 -0700144
145 const GrEffect::VertexAttribArray& vars = effect.getVertexAttribs();
146 int numAttributes = vars.count();
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000147 SkASSERT(numAttributes <= 2);
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000148 for (int a = 0; a < numAttributes; ++a) {
joshualitt249af152014-09-15 11:41:13 -0700149 uint32_t value = 1 << a;
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000150 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()) {
joshualitt249af152014-09-15 11:41:13 -0700282 GrGLGeometryProcessor* vertexEffect = static_cast<GrGLGeometryProcessor*>(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
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());
397 GrDrawEffect drawEffect(*effectStage, fHasExplicitLocalCoords);
398 fGLEffects[0]->setData(programDataManager, drawEffect);
399 if (GrGpu::IsPathRenderingDrawType(drawType)) {
400 this->setPathTransformData(gpu, programDataManager, drawEffect, 0);
401 } else {
402 this->setTransformData(gpu, programDataManager, drawEffect, 0);
403 }
404
405 this->bindTextures(gpu, drawEffect.effect(), 0);
406}
407
kkinnunenec56e452014-08-25 22:21:16 -0700408void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
409 const GrGLProgramDataManager& pdman,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000410 const GrDrawEffect& drawEffect,
411 int effectIdx) {
412 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
413 int numTransforms = transforms.count();
bsalomonf99f8842014-07-07 11:54:23 -0700414 SkASSERT(numTransforms == drawEffect.effect()->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());
417 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
418 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,
427 const GrDrawEffect& drawEffect,
428 int effectIdx) {
429 SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
430 int numTransforms = transforms.count();
431 SkASSERT(numTransforms == drawEffect.effect()->numTransforms());
432 for (int t = 0; t < numTransforms; ++t) {
433 SkASSERT(transforms[t].fHandle.isValid());
434 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
435 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) {
476 GrDrawEffect drawEffect(stage, false);
bsalomonf99f8842014-07-07 11:54:23 -0700477 const GrEffect* effect = stage.getEffect();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000478 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
479 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
480
joshualitt249af152014-09-15 11:41:13 -0700481 SkASSERT(0 == effect->getVertexAttribs().count());
bsalomon848faf02014-07-11 10:01:02 -0700482 this->setupPathTexGen(builder, drawEffect, &coords);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000483 this->emitSamplers(builder, effect, &samplers);
484
485 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
486 fGLEffects.push_back(glEffect);
487
joshualitt30ba4362014-08-21 20:18:45 -0700488 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000489 // Enclose custom code in a block to avoid namespace conflicts
490 SkString openBrace;
491 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
joshualitt30ba4362014-08-21 20:18:45 -0700492 fsBuilder->codeAppend(openBrace.c_str());
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000493
494 SkASSERT(!glEffect->isVertexEffect());
495 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
496
joshualitt30ba4362014-08-21 20:18:45 -0700497 fsBuilder->codeAppend("\t}\n");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000498}
499
joshualitt30ba4362014-08-21 20:18:45 -0700500void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
bsalomon848faf02014-07-11 10:01:02 -0700501 const GrDrawEffect& drawEffect,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000502 TransformedCoordsArray* outCoords) {
bsalomon848faf02014-07-11 10:01:02 -0700503 int numTransforms = drawEffect.effect()->numTransforms();
bsalomon63e99f72014-07-21 08:03:14 -0700504 uint32_t totalKey = GenTransformKey(drawEffect);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000505 int texCoordIndex = builder->addTexCoordSets(numTransforms);
506 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
507 SkString name;
508 for (int t = 0; t < numTransforms; ++t) {
509 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
510 kVec3f_GrSLType :
511 kVec2f_GrSLType;
512 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
513 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
514 }
515}
516
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000517void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
kkinnunenec56e452014-08-25 22:21:16 -0700518 GrGpu::DrawType,
519 const GrGLProgramDataManager& pdman,
520 const GrEffectStage* effectStages[]) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000521 int numEffects = fGLEffects.count();
522 SkASSERT(numEffects == fTransforms.count());
523 SkASSERT(numEffects == fSamplers.count());
524 for (int e = 0; e < numEffects; ++e) {
525 GrDrawEffect drawEffect(*effectStages[e], false);
kkinnunenec56e452014-08-25 22:21:16 -0700526 fGLEffects[e]->setData(pdman, drawEffect);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000527 this->setPathTexGenState(gpu, drawEffect, e);
bsalomonf99f8842014-07-07 11:54:23 -0700528 this->bindTextures(gpu, drawEffect.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,
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000533 const GrDrawEffect& drawEffect,
534 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;
bsalomonf99f8842014-07-07 11:54:23 -0700537 int numTransforms = drawEffect.effect()->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: {
541 const SkMatrix& transform = get_transform_matrix(drawEffect, 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: {
549 const SkMatrix& transform = get_transform_matrix(drawEffect, 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