1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrBezierEffect.h" 9#include "GrShaderCaps.h" 10#include "glsl/GrGLSLFragmentShaderBuilder.h" 11#include "glsl/GrGLSLGeometryProcessor.h" 12#include "glsl/GrGLSLProgramDataManager.h" 13#include "glsl/GrGLSLUniformHandler.h" 14#include "glsl/GrGLSLUtil.h" 15#include "glsl/GrGLSLVarying.h" 16#include "glsl/GrGLSLVertexGeoBuilder.h" 17 18class GrGLConicEffect : public GrGLSLGeometryProcessor { 19public: 20 GrGLConicEffect(const GrGeometryProcessor&); 21 22 void onEmitCode(EmitArgs&, GrGPArgs*) override; 23 24 static inline void GenKey(const GrGeometryProcessor&, 25 const GrShaderCaps&, 26 GrProcessorKeyBuilder*); 27 28 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 29 FPCoordTransformIter&& transformIter) override { 30 const GrConicEffect& ce = primProc.cast<GrConicEffect>(); 31 32 if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) { 33 fViewMatrix = ce.viewMatrix(); 34 float viewMatrix[3 * 3]; 35 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 36 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 37 } 38 39 if (ce.color() != fColor) { 40 float c[4]; 41 GrColorToRGBAFloat(ce.color(), c); 42 pdman.set4fv(fColorUniform, 1, c); 43 fColor = ce.color(); 44 } 45 46 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) { 47 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale())); 48 fCoverageScale = ce.coverageScale(); 49 } 50 this->setTransformDataHelper(ce.localMatrix(), pdman, &transformIter); 51 } 52 53private: 54 SkMatrix fViewMatrix; 55 GrColor fColor; 56 uint8_t fCoverageScale; 57 GrClipEdgeType fEdgeType; 58 UniformHandle fColorUniform; 59 UniformHandle fCoverageScaleUniform; 60 UniformHandle fViewMatrixUniform; 61 62 typedef GrGLSLGeometryProcessor INHERITED; 63}; 64 65GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor) 66 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) { 67 const GrConicEffect& ce = processor.cast<GrConicEffect>(); 68 fEdgeType = ce.getEdgeType(); 69} 70 71void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 72 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 73 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>(); 74 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 75 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 76 77 // emit attributes 78 varyingHandler->emitAttributes(gp); 79 80 GrGLSLVarying v(kFloat4_GrSLType); 81 varyingHandler->addVarying("ConicCoeffs", &v); 82 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName); 83 84 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 85 // Setup pass through color 86 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); 87 88 // Setup position 89 this->writeOutputPosition(vertBuilder, 90 uniformHandler, 91 gpArgs, 92 gp.inPosition()->fName, 93 gp.viewMatrix(), 94 &fViewMatrixUniform); 95 96 // emit transforms with position 97 this->emitTransforms(vertBuilder, 98 varyingHandler, 99 uniformHandler, 100 gp.inPosition()->asShaderVar(), 101 gp.localMatrix(), 102 args.fFPCoordTransformHandler); 103 104 // TODO: we should check on the number of bits float and half provide and use the smallest one 105 // that suffices. Additionally we should assert that the upstream code only lets us get here if 106 // either float or half provides the required number of bits. 107 108 GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0); 109 GrShaderVar dklmdx("dklmdx", kFloat3_GrSLType, 0); 110 GrShaderVar dklmdy("dklmdy", kFloat3_GrSLType, 0); 111 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0); 112 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0); 113 GrShaderVar gF("gF", kFloat2_GrSLType, 0); 114 GrShaderVar gFM("gFM", kFloat_GrSLType, 0); 115 GrShaderVar func("func", kFloat_GrSLType, 0); 116 117 fragBuilder->declAppend(edgeAlpha); 118 fragBuilder->declAppend(dklmdx); 119 fragBuilder->declAppend(dklmdy); 120 fragBuilder->declAppend(dfdx); 121 fragBuilder->declAppend(dfdy); 122 fragBuilder->declAppend(gF); 123 fragBuilder->declAppend(gFM); 124 fragBuilder->declAppend(func); 125 126 switch (fEdgeType) { 127 case GrClipEdgeType::kHairlineAA: { 128 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); 129 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); 130 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 131 dfdx.c_str(), 132 v.fsIn(), dklmdx.c_str(), 133 v.fsIn(), dklmdx.c_str(), 134 v.fsIn(), dklmdx.c_str()); 135 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 136 dfdy.c_str(), 137 v.fsIn(), dklmdy.c_str(), 138 v.fsIn(), dklmdy.c_str(), 139 v.fsIn(), dklmdy.c_str()); 140 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), 141 dfdy.c_str()); 142 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", 143 gFM.c_str(), gF.c_str(), gF.c_str()); 144 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;", 145 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 146 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str()); 147 fragBuilder->codeAppendf("%s = %s / %s;", 148 edgeAlpha.c_str(), func.c_str(), gFM.c_str()); 149 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);", 150 edgeAlpha.c_str(), edgeAlpha.c_str()); 151 // Add line below for smooth cubic ramp 152 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 153 break; 154 } 155 case GrClipEdgeType::kFillAA: { 156 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); 157 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); 158 fragBuilder->codeAppendf("%s =" 159 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 160 dfdx.c_str(), 161 v.fsIn(), dklmdx.c_str(), 162 v.fsIn(), dklmdx.c_str(), 163 v.fsIn(), dklmdx.c_str()); 164 fragBuilder->codeAppendf("%s =" 165 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 166 dfdy.c_str(), 167 v.fsIn(), dklmdy.c_str(), 168 v.fsIn(), dklmdy.c_str(), 169 v.fsIn(), dklmdy.c_str()); 170 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), 171 dfdy.c_str()); 172 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", 173 gFM.c_str(), gF.c_str(), gF.c_str()); 174 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", 175 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 176 fragBuilder->codeAppendf("%s = %s / %s;", 177 edgeAlpha.c_str(), func.c_str(), gFM.c_str()); 178 fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);", 179 edgeAlpha.c_str(), edgeAlpha.c_str()); 180 // Add line below for smooth cubic ramp 181 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 182 break; 183 } 184 case GrClipEdgeType::kFillBW: { 185 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", 186 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 187 fragBuilder->codeAppendf("%s = float(%s < 0.0);", 188 edgeAlpha.c_str(), edgeAlpha.c_str()); 189 break; 190 } 191 default: 192 SK_ABORT("Shouldn't get here"); 193 } 194 195 // TODO should we really be doing this? 196 if (gp.coverageScale() != 0xff) { 197 const char* coverageScale; 198 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 199 kFloat_GrSLType, 200 "Coverage", 201 &coverageScale); 202 fragBuilder->codeAppendf("%s = half4(%s * %s);", 203 args.fOutputCoverage, coverageScale, edgeAlpha.c_str()); 204 } else { 205 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); 206 } 207} 208 209void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp, 210 const GrShaderCaps&, 211 GrProcessorKeyBuilder* b) { 212 const GrConicEffect& ce = gp.cast<GrConicEffect>(); 213 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 214 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0; 215 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; 216 key |= ComputePosKey(ce.viewMatrix()) << 5; 217 b->add32(key); 218} 219 220////////////////////////////////////////////////////////////////////////////// 221 222GrConicEffect::~GrConicEffect() {} 223 224void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, 225 GrProcessorKeyBuilder* b) const { 226 GrGLConicEffect::GenKey(*this, caps, b); 227} 228 229GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) const { 230 return new GrGLConicEffect(*this); 231} 232 233GrConicEffect::GrConicEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage, 234 GrClipEdgeType edgeType, const SkMatrix& localMatrix, 235 bool usesLocalCoords) 236 : INHERITED(kGrConicEffect_ClassID) 237 , fColor(color) 238 , fViewMatrix(viewMatrix) 239 , fLocalMatrix(viewMatrix) 240 , fUsesLocalCoords(usesLocalCoords) 241 , fCoverageScale(coverage) 242 , fEdgeType(edgeType) { 243 fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); 244 fInConicCoeffs = &this->addVertexAttrib("inConicCoeffs", kHalf4_GrVertexAttribType); 245} 246 247////////////////////////////////////////////////////////////////////////////// 248 249GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect); 250 251#if GR_TEST_UTILS 252sk_sp<GrGeometryProcessor> GrConicEffect::TestCreate(GrProcessorTestData* d) { 253 sk_sp<GrGeometryProcessor> gp; 254 do { 255 GrClipEdgeType edgeType = 256 static_cast<GrClipEdgeType>( 257 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); 258 gp = GrConicEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom), 259 edgeType, *d->caps(), GrTest::TestMatrix(d->fRandom), 260 d->fRandom->nextBool()); 261 } while (nullptr == gp); 262 return gp; 263} 264#endif 265 266////////////////////////////////////////////////////////////////////////////// 267// Quad 268////////////////////////////////////////////////////////////////////////////// 269 270class GrGLQuadEffect : public GrGLSLGeometryProcessor { 271public: 272 GrGLQuadEffect(const GrGeometryProcessor&); 273 274 void onEmitCode(EmitArgs&, GrGPArgs*) override; 275 276 static inline void GenKey(const GrGeometryProcessor&, 277 const GrShaderCaps&, 278 GrProcessorKeyBuilder*); 279 280 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 281 FPCoordTransformIter&& transformIter) override { 282 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>(); 283 284 if (!qe.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(qe.viewMatrix())) { 285 fViewMatrix = qe.viewMatrix(); 286 float viewMatrix[3 * 3]; 287 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 288 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 289 } 290 291 if (qe.color() != fColor) { 292 float c[4]; 293 GrColorToRGBAFloat(qe.color(), c); 294 pdman.set4fv(fColorUniform, 1, c); 295 fColor = qe.color(); 296 } 297 298 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) { 299 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale())); 300 fCoverageScale = qe.coverageScale(); 301 } 302 this->setTransformDataHelper(qe.localMatrix(), pdman, &transformIter); 303 } 304 305private: 306 SkMatrix fViewMatrix; 307 GrColor fColor; 308 uint8_t fCoverageScale; 309 GrClipEdgeType fEdgeType; 310 UniformHandle fColorUniform; 311 UniformHandle fCoverageScaleUniform; 312 UniformHandle fViewMatrixUniform; 313 314 typedef GrGLSLGeometryProcessor INHERITED; 315}; 316 317GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor) 318 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) { 319 const GrQuadEffect& ce = processor.cast<GrQuadEffect>(); 320 fEdgeType = ce.getEdgeType(); 321} 322 323void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 324 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 325 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>(); 326 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 327 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 328 329 // emit attributes 330 varyingHandler->emitAttributes(gp); 331 332 GrGLSLVarying v(kHalf4_GrSLType); 333 varyingHandler->addVarying("HairQuadEdge", &v); 334 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName); 335 336 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 337 // Setup pass through color 338 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); 339 340 // Setup position 341 this->writeOutputPosition(vertBuilder, 342 uniformHandler, 343 gpArgs, 344 gp.inPosition()->fName, 345 gp.viewMatrix(), 346 &fViewMatrixUniform); 347 348 // emit transforms with position 349 this->emitTransforms(vertBuilder, 350 varyingHandler, 351 uniformHandler, 352 gp.inPosition()->asShaderVar(), 353 gp.localMatrix(), 354 args.fFPCoordTransformHandler); 355 356 fragBuilder->codeAppendf("half edgeAlpha;"); 357 358 switch (fEdgeType) { 359 case GrClipEdgeType::kHairlineAA: { 360 fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn()); 361 fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn()); 362 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," 363 " 2.0 * %s.x * duvdy.x - duvdy.y);", 364 v.fsIn(), v.fsIn()); 365 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", 366 v.fsIn(), v.fsIn(), v.fsIn()); 367 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));"); 368 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);"); 369 // Add line below for smooth cubic ramp 370 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 371 break; 372 } 373 case GrClipEdgeType::kFillAA: { 374 fragBuilder->codeAppendf("half2 duvdx = dFdx(%s.xy);", v.fsIn()); 375 fragBuilder->codeAppendf("half2 duvdy = dFdy(%s.xy);", v.fsIn()); 376 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," 377 " 2.0 * %s.x * duvdy.x - duvdy.y);", 378 v.fsIn(), v.fsIn()); 379 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", 380 v.fsIn(), v.fsIn(), v.fsIn()); 381 fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));"); 382 fragBuilder->codeAppend("edgeAlpha = clamp(0.5 - edgeAlpha, 0.0, 1.0);"); 383 // Add line below for smooth cubic ramp 384 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 385 break; 386 } 387 case GrClipEdgeType::kFillBW: { 388 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", 389 v.fsIn(), v.fsIn(), v.fsIn()); 390 fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);"); 391 break; 392 } 393 default: 394 SK_ABORT("Shouldn't get here"); 395 } 396 397 if (0xff != gp.coverageScale()) { 398 const char* coverageScale; 399 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 400 kHalf_GrSLType, 401 "Coverage", 402 &coverageScale); 403 fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage, 404 coverageScale); 405 } else { 406 fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); 407 } 408} 409 410void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp, 411 const GrShaderCaps&, 412 GrProcessorKeyBuilder* b) { 413 const GrQuadEffect& ce = gp.cast<GrQuadEffect>(); 414 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 415 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0; 416 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; 417 key |= ComputePosKey(ce.viewMatrix()) << 5; 418 b->add32(key); 419} 420 421////////////////////////////////////////////////////////////////////////////// 422 423GrQuadEffect::~GrQuadEffect() {} 424 425void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps, 426 GrProcessorKeyBuilder* b) const { 427 GrGLQuadEffect::GenKey(*this, caps, b); 428} 429 430GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const { 431 return new GrGLQuadEffect(*this); 432} 433 434GrQuadEffect::GrQuadEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage, 435 GrClipEdgeType edgeType, const SkMatrix& localMatrix, 436 bool usesLocalCoords) 437 : INHERITED(kGrQuadEffect_ClassID) 438 , fColor(color) 439 , fViewMatrix(viewMatrix) 440 , fLocalMatrix(localMatrix) 441 , fUsesLocalCoords(usesLocalCoords) 442 , fCoverageScale(coverage) 443 , fEdgeType(edgeType) { 444 fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); 445 fInHairQuadEdge = &this->addVertexAttrib("inHairQuadEdge", kHalf4_GrVertexAttribType); 446} 447 448////////////////////////////////////////////////////////////////////////////// 449 450GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect); 451 452#if GR_TEST_UTILS 453sk_sp<GrGeometryProcessor> GrQuadEffect::TestCreate(GrProcessorTestData* d) { 454 sk_sp<GrGeometryProcessor> gp; 455 do { 456 GrClipEdgeType edgeType = static_cast<GrClipEdgeType>( 457 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); 458 gp = GrQuadEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom), edgeType, 459 *d->caps(), GrTest::TestMatrix(d->fRandom), 460 d->fRandom->nextBool()); 461 } while (nullptr == gp); 462 return gp; 463} 464#endif 465 466////////////////////////////////////////////////////////////////////////////// 467// Cubic 468////////////////////////////////////////////////////////////////////////////// 469 470class GrGLCubicEffect : public GrGLSLGeometryProcessor { 471public: 472 GrGLCubicEffect(const GrGeometryProcessor&); 473 474 void onEmitCode(EmitArgs&, GrGPArgs*) override; 475 476 static inline void GenKey(const GrGeometryProcessor&, 477 const GrShaderCaps&, 478 GrProcessorKeyBuilder*); 479 480 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 481 FPCoordTransformIter&& transformIter) override { 482 const GrCubicEffect& ce = primProc.cast<GrCubicEffect>(); 483 484 if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) { 485 fViewMatrix = ce.viewMatrix(); 486 float viewMatrix[3 * 3]; 487 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 488 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 489 } 490 491 if (!fDevKLMMatrix.cheapEqualTo(ce.devKLMMatrix())) { 492 fDevKLMMatrix = ce.devKLMMatrix(); 493 float devKLMMatrix[3 * 3]; 494 GrGLSLGetMatrix<3>(devKLMMatrix, fDevKLMMatrix); 495 pdman.setMatrix3f(fDevKLMUniform, devKLMMatrix); 496 } 497 498 if (ce.color() != fColor) { 499 float c[4]; 500 GrColorToRGBAFloat(ce.color(), c); 501 pdman.set4fv(fColorUniform, 1, c); 502 fColor = ce.color(); 503 } 504 505 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); 506 } 507 508private: 509 SkMatrix fViewMatrix; 510 SkMatrix fDevKLMMatrix; 511 GrColor fColor; 512 GrClipEdgeType fEdgeType; 513 UniformHandle fColorUniform; 514 UniformHandle fViewMatrixUniform; 515 UniformHandle fDevKLMUniform; 516 517 typedef GrGLSLGeometryProcessor INHERITED; 518}; 519 520GrGLCubicEffect::GrGLCubicEffect(const GrGeometryProcessor& processor) 521 : fViewMatrix(SkMatrix::InvalidMatrix()) 522 , fDevKLMMatrix(SkMatrix::InvalidMatrix()) 523 , fColor(GrColor_ILLEGAL) { 524 const GrCubicEffect& ce = processor.cast<GrCubicEffect>(); 525 fEdgeType = ce.getEdgeType(); 526} 527 528void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 529 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 530 const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>(); 531 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 532 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 533 534 // emit attributes 535 varyingHandler->emitAttributes(gp); 536 537 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 538 // Setup pass through color 539 if (!gp.colorIgnored()) { 540 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); 541 } 542 543 // Setup position 544 this->writeOutputPosition(vertBuilder, 545 uniformHandler, 546 gpArgs, 547 gp.inPosition()->fName, 548 gp.viewMatrix(), 549 &fViewMatrixUniform); 550 551 // Setup KLM 552 const char* devkLMMatrixName; 553 fDevKLMUniform = uniformHandler->addUniform(kVertex_GrShaderFlag, kFloat3x3_GrSLType, "KLM", 554 &devkLMMatrixName); 555 GrGLSLVarying v(kFloat3_GrSLType); 556 varyingHandler->addVarying("CubicCoeffs", &v); 557 vertBuilder->codeAppendf("%s = %s * float3(%s, 1);", 558 v.vsOut(), devkLMMatrixName, gpArgs->fPositionVar.c_str()); 559 560 561 GrGLSLVarying gradCoeffs(kFloat4_GrSLType); 562 if (GrClipEdgeType::kFillAA == fEdgeType || GrClipEdgeType::kHairlineAA == fEdgeType) { 563 varyingHandler->addVarying("GradCoeffs", &gradCoeffs); 564 vertBuilder->codeAppendf("float k = %s[0], l = %s[1], m = %s[2];", 565 v.vsOut(), v.vsOut(), v.vsOut()); 566 vertBuilder->codeAppendf("float2 gk = float2(%s[0][0], %s[1][0]), " 567 "gl = float2(%s[0][1], %s[1][1]), " 568 "gm = float2(%s[0][2], %s[1][2]);", 569 devkLMMatrixName, devkLMMatrixName, devkLMMatrixName, 570 devkLMMatrixName, devkLMMatrixName, devkLMMatrixName); 571 vertBuilder->codeAppendf("%s = float4(3 * k * gk, -m * gl - l * gm);", 572 gradCoeffs.vsOut()); 573 } 574 575 // emit transforms with position 576 this->emitTransforms(vertBuilder, 577 varyingHandler, 578 uniformHandler, 579 gp.inPosition()->asShaderVar(), 580 args.fFPCoordTransformHandler); 581 582 GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0); 583 GrShaderVar gF("gF", kFloat2_GrSLType, 0); 584 GrShaderVar func("func", kFloat_GrSLType, 0); 585 586 fragBuilder->declAppend(edgeAlpha); 587 fragBuilder->declAppend(gF); 588 fragBuilder->declAppend(func); 589 590 switch (fEdgeType) { 591 case GrClipEdgeType::kHairlineAA: { 592 fragBuilder->codeAppendf("%s = %s.x * %s.xy + %s.zw;", 593 gF.c_str(), v.fsIn(), gradCoeffs.fsIn(), gradCoeffs.fsIn()); 594 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;", 595 func.c_str(), v.fsIn(), v.fsIn(), 596 v.fsIn(), v.fsIn(), v.fsIn()); 597 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str()); 598 fragBuilder->codeAppendf("%s = %s * inversesqrt(dot(%s, %s));", 599 edgeAlpha.c_str(), func.c_str(), gF.c_str(), gF.c_str()); 600 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);", 601 edgeAlpha.c_str(), edgeAlpha.c_str()); 602 // Add line below for smooth cubic ramp 603 // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);", 604 // edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(), 605 // edgeAlpha.c_str()); 606 break; 607 } 608 case GrClipEdgeType::kFillAA: { 609 fragBuilder->codeAppendf("%s = %s.x * %s.xy + %s.zw;", 610 gF.c_str(), v.fsIn(), gradCoeffs.fsIn(), gradCoeffs.fsIn()); 611 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;", 612 func.c_str(), 613 v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 614 fragBuilder->codeAppendf("%s = %s * inversesqrt(dot(%s, %s));", 615 edgeAlpha.c_str(), func.c_str(), gF.c_str(), gF.c_str()); 616 fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);", 617 edgeAlpha.c_str(), edgeAlpha.c_str()); 618 // Add line below for smooth cubic ramp 619 // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);", 620 // edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(), 621 // edgeAlpha.c_str()); 622 break; 623 } 624 case GrClipEdgeType::kFillBW: { 625 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;", 626 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), 627 v.fsIn(), v.fsIn(), v.fsIn()); 628 fragBuilder->codeAppendf("%s = half(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str()); 629 break; 630 } 631 default: 632 SK_ABORT("Shouldn't get here"); 633 } 634 635 636 fragBuilder->codeAppendf("%s = float4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); 637} 638 639void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp, 640 const GrShaderCaps&, 641 GrProcessorKeyBuilder* b) { 642 const GrCubicEffect& ce = gp.cast<GrCubicEffect>(); 643 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 644 key |= ComputePosKey(ce.viewMatrix()) << 5; 645 b->add32(key); 646} 647 648////////////////////////////////////////////////////////////////////////////// 649 650GrCubicEffect::~GrCubicEffect() {} 651 652void GrCubicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { 653 GrGLCubicEffect::GenKey(*this, caps, b); 654} 655 656GrGLSLPrimitiveProcessor* GrCubicEffect::createGLSLInstance(const GrShaderCaps&) const { 657 return new GrGLCubicEffect(*this); 658} 659 660GrCubicEffect::GrCubicEffect(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& 661 devKLMMatrix, GrClipEdgeType edgeType) 662 : INHERITED(kGrCubicEffect_ClassID) 663 , fColor(color) 664 , fViewMatrix(viewMatrix) 665 , fDevKLMMatrix(devKLMMatrix) 666 , fEdgeType(edgeType) { 667 fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType); 668} 669 670////////////////////////////////////////////////////////////////////////////// 671 672GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrCubicEffect); 673 674#if GR_TEST_UTILS 675sk_sp<GrGeometryProcessor> GrCubicEffect::TestCreate(GrProcessorTestData* d) { 676 sk_sp<GrGeometryProcessor> gp; 677 do { 678 GrClipEdgeType edgeType = 679 static_cast<GrClipEdgeType>( 680 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); 681 gp = GrCubicEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom), 682 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool(), edgeType, 683 *d->caps()); 684 } while (nullptr == gp); 685 return gp; 686} 687#endif 688