| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrGeometryProcessor.h" | 8 #include "GrGeometryProcessor.h" |
| 9 | 9 |
| 10 #include "GrCoordTransform.h" | |
| 11 #include "GrInvariantOutput.h" | 10 #include "GrInvariantOutput.h" |
| 12 #include "gl/GrGLGeometryProcessor.h" | |
| 13 | |
| 14 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 15 | |
| 16 /** | |
| 17 * The key for an individual coord transform is made up of a matrix type, a prec
ision, and a bit | |
| 18 * that indicates the source of the input coords. | |
| 19 */ | |
| 20 enum { | |
| 21 kMatrixTypeKeyBits = 1, | |
| 22 kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, | |
| 23 | |
| 24 kPrecisionBits = 2, | |
| 25 kPrecisionShift = kMatrixTypeKeyBits, | |
| 26 | |
| 27 kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)), | |
| 28 kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag, | |
| 29 | |
| 30 kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2, | |
| 31 }; | |
| 32 | |
| 33 GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits)); | |
| 34 | |
| 35 /** | |
| 36 * We specialize the vertex code for each of these matrix types. | |
| 37 */ | |
| 38 enum MatrixType { | |
| 39 kNoPersp_MatrixType = 0, | |
| 40 kGeneral_MatrixType = 1, | |
| 41 }; | |
| 42 | |
| 43 uint32_t | |
| 44 GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, tr
ue>& coords) const { | |
| 45 uint32_t totalKey = 0; | |
| 46 for (int t = 0; t < coords.count(); ++t) { | |
| 47 uint32_t key = 0; | |
| 48 const GrCoordTransform* coordTransform = coords[t]; | |
| 49 if (coordTransform->getMatrix().hasPerspective()) { | |
| 50 key |= kGeneral_MatrixType; | |
| 51 } else { | |
| 52 key |= kNoPersp_MatrixType; | |
| 53 } | |
| 54 | |
| 55 if (kLocal_GrCoordSet == coordTransform->sourceCoords() && | |
| 56 !this->hasExplicitLocalCoords()) { | |
| 57 key |= kPositionCoords_Flag; | |
| 58 } else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) { | |
| 59 key |= kDeviceCoords_Flag; | |
| 60 } | |
| 61 | |
| 62 GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits)); | |
| 63 key |= (coordTransform->precision() << kPrecisionShift); | |
| 64 | |
| 65 key <<= kTransformKeyBits * t; | |
| 66 | |
| 67 SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to
overlap | |
| 68 totalKey |= key; | |
| 69 } | |
| 70 return totalKey; | |
| 71 } | |
| 72 | |
| 73 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 74 | 11 |
| 75 void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) co
nst { | 12 void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) co
nst { |
| 76 if (fHasVertexColor) { | 13 if (fHasVertexColor) { |
| 77 if (fOpaqueVertexColors) { | 14 if (fOpaqueVertexColors) { |
| 78 out->setUnknownOpaqueFourComponents(); | 15 out->setUnknownOpaqueFourComponents(); |
| 79 } else { | 16 } else { |
| 80 out->setUnknownFourComponents(); | 17 out->setUnknownFourComponents(); |
| 81 } | 18 } |
| 82 } else { | 19 } else { |
| 83 out->setKnownFourComponents(fColor); | 20 out->setKnownFourComponents(fColor); |
| 84 } | 21 } |
| 85 this->onGetInvariantOutputColor(out); | 22 this->onGetInvariantOutputColor(out); |
| 86 } | 23 } |
| 87 | 24 |
| 88 void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
const { | 25 void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
const { |
| 89 this->onGetInvariantOutputCoverage(out); | 26 this->onGetInvariantOutputCoverage(out); |
| 90 } | 27 } |
| 91 | 28 |
| 92 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 93 | 29 |
| 94 #include "gl/builders/GrGLProgramBuilder.h" | |
| 95 | |
| 96 SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix, | |
| 97 const GrCoordTransform& coor
dTransform) { | |
| 98 SkMatrix combined; | |
| 99 // We only apply the localmatrix to localcoords | |
| 100 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { | |
| 101 combined.setConcat(coordTransform.getMatrix(), localMatrix); | |
| 102 } 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 } | |
| 117 | |
| 118 void | |
| 119 GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb, | |
| 120 GrGPInput inputType, | |
| 121 const char* outputName, | |
| 122 const GrGeometryProcessor::Attribu
te* colorAttr, | |
| 123 UniformHandle* colorUniform) { | |
| 124 GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder(); | |
| 125 if (kUniform_GrGPInput == inputType) { | |
| 126 SkASSERT(colorUniform); | |
| 127 const char* stagedLocalVarName; | |
| 128 *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
| 129 kVec4f_GrSLType, | |
| 130 kDefault_GrSLPrecision, | |
| 131 "Color", | |
| 132 &stagedLocalVarName); | |
| 133 fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName); | |
| 134 } else if (kAttribute_GrGPInput == inputType) { | |
| 135 SkASSERT(colorAttr); | |
| 136 pb->addPassThroughAttribute(colorAttr, outputName); | |
| 137 } else if (kAllOnes_GrGPInput == inputType) { | |
| 138 fs->codeAppendf("%s = vec4(1);", outputName); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) { | |
| 143 fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, | |
| 144 kMat33f_GrSLType, kDefault_GrSLPrecision
, | |
| 145 "uViewM", | |
| 146 &fViewMatrixName); | |
| 147 } | |
| 148 | |
| 149 void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager&
pdman, | |
| 150 const SkMatrix& viewMatrix) { | |
| 151 if (!fViewMatrix.cheapEqualTo(viewMatrix)) { | |
| 152 SkASSERT(fViewMatrixUniform.isValid()); | |
| 153 fViewMatrix = viewMatrix; | |
| 154 | |
| 155 GrGLfloat viewMatrix[3 * 3]; | |
| 156 GrGLGetMatrix<3>(viewMatrix, fViewMatrix); | |
| 157 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 162 | |
| 163 | |
| 164 void GrGLGeometryProcessor::emitCode(EmitArgs& args) { | |
| 165 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
| 166 GrGPArgs gpArgs; | |
| 167 this->onEmitCode(args, &gpArgs); | |
| 168 vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar); | |
| 169 } | |
| 170 | |
| 171 void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb, | |
| 172 const GrShaderVar& posVar, | |
| 173 const char* localCoords, | |
| 174 const SkMatrix& localMatrix, | |
| 175 const TransformsIn& tin, | |
| 176 TransformsOut* tout) { | |
| 177 GrGLVertexBuilder* vb = pb->getVertexShaderBuilder(); | |
| 178 tout->push_back_n(tin.count()); | |
| 179 fInstalledTransforms.push_back_n(tin.count()); | |
| 180 for (int i = 0; i < tin.count(); i++) { | |
| 181 const ProcCoords& coordTransforms = tin[i]; | |
| 182 fInstalledTransforms[i].push_back_n(coordTransforms.count()); | |
| 183 for (int t = 0; t < coordTransforms.count(); t++) { | |
| 184 SkString strUniName("StageMatrix"); | |
| 185 strUniName.appendf("_%i_%i", i, t); | |
| 186 GrSLType varyingType; | |
| 187 | |
| 188 GrCoordSet coordType = coordTransforms[t]->sourceCoords(); | |
| 189 uint32_t type = coordTransforms[t]->getMatrix().getType(); | |
| 190 if (kLocal_GrCoordSet == coordType) { | |
| 191 type |= localMatrix.getType(); | |
| 192 } | |
| 193 varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_
GrSLType : | |
| 194 kVec2f_
GrSLType; | |
| 195 GrSLPrecision precision = coordTransforms[t]->precision(); | |
| 196 | |
| 197 const char* uniName; | |
| 198 fInstalledTransforms[i][t].fHandle = | |
| 199 pb->addUniform(GrGLProgramBuilder::kVertex_Visibility, | |
| 200 kMat33f_GrSLType, precision, | |
| 201 strUniName.c_str(), | |
| 202 &uniName).toShaderBuilderIndex(); | |
| 203 | |
| 204 SkString strVaryingName("MatrixCoord"); | |
| 205 strVaryingName.appendf("_%i_%i", i, t); | |
| 206 | |
| 207 GrGLVertToFrag v(varyingType); | |
| 208 pb->addVarying(strVaryingName.c_str(), &v, precision); | |
| 209 | |
| 210 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyin
gType); | |
| 211 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords
, | |
| 212 (SkString(v.fsIn()), varyingType)); | |
| 213 | |
| 214 // varying = matrix * coords (logically) | |
| 215 if (kDevice_GrCoordSet == coordType) { | |
| 216 if (kVec2f_GrSLType == varyingType) { | |
| 217 if (kVec2f_GrSLType == posVar.getType()) { | |
| 218 vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", | |
| 219 v.vsOut(), uniName, posVar.c_str()); | |
| 220 } else { | |
| 221 // The brackets here are just to scope the temp variable | |
| 222 vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVa
r.c_str()); | |
| 223 vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z)
; }", v.vsOut()); | |
| 224 } | |
| 225 } else { | |
| 226 if (kVec2f_GrSLType == posVar.getType()) { | |
| 227 vb->codeAppendf("%s = %s * vec3(%s, 1);", | |
| 228 v.vsOut(), uniName, posVar.c_str()); | |
| 229 } else { | |
| 230 vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, pos
Var.c_str()); | |
| 231 } | |
| 232 } | |
| 233 } else { | |
| 234 if (kVec2f_GrSLType == varyingType) { | |
| 235 vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), un
iName, localCoords); | |
| 236 } else { | |
| 237 vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName
, localCoords); | |
| 238 } | |
| 239 } | |
| 240 } | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 | |
| 245 void | |
| 246 GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc, | |
| 247 const GrGLProgramDataManager& pdman, | |
| 248 int index, | |
| 249 const SkTArray<const GrCoordTransform*,
true>& transforms) { | |
| 250 SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index]; | |
| 251 int numTransforms = transforms.count(); | |
| 252 for (int t = 0; t < numTransforms; ++t) { | |
| 253 SkASSERT(procTransforms[t].fHandle.isValid()); | |
| 254 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *
transforms[t]); | |
| 255 if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) { | |
| 256 pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle()
, transform); | |
| 257 procTransforms[t].fCurrentValue = transform; | |
| 258 } | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder, | |
| 263 GrGPArgs* gpArgs, | |
| 264 const char* posName, | |
| 265 const SkMatrix& mat, | |
| 266 const char* matName) { | |
| 267 if (mat.isIdentity()) { | |
| 268 gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); | |
| 269 | |
| 270 vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), po
sName); | |
| 271 } else if (!mat.hasPerspective()) { | |
| 272 gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2"); | |
| 273 | |
| 274 vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));", | |
| 275 gpArgs->fPositionVar.c_str(), matName, posName); | |
| 276 } else { | |
| 277 gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3"); | |
| 278 | |
| 279 vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);", | |
| 280 gpArgs->fPositionVar.c_str(), matName, posName); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 285 | |
| 286 #include "gl/GrGLGpu.h" | |
| 287 #include "gl/GrGLPathRendering.h" | |
| 288 | |
| 289 struct PathBatchTracker { | |
| 290 GrGPInput fInputColorType; | |
| 291 GrGPInput fInputCoverageType; | |
| 292 GrColor fColor; | |
| 293 bool fUsesLocalCoords; | |
| 294 }; | |
| 295 | |
| 296 GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracke
r&) | |
| 297 : fColor(GrColor_ILLEGAL) {} | |
| 298 | |
| 299 void GrGLPathProcessor::emitCode(EmitArgs& args) { | |
| 300 GrGLGPBuilder* pb = args.fPB; | |
| 301 GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder(); | |
| 302 const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>(); | |
| 303 | |
| 304 // emit transforms | |
| 305 this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut); | |
| 306 | |
| 307 // Setup uniform color | |
| 308 if (kUniform_GrGPInput == local.fInputColorType) { | |
| 309 const char* stagedLocalVarName; | |
| 310 fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility, | |
| 311 kVec4f_GrSLType, | |
| 312 kDefault_GrSLPrecision, | |
| 313 "Color", | |
| 314 &stagedLocalVarName); | |
| 315 fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName); | |
| 316 } | |
| 317 | |
| 318 // setup constant solid coverage | |
| 319 if (kAllOnes_GrGPInput == local.fInputCoverageType) { | |
| 320 fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage); | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 void GrGLPathProcessor::GenKey(const GrPathProcessor&, | |
| 325 const GrBatchTracker& bt, | |
| 326 const GrGLCaps&, | |
| 327 GrProcessorKeyBuilder* b) { | |
| 328 const PathBatchTracker& local = bt.cast<PathBatchTracker>(); | |
| 329 b->add32(local.fInputColorType | local.fInputCoverageType << 16); | |
| 330 } | |
| 331 | |
| 332 void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman, | |
| 333 const GrPrimitiveProcessor& primProc, | |
| 334 const GrBatchTracker& bt) { | |
| 335 const PathBatchTracker& local = bt.cast<PathBatchTracker>(); | |
| 336 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { | |
| 337 GrGLfloat c[4]; | |
| 338 GrColorToRGBAFloat(local.fColor, c); | |
| 339 pdman.set4fv(fColorUniform, 1, c); | |
| 340 fColor = local.fColor; | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 class GrGLLegacyPathProcessor : public GrGLPathProcessor { | |
| 345 public: | |
| 346 GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracke
r& bt, | |
| 347 int maxTexCoords) | |
| 348 : INHERITED(pathProc, bt) | |
| 349 , fTexCoordSetCnt(0) { | |
| 350 SkDEBUGCODE(fMaxTexCoords = maxTexCoords;) | |
| 351 } | |
| 352 | |
| 353 int addTexCoordSets(int count) { | |
| 354 int firstFreeCoordSet = fTexCoordSetCnt; | |
| 355 fTexCoordSetCnt += count; | |
| 356 SkASSERT(fMaxTexCoords >= fTexCoordSetCnt); | |
| 357 return firstFreeCoordSet; | |
| 358 } | |
| 359 | |
| 360 void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut*
tout) SK_OVERRIDE { | |
| 361 tout->push_back_n(tin.count()); | |
| 362 fInstalledTransforms.push_back_n(tin.count()); | |
| 363 for (int i = 0; i < tin.count(); i++) { | |
| 364 const ProcCoords& coordTransforms = tin[i]; | |
| 365 int texCoordIndex = this->addTexCoordSets(coordTransforms.count()); | |
| 366 | |
| 367 // Use the first uniform location as the texcoord index. | |
| 368 fInstalledTransforms[i].push_back_n(1); | |
| 369 fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex); | |
| 370 | |
| 371 SkString name; | |
| 372 for (int t = 0; t < coordTransforms.count(); ++t) { | |
| 373 GrSLType type = coordTransforms[t]->getMatrix().hasPerspective()
? kVec3f_GrSLType : | |
| 374
kVec2f_GrSLType; | |
| 375 | |
| 376 name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCo
ordIndex++); | |
| 377 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCo
ords, (name, type)); | |
| 378 } | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 void setTransformData(const GrPrimitiveProcessor& primProc, | |
| 383 int index, | |
| 384 const SkTArray<const GrCoordTransform*, true>& transfo
rms, | |
| 385 GrGLPathRendering* glpr, | |
| 386 GrGLuint) SK_OVERRIDE { | |
| 387 // We've hidden the texcoord index in the first entry of the transforms
array for each | |
| 388 // effect | |
| 389 int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle(); | |
| 390 for (int t = 0; t < transforms.count(); ++t) { | |
| 391 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(
), *transforms[t]); | |
| 392 GrGLPathRendering::PathTexGenComponents components = | |
| 393 GrGLPathRendering::kST_PathTexGenComponents; | |
| 394 if (transform.hasPerspective()) { | |
| 395 components = GrGLPathRendering::kSTR_PathTexGenComponents; | |
| 396 } | |
| 397 glpr->enablePathTexGen(texCoordIndex++, components, transform); | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE { | |
| 402 glpr->flushPathTexGenSettings(fTexCoordSetCnt); | |
| 403 } | |
| 404 | |
| 405 private: | |
| 406 SkDEBUGCODE(int fMaxTexCoords;) | |
| 407 int fTexCoordSetCnt; | |
| 408 | |
| 409 typedef GrGLPathProcessor INHERITED; | |
| 410 }; | |
| 411 | |
| 412 class GrGLNormalPathProcessor : public GrGLPathProcessor { | |
| 413 public: | |
| 414 GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracke
r& bt) | |
| 415 : INHERITED(pathProc, bt) {} | |
| 416 | |
| 417 void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin, | |
| 418 TransformsOut* tout) SK_OVERRIDE { | |
| 419 tout->push_back_n(tin.count()); | |
| 420 fInstalledTransforms.push_back_n(tin.count()); | |
| 421 for (int i = 0; i < tin.count(); i++) { | |
| 422 const ProcCoords& coordTransforms = tin[i]; | |
| 423 fInstalledTransforms[i].push_back_n(coordTransforms.count()); | |
| 424 for (int t = 0; t < coordTransforms.count(); t++) { | |
| 425 GrSLType varyingType = | |
| 426 coordTransforms[t]->getMatrix().hasPerspective() ? kVec3
f_GrSLType : | |
| 427 kVec2
f_GrSLType; | |
| 428 | |
| 429 | |
| 430 SkString strVaryingName("MatrixCoord"); | |
| 431 strVaryingName.appendf("_%i_%i", i, t); | |
| 432 GrGLVertToFrag v(varyingType); | |
| 433 pb->addVarying(strVaryingName.c_str(), &v); | |
| 434 SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_
back(); | |
| 435 varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.
back(); | |
| 436 varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1; | |
| 437 varyingInfo.fType = varyingType; | |
| 438 fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo
.fLocation); | |
| 439 fInstalledTransforms[i][t].fType = varyingType; | |
| 440 | |
| 441 SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCo
ords, | |
| 442 (SkString(v.fsIn()), varyingType)); | |
| 443 } | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) { | |
| 448 int count = fSeparableVaryingInfos.count(); | |
| 449 for (int i = 0; i < count; ++i) { | |
| 450 GrGLint location; | |
| 451 GR_GL_CALL_RET(gpu->glInterface(), | |
| 452 location, | |
| 453 GetProgramResourceLocation(programId, | |
| 454 GR_GL_FRAGMENT_INPUT, | |
| 455 fSeparableVaryingInfos[i].
fVariable.c_str())); | |
| 456 fSeparableVaryingInfos[i].fLocation = location; | |
| 457 } | |
| 458 } | |
| 459 | |
| 460 void setTransformData(const GrPrimitiveProcessor& primProc, | |
| 461 int index, | |
| 462 const SkTArray<const GrCoordTransform*, true>& coordTr
ansforms, | |
| 463 GrGLPathRendering* glpr, | |
| 464 GrGLuint programID) SK_OVERRIDE { | |
| 465 SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index]; | |
| 466 int numTransforms = transforms.count(); | |
| 467 for (int t = 0; t < numTransforms; ++t) { | |
| 468 SkASSERT(transforms[t].fHandle.isValid()); | |
| 469 const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(
), | |
| 470 *coordTransforms[t]); | |
| 471 if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { | |
| 472 continue; | |
| 473 } | |
| 474 transforms[t].fCurrentValue = transform; | |
| 475 const SeparableVaryingInfo& fragmentInput = | |
| 476 fSeparableVaryingInfos[transforms[t].fHandle.handle()]; | |
| 477 SkASSERT(transforms[t].fType == kVec2f_GrSLType || | |
| 478 transforms[t].fType == kVec3f_GrSLType); | |
| 479 unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3
; | |
| 480 glpr->setProgramPathFragmentInputTransform(programID, | |
| 481 fragmentInput.fLocation, | |
| 482 GR_GL_OBJECT_LINEAR, | |
| 483 components, | |
| 484 transform); | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 private: | |
| 489 struct SeparableVaryingInfo { | |
| 490 GrSLType fType; | |
| 491 GrGLShaderVar fVariable; | |
| 492 GrGLint fLocation; | |
| 493 }; | |
| 494 | |
| 495 | |
| 496 typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray; | |
| 497 | |
| 498 SeparableVaryingInfoArray fSeparableVaryingInfos; | |
| 499 | |
| 500 typedef GrGLPathProcessor INHERITED; | |
| 501 }; | |
| 502 | |
| 503 GrPathProcessor::GrPathProcessor(GrColor color, | |
| 504 const SkMatrix& viewMatrix, | |
| 505 const SkMatrix& localMatrix) | |
| 506 : INHERITED(viewMatrix, localMatrix, true) | |
| 507 , fColor(color) { | |
| 508 this->initClassID<GrPathProcessor>(); | |
| 509 } | |
| 510 | |
| 511 void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const
{ | |
| 512 out->setKnownFourComponents(fColor); | |
| 513 } | |
| 514 | |
| 515 void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) con
st { | |
| 516 out->setKnownSingleComponent(0xff); | |
| 517 } | |
| 518 | |
| 519 void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo&
init) const { | |
| 520 PathBatchTracker* local = bt->cast<PathBatchTracker>(); | |
| 521 if (init.fColorIgnored) { | |
| 522 local->fInputColorType = kIgnored_GrGPInput; | |
| 523 local->fColor = GrColor_ILLEGAL; | |
| 524 } else { | |
| 525 local->fInputColorType = kUniform_GrGPInput; | |
| 526 local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() : | |
| 527 init.fOverrideC
olor; | |
| 528 } | |
| 529 | |
| 530 local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAl
lOnes_GrGPInput; | |
| 531 local->fUsesLocalCoords = init.fUsesLocalCoords; | |
| 532 } | |
| 533 | |
| 534 bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, | |
| 535 const GrPrimitiveProcessor& that, | |
| 536 const GrBatchTracker& t) const { | |
| 537 if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)
) { | |
| 538 return false; | |
| 539 } | |
| 540 | |
| 541 if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) { | |
| 542 return false; | |
| 543 } | |
| 544 | |
| 545 const PathBatchTracker& mine = m.cast<PathBatchTracker>(); | |
| 546 const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); | |
| 547 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | |
| 548 that, theirs.fUsesLocalCoords) && | |
| 549 CanCombineOutput(mine.fInputColorType, mine.fColor, | |
| 550 theirs.fInputColorType, theirs.fColor) && | |
| 551 CanCombineOutput(mine.fInputCoverageType, 0xff, | |
| 552 theirs.fInputCoverageType, 0xff); | |
| 553 } | |
| 554 | |
| 555 void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt, | |
| 556 const GrGLCaps& caps, | |
| 557 GrProcessorKeyBuilder* b) const { | |
| 558 GrGLPathProcessor::GenKey(*this, bt, caps, b); | |
| 559 } | |
| 560 | |
| 561 GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker&
bt, | |
| 562 const GrGLCaps& caps)
const { | |
| 563 SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport); | |
| 564 if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) { | |
| 565 return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt, | |
| 566 caps.maxFixedFunctionTexture
Coords())); | |
| 567 } else { | |
| 568 return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt)); | |
| 569 } | |
| 570 } | |
| 571 | |
| OLD | NEW |