gfx/skia/trunk/src/gpu/gl/GrGLProgramEffects.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2013 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "GrGLProgramEffects.h"
michael@0 9 #include "GrDrawEffect.h"
michael@0 10 #include "gl/GrGLEffect.h"
michael@0 11 #include "gl/GrGLShaderBuilder.h"
michael@0 12 #include "gl/GrGLVertexEffect.h"
michael@0 13 #include "gl/GrGpuGL.h"
michael@0 14
michael@0 15 typedef GrGLProgramEffects::EffectKey EffectKey;
michael@0 16 typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
michael@0 17 typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
michael@0 18 typedef GrGLProgramEffects::TextureSampler TextureSampler;
michael@0 19 typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
michael@0 20
michael@0 21 /**
michael@0 22 * We specialize the vertex code for each of these matrix types.
michael@0 23 */
michael@0 24 enum MatrixType {
michael@0 25 kIdentity_MatrixType = 0,
michael@0 26 kTrans_MatrixType = 1,
michael@0 27 kNoPersp_MatrixType = 2,
michael@0 28 kGeneral_MatrixType = 3,
michael@0 29 };
michael@0 30
michael@0 31 /**
michael@0 32 * The key for an individual coord transform is made up of a matrix type and a bit that
michael@0 33 * indicates the source of the input coords.
michael@0 34 */
michael@0 35 enum {
michael@0 36 kMatrixTypeKeyBits = 2,
michael@0 37 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
michael@0 38 kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
michael@0 39 kTransformKeyBits = kMatrixTypeKeyBits + 1,
michael@0 40 };
michael@0 41
michael@0 42 namespace {
michael@0 43
michael@0 44 /**
michael@0 45 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
michael@0 46 * present in the texture's config. swizzleComponentMask indicates the channels present in the
michael@0 47 * shader swizzle.
michael@0 48 */
michael@0 49 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
michael@0 50 uint32_t configComponentMask,
michael@0 51 uint32_t swizzleComponentMask) {
michael@0 52 if (caps.textureSwizzleSupport()) {
michael@0 53 // Any remapping is handled using texture swizzling not shader modifications.
michael@0 54 return false;
michael@0 55 }
michael@0 56 // check if the texture is alpha-only
michael@0 57 if (kA_GrColorComponentFlag == configComponentMask) {
michael@0 58 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
michael@0 59 // we must map the swizzle 'a's to 'r'.
michael@0 60 return true;
michael@0 61 }
michael@0 62 if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
michael@0 63 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
michael@0 64 // alpha-only textures smear alpha across all four channels when read.
michael@0 65 return true;
michael@0 66 }
michael@0 67 }
michael@0 68 return false;
michael@0 69 }
michael@0 70
michael@0 71 /**
michael@0 72 * Retrieves the matrix type from transformKey for the transform at transformIdx.
michael@0 73 */
michael@0 74 MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
michael@0 75 return static_cast<MatrixType>(
michael@0 76 (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
michael@0 77 }
michael@0 78
michael@0 79 /**
michael@0 80 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
michael@0 81 * the same coordinate set as the original GrCoordTransform if the position and local coords are
michael@0 82 * identical for this program.
michael@0 83 */
michael@0 84 GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
michael@0 85 return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
michael@0 86 kPosition_GrCoordSet :
michael@0 87 kLocal_GrCoordSet;
michael@0 88 }
michael@0 89
michael@0 90 /**
michael@0 91 * Retrieves the final translation that a transform needs to apply to its source coords (and
michael@0 92 * verifies that a translation is all it needs).
michael@0 93 */
michael@0 94 void get_transform_translation(const GrDrawEffect& drawEffect,
michael@0 95 int transformIdx,
michael@0 96 GrGLfloat* tx,
michael@0 97 GrGLfloat* ty) {
michael@0 98 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
michael@0 99 SkASSERT(!coordTransform.reverseY());
michael@0 100 const SkMatrix& matrix = coordTransform.getMatrix();
michael@0 101 if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
michael@0 102 !drawEffect.programHasExplicitLocalCoords()) {
michael@0 103 const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix();
michael@0 104 SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
michael@0 105 *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]);
michael@0 106 *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]);
michael@0 107 } else {
michael@0 108 SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType());
michael@0 109 *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
michael@0 110 *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
michael@0 111 }
michael@0 112 }
michael@0 113
michael@0 114 /**
michael@0 115 * Retrieves the final matrix that a transform needs to apply to its source coords.
michael@0 116 */
michael@0 117 SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
michael@0 118 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
michael@0 119 SkMatrix combined;
michael@0 120 if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
michael@0 121 !drawEffect.programHasExplicitLocalCoords()) {
michael@0 122 combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
michael@0 123 } else {
michael@0 124 combined = coordTransform.getMatrix();
michael@0 125 }
michael@0 126 if (coordTransform.reverseY()) {
michael@0 127 // combined.postScale(1,-1);
michael@0 128 // combined.postTranslate(0,1);
michael@0 129 combined.set(SkMatrix::kMSkewY,
michael@0 130 combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
michael@0 131 combined.set(SkMatrix::kMScaleY,
michael@0 132 combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
michael@0 133 combined.set(SkMatrix::kMTransY,
michael@0 134 combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
michael@0 135 }
michael@0 136 return combined;
michael@0 137 }
michael@0 138
michael@0 139 }
michael@0 140
michael@0 141 ////////////////////////////////////////////////////////////////////////////////
michael@0 142
michael@0 143 EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
michael@0 144 EffectKey key = 0;
michael@0 145 int numAttributes = drawEffect.getVertexAttribIndexCount();
michael@0 146 SkASSERT(numAttributes <= 2);
michael@0 147 const int* attributeIndices = drawEffect.getVertexAttribIndices();
michael@0 148 for (int a = 0; a < numAttributes; ++a) {
michael@0 149 EffectKey value = attributeIndices[a] << 3 * a;
michael@0 150 SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
michael@0 151 key |= value;
michael@0 152 }
michael@0 153 return key;
michael@0 154 }
michael@0 155
michael@0 156 EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
michael@0 157 EffectKey totalKey = 0;
michael@0 158 int numTransforms = (*drawEffect.effect())->numTransforms();
michael@0 159 for (int t = 0; t < numTransforms; ++t) {
michael@0 160 EffectKey key = 0;
michael@0 161 const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t);
michael@0 162 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
michael@0 163 SkMatrix::TypeMask type1;
michael@0 164 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
michael@0 165 type1 = drawEffect.getCoordChangeMatrix().getType();
michael@0 166 } else {
michael@0 167 if (drawEffect.programHasExplicitLocalCoords()) {
michael@0 168 // We only make the key indicate that device coords are referenced when the local coords
michael@0 169 // are not actually determined by positions. Otherwise the local coords var and position
michael@0 170 // var are identical.
michael@0 171 key |= kPositionCoords_Flag;
michael@0 172 }
michael@0 173 type1 = SkMatrix::kIdentity_Mask;
michael@0 174 }
michael@0 175
michael@0 176 int combinedTypes = type0 | type1;
michael@0 177
michael@0 178 bool reverseY = coordTransform.reverseY();
michael@0 179
michael@0 180 if (SkMatrix::kPerspective_Mask & combinedTypes) {
michael@0 181 key |= kGeneral_MatrixType;
michael@0 182 } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) {
michael@0 183 key |= kNoPersp_MatrixType;
michael@0 184 } else if (SkMatrix::kTranslate_Mask & combinedTypes) {
michael@0 185 key |= kTrans_MatrixType;
michael@0 186 } else {
michael@0 187 key |= kIdentity_MatrixType;
michael@0 188 }
michael@0 189 key <<= kTransformKeyBits * t;
michael@0 190 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
michael@0 191 totalKey |= key;
michael@0 192 }
michael@0 193 return totalKey;
michael@0 194 }
michael@0 195
michael@0 196 EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
michael@0 197 EffectKey key = 0;
michael@0 198 int numTextures = (*drawEffect.effect())->numTextures();
michael@0 199 for (int t = 0; t < numTextures; ++t) {
michael@0 200 const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(t);
michael@0 201 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
michael@0 202 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
michael@0 203 key |= 1 << t;
michael@0 204 }
michael@0 205 }
michael@0 206 return key;
michael@0 207 }
michael@0 208
michael@0 209 GrGLProgramEffects::~GrGLProgramEffects() {
michael@0 210 int numEffects = fGLEffects.count();
michael@0 211 for (int e = 0; e < numEffects; ++e) {
michael@0 212 SkDELETE(fGLEffects[e]);
michael@0 213 }
michael@0 214 }
michael@0 215
michael@0 216 void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
michael@0 217 const GrEffectRef& effect,
michael@0 218 TextureSamplerArray* outSamplers) {
michael@0 219 SkTArray<Sampler, true>& samplers = fSamplers.push_back();
michael@0 220 int numTextures = effect->numTextures();
michael@0 221 samplers.push_back_n(numTextures);
michael@0 222 SkString name;
michael@0 223 for (int t = 0; t < numTextures; ++t) {
michael@0 224 name.printf("Sampler%d", t);
michael@0 225 samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
michael@0 226 kSampler2D_GrSLType,
michael@0 227 name.c_str());
michael@0 228 SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
michael@0 229 (samplers[t].fUniform, effect->textureAccess(t)));
michael@0 230 }
michael@0 231 }
michael@0 232
michael@0 233 void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
michael@0 234 int numEffects = fGLEffects.count();
michael@0 235 SkASSERT(numEffects == fSamplers.count());
michael@0 236 for (int e = 0; e < numEffects; ++e) {
michael@0 237 SkTArray<Sampler, true>& samplers = fSamplers[e];
michael@0 238 int numSamplers = samplers.count();
michael@0 239 for (int s = 0; s < numSamplers; ++s) {
michael@0 240 SkASSERT(samplers[s].fUniform.isValid());
michael@0 241 uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx);
michael@0 242 samplers[s].fTextureUnit = (*texUnitIdx)++;
michael@0 243 }
michael@0 244 }
michael@0 245 }
michael@0 246
michael@0 247 void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) {
michael@0 248 const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
michael@0 249 int numSamplers = samplers.count();
michael@0 250 SkASSERT(numSamplers == effect->numTextures());
michael@0 251 for (int s = 0; s < numSamplers; ++s) {
michael@0 252 SkASSERT(samplers[s].fTextureUnit >= 0);
michael@0 253 const GrTextureAccess& textureAccess = effect->textureAccess(s);
michael@0 254 gpu->bindTexture(samplers[s].fTextureUnit,
michael@0 255 textureAccess.getParams(),
michael@0 256 static_cast<GrGLTexture*>(textureAccess.getTexture()));
michael@0 257 }
michael@0 258 }
michael@0 259
michael@0 260 ////////////////////////////////////////////////////////////////////////////////
michael@0 261
michael@0 262 void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
michael@0 263 const GrEffectStage& stage,
michael@0 264 EffectKey key,
michael@0 265 const char* outColor,
michael@0 266 const char* inColor,
michael@0 267 int stageIndex) {
michael@0 268 GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
michael@0 269 const GrEffectRef& effect = *stage.getEffect();
michael@0 270 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
michael@0 271 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
michael@0 272
michael@0 273 this->emitAttributes(builder, stage);
michael@0 274 this->emitTransforms(builder, effect, key, &coords);
michael@0 275 this->emitSamplers(builder, effect, &samplers);
michael@0 276
michael@0 277 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
michael@0 278 fGLEffects.push_back(glEffect);
michael@0 279
michael@0 280 // Enclose custom code in a block to avoid namespace conflicts
michael@0 281 SkString openBrace;
michael@0 282 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
michael@0 283 builder->vsCodeAppend(openBrace.c_str());
michael@0 284 builder->fsCodeAppend(openBrace.c_str());
michael@0 285
michael@0 286 if (glEffect->isVertexEffect()) {
michael@0 287 GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
michael@0 288 vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
michael@0 289 } else {
michael@0 290 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
michael@0 291 }
michael@0 292
michael@0 293 builder->vsCodeAppend("\t}\n");
michael@0 294 builder->fsCodeAppend("\t}\n");
michael@0 295 }
michael@0 296
michael@0 297 void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
michael@0 298 const GrEffectStage& stage) {
michael@0 299 int numAttributes = stage.getVertexAttribIndexCount();
michael@0 300 const int* attributeIndices = stage.getVertexAttribIndices();
michael@0 301 for (int a = 0; a < numAttributes; ++a) {
michael@0 302 // TODO: Make addAttribute mangle the name.
michael@0 303 SkString attributeName("aAttr");
michael@0 304 attributeName.appendS32(attributeIndices[a]);
michael@0 305 builder->addEffectAttribute(attributeIndices[a],
michael@0 306 (*stage.getEffect())->vertexAttribType(a),
michael@0 307 attributeName);
michael@0 308 }
michael@0 309 }
michael@0 310
michael@0 311 void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
michael@0 312 const GrEffectRef& effect,
michael@0 313 EffectKey effectKey,
michael@0 314 TransformedCoordsArray* outCoords) {
michael@0 315 SkTArray<Transform, true>& transforms = fTransforms.push_back();
michael@0 316 EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
michael@0 317 int numTransforms = effect->numTransforms();
michael@0 318 transforms.push_back_n(numTransforms);
michael@0 319 for (int t = 0; t < numTransforms; t++) {
michael@0 320 GrSLType varyingType = kVoid_GrSLType;
michael@0 321 const char* uniName;
michael@0 322 switch (get_matrix_type(totalKey, t)) {
michael@0 323 case kIdentity_MatrixType:
michael@0 324 transforms[t].fType = kVoid_GrSLType;
michael@0 325 uniName = NULL;
michael@0 326 varyingType = kVec2f_GrSLType;
michael@0 327 break;
michael@0 328 case kTrans_MatrixType:
michael@0 329 transforms[t].fType = kVec2f_GrSLType;
michael@0 330 uniName = "StageTranslate";
michael@0 331 varyingType = kVec2f_GrSLType;
michael@0 332 break;
michael@0 333 case kNoPersp_MatrixType:
michael@0 334 transforms[t].fType = kMat33f_GrSLType;
michael@0 335 uniName = "StageMatrix";
michael@0 336 varyingType = kVec2f_GrSLType;
michael@0 337 break;
michael@0 338 case kGeneral_MatrixType:
michael@0 339 transforms[t].fType = kMat33f_GrSLType;
michael@0 340 uniName = "StageMatrix";
michael@0 341 varyingType = kVec3f_GrSLType;
michael@0 342 break;
michael@0 343 default:
michael@0 344 GrCrash("Unexpected key.");
michael@0 345 }
michael@0 346 SkString suffixedUniName;
michael@0 347 if (kVoid_GrSLType != transforms[t].fType) {
michael@0 348 if (0 != t) {
michael@0 349 suffixedUniName.append(uniName);
michael@0 350 suffixedUniName.appendf("_%i", t);
michael@0 351 uniName = suffixedUniName.c_str();
michael@0 352 }
michael@0 353 transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
michael@0 354 transforms[t].fType,
michael@0 355 uniName,
michael@0 356 &uniName);
michael@0 357 }
michael@0 358
michael@0 359 const char* varyingName = "MatrixCoord";
michael@0 360 SkString suffixedVaryingName;
michael@0 361 if (0 != t) {
michael@0 362 suffixedVaryingName.append(varyingName);
michael@0 363 suffixedVaryingName.appendf("_%i", t);
michael@0 364 varyingName = suffixedVaryingName.c_str();
michael@0 365 }
michael@0 366 const char* vsVaryingName;
michael@0 367 const char* fsVaryingName;
michael@0 368 builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
michael@0 369
michael@0 370 const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
michael@0 371 builder->positionAttribute() :
michael@0 372 builder->localCoordsAttribute();
michael@0 373 // varying = matrix * coords (logically)
michael@0 374 switch (transforms[t].fType) {
michael@0 375 case kVoid_GrSLType:
michael@0 376 SkASSERT(kVec2f_GrSLType == varyingType);
michael@0 377 builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
michael@0 378 break;
michael@0 379 case kVec2f_GrSLType:
michael@0 380 SkASSERT(kVec2f_GrSLType == varyingType);
michael@0 381 builder->vsCodeAppendf("\t%s = %s + %s;\n",
michael@0 382 vsVaryingName, uniName, coords.c_str());
michael@0 383 break;
michael@0 384 case kMat33f_GrSLType: {
michael@0 385 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
michael@0 386 if (kVec2f_GrSLType == varyingType) {
michael@0 387 builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
michael@0 388 vsVaryingName, uniName, coords.c_str());
michael@0 389 } else {
michael@0 390 builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
michael@0 391 vsVaryingName, uniName, coords.c_str());
michael@0 392 }
michael@0 393 break;
michael@0 394 }
michael@0 395 default:
michael@0 396 GrCrash("Unexpected uniform type.");
michael@0 397 }
michael@0 398 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
michael@0 399 (SkString(fsVaryingName), varyingType));
michael@0 400 }
michael@0 401 }
michael@0 402
michael@0 403 void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
michael@0 404 const GrGLUniformManager& uniformManager,
michael@0 405 const GrEffectStage* effectStages[]) {
michael@0 406 int numEffects = fGLEffects.count();
michael@0 407 SkASSERT(numEffects == fTransforms.count());
michael@0 408 SkASSERT(numEffects == fSamplers.count());
michael@0 409 for (int e = 0; e < numEffects; ++e) {
michael@0 410 GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
michael@0 411 fGLEffects[e]->setData(uniformManager, drawEffect);
michael@0 412 this->setTransformData(uniformManager, drawEffect, e);
michael@0 413 this->bindTextures(gpu, *drawEffect.effect(), e);
michael@0 414 }
michael@0 415 }
michael@0 416
michael@0 417 void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
michael@0 418 const GrDrawEffect& drawEffect,
michael@0 419 int effectIdx) {
michael@0 420 SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
michael@0 421 int numTransforms = transforms.count();
michael@0 422 SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
michael@0 423 for (int t = 0; t < numTransforms; ++t) {
michael@0 424 SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
michael@0 425 switch (transforms[t].fType) {
michael@0 426 case kVoid_GrSLType:
michael@0 427 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
michael@0 428 return;
michael@0 429 case kVec2f_GrSLType: {
michael@0 430 GrGLfloat tx, ty;
michael@0 431 get_transform_translation(drawEffect, t, &tx, &ty);
michael@0 432 if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
michael@0 433 transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
michael@0 434 uniformManager.set2f(transforms[t].fHandle, tx, ty);
michael@0 435 transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
michael@0 436 transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
michael@0 437 }
michael@0 438 break;
michael@0 439 }
michael@0 440 case kMat33f_GrSLType: {
michael@0 441 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
michael@0 442 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
michael@0 443 uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
michael@0 444 transforms[t].fCurrentValue = matrix;
michael@0 445 }
michael@0 446 break;
michael@0 447 }
michael@0 448 default:
michael@0 449 GrCrash("Unexpected uniform type.");
michael@0 450 }
michael@0 451 }
michael@0 452 }
michael@0 453
michael@0 454 GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
michael@0 455 int reserveCount)
michael@0 456 : fBuilder(builder)
michael@0 457 , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
michael@0 458 (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
michael@0 459 }
michael@0 460
michael@0 461 void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
michael@0 462 GrGLProgramEffects::EffectKey key,
michael@0 463 const char* outColor,
michael@0 464 const char* inColor,
michael@0 465 int stageIndex) {
michael@0 466 SkASSERT(NULL != fProgramEffects.get());
michael@0 467 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
michael@0 468 }
michael@0 469
michael@0 470 ////////////////////////////////////////////////////////////////////////////////
michael@0 471
michael@0 472 void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
michael@0 473 const GrEffectStage& stage,
michael@0 474 EffectKey key,
michael@0 475 const char* outColor,
michael@0 476 const char* inColor,
michael@0 477 int stageIndex) {
michael@0 478 GrDrawEffect drawEffect(stage, false);
michael@0 479 const GrEffectRef& effect = *stage.getEffect();
michael@0 480 SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
michael@0 481 SkSTArray<4, TextureSampler> samplers(effect->numTextures());
michael@0 482
michael@0 483 SkASSERT(0 == stage.getVertexAttribIndexCount());
michael@0 484 this->setupTexGen(builder, effect, key, &coords);
michael@0 485 this->emitSamplers(builder, effect, &samplers);
michael@0 486
michael@0 487 GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
michael@0 488 fGLEffects.push_back(glEffect);
michael@0 489
michael@0 490 // Enclose custom code in a block to avoid namespace conflicts
michael@0 491 SkString openBrace;
michael@0 492 openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
michael@0 493 builder->fsCodeAppend(openBrace.c_str());
michael@0 494
michael@0 495 SkASSERT(!glEffect->isVertexEffect());
michael@0 496 glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
michael@0 497
michael@0 498 builder->fsCodeAppend("\t}\n");
michael@0 499 }
michael@0 500
michael@0 501 void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
michael@0 502 const GrEffectRef& effect,
michael@0 503 EffectKey effectKey,
michael@0 504 TransformedCoordsArray* outCoords) {
michael@0 505 int numTransforms = effect->numTransforms();
michael@0 506 EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
michael@0 507 int texCoordIndex = builder->addTexCoordSets(numTransforms);
michael@0 508 SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
michael@0 509 SkString name;
michael@0 510 for (int t = 0; t < numTransforms; ++t) {
michael@0 511 GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
michael@0 512 kVec3f_GrSLType :
michael@0 513 kVec2f_GrSLType;
michael@0 514 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
michael@0 515 SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
michael@0 516 }
michael@0 517 }
michael@0 518
michael@0 519 void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
michael@0 520 const GrGLUniformManager& uniformManager,
michael@0 521 const GrEffectStage* effectStages[]) {
michael@0 522 int numEffects = fGLEffects.count();
michael@0 523 SkASSERT(numEffects == fTransforms.count());
michael@0 524 SkASSERT(numEffects == fSamplers.count());
michael@0 525 for (int e = 0; e < numEffects; ++e) {
michael@0 526 GrDrawEffect drawEffect(*effectStages[e], false);
michael@0 527 fGLEffects[e]->setData(uniformManager, drawEffect);
michael@0 528 this->setTexGenState(gpu, drawEffect, e);
michael@0 529 this->bindTextures(gpu, *drawEffect.effect(), e);
michael@0 530 }
michael@0 531 }
michael@0 532
michael@0 533 void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
michael@0 534 const GrDrawEffect& drawEffect,
michael@0 535 int effectIdx) {
michael@0 536 EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
michael@0 537 int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
michael@0 538 int numTransforms = (*drawEffect.effect())->numTransforms();
michael@0 539 for (int t = 0; t < numTransforms; ++t) {
michael@0 540 switch (get_matrix_type(totalKey, t)) {
michael@0 541 case kIdentity_MatrixType: {
michael@0 542 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
michael@0 543 GrGLfloat identity[] = {1, 0, 0,
michael@0 544 0, 1, 0};
michael@0 545 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
michael@0 546 break;
michael@0 547 }
michael@0 548 case kTrans_MatrixType: {
michael@0 549 GrGLfloat tx, ty;
michael@0 550 get_transform_translation(drawEffect, t, &tx, &ty);
michael@0 551 GrGLfloat translate[] = {1, 0, tx,
michael@0 552 0, 1, ty};
michael@0 553 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
michael@0 554 break;
michael@0 555 }
michael@0 556 case kNoPersp_MatrixType: {
michael@0 557 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
michael@0 558 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
michael@0 559 break;
michael@0 560 }
michael@0 561 case kGeneral_MatrixType: {
michael@0 562 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
michael@0 563 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
michael@0 564 break;
michael@0 565 }
michael@0 566 default:
michael@0 567 GrCrash("Unexpected matrixs type.");
michael@0 568 }
michael@0 569 }
michael@0 570 }
michael@0 571
michael@0 572 GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
michael@0 573 GrGLFragmentOnlyShaderBuilder* builder,
michael@0 574 int reserveCount)
michael@0 575 : fBuilder(builder)
michael@0 576 , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
michael@0 577 }
michael@0 578
michael@0 579 void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
michael@0 580 GrGLProgramEffects::EffectKey key,
michael@0 581 const char* outColor,
michael@0 582 const char* inColor,
michael@0 583 int stageIndex) {
michael@0 584 SkASSERT(NULL != fProgramEffects.get());
michael@0 585 fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
michael@0 586 }

mercurial