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 18 class GrGLConicEffect : public GrGLSLGeometryProcessor { 19 public: 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 pdman.set4fv(fColorUniform, 1, ce.color().vec()); 41 fColor = ce.color(); 42 } 43 44 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) { 45 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale())); 46 fCoverageScale = ce.coverageScale(); 47 } 48 this->setTransformDataHelper(ce.localMatrix(), pdman, &transformIter); 49 } 50 51 private: 52 SkMatrix fViewMatrix; 53 SkPMColor4f fColor; 54 uint8_t fCoverageScale; 55 GrClipEdgeType fEdgeType; 56 UniformHandle fColorUniform; 57 UniformHandle fCoverageScaleUniform; 58 UniformHandle fViewMatrixUniform; 59 60 typedef GrGLSLGeometryProcessor INHERITED; 61 }; 62 63 GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor) 64 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) { 65 const GrConicEffect& ce = processor.cast<GrConicEffect>(); 66 fEdgeType = ce.getEdgeType(); 67 } 68 69 void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 70 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 71 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>(); 72 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 73 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 74 75 // emit attributes 76 varyingHandler->emitAttributes(gp); 77 78 GrGLSLVarying v(kFloat4_GrSLType); 79 varyingHandler->addVarying("ConicCoeffs", &v); 80 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name()); 81 82 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 83 // Setup pass through color 84 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); 85 86 // Setup position 87 this->writeOutputPosition(vertBuilder, 88 uniformHandler, 89 gpArgs, 90 gp.inPosition().name(), 91 gp.viewMatrix(), 92 &fViewMatrixUniform); 93 94 // emit transforms with position 95 this->emitTransforms(vertBuilder, 96 varyingHandler, 97 uniformHandler, 98 gp.inPosition().asShaderVar(), 99 gp.localMatrix(), 100 args.fFPCoordTransformHandler); 101 102 // TODO: we should check on the number of bits float and half provide and use the smallest one 103 // that suffices. Additionally we should assert that the upstream code only lets us get here if 104 // either float or half provides the required number of bits. 105 106 GrShaderVar edgeAlpha("edgeAlpha", kHalf_GrSLType, 0); 107 GrShaderVar dklmdx("dklmdx", kFloat3_GrSLType, 0); 108 GrShaderVar dklmdy("dklmdy", kFloat3_GrSLType, 0); 109 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0); 110 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0); 111 GrShaderVar gF("gF", kFloat2_GrSLType, 0); 112 GrShaderVar gFM("gFM", kFloat_GrSLType, 0); 113 GrShaderVar func("func", kFloat_GrSLType, 0); 114 115 fragBuilder->declAppend(edgeAlpha); 116 fragBuilder->declAppend(dklmdx); 117 fragBuilder->declAppend(dklmdy); 118 fragBuilder->declAppend(dfdx); 119 fragBuilder->declAppend(dfdy); 120 fragBuilder->declAppend(gF); 121 fragBuilder->declAppend(gFM); 122 fragBuilder->declAppend(func); 123 124 switch (fEdgeType) { 125 case GrClipEdgeType::kHairlineAA: { 126 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); 127 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); 128 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 129 dfdx.c_str(), 130 v.fsIn(), dklmdx.c_str(), 131 v.fsIn(), dklmdx.c_str(), 132 v.fsIn(), dklmdx.c_str()); 133 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 134 dfdy.c_str(), 135 v.fsIn(), dklmdy.c_str(), 136 v.fsIn(), dklmdy.c_str(), 137 v.fsIn(), dklmdy.c_str()); 138 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), 139 dfdy.c_str()); 140 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", 141 gFM.c_str(), gF.c_str(), gF.c_str()); 142 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;", 143 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 144 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str()); 145 fragBuilder->codeAppendf("%s = half(%s / %s);", 146 edgeAlpha.c_str(), func.c_str(), gFM.c_str()); 147 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);", 148 edgeAlpha.c_str(), edgeAlpha.c_str()); 149 // Add line below for smooth cubic ramp 150 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 151 break; 152 } 153 case GrClipEdgeType::kFillAA: { 154 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn()); 155 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn()); 156 fragBuilder->codeAppendf("%s =" 157 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 158 dfdx.c_str(), 159 v.fsIn(), dklmdx.c_str(), 160 v.fsIn(), dklmdx.c_str(), 161 v.fsIn(), dklmdx.c_str()); 162 fragBuilder->codeAppendf("%s =" 163 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;", 164 dfdy.c_str(), 165 v.fsIn(), dklmdy.c_str(), 166 v.fsIn(), dklmdy.c_str(), 167 v.fsIn(), dklmdy.c_str()); 168 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(), 169 dfdy.c_str()); 170 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", 171 gFM.c_str(), gF.c_str(), gF.c_str()); 172 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;", 173 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 174 fragBuilder->codeAppendf("%s = half(%s / %s);", 175 edgeAlpha.c_str(), func.c_str(), gFM.c_str()); 176 fragBuilder->codeAppendf("%s = saturate(0.5 - %s);", 177 edgeAlpha.c_str(), edgeAlpha.c_str()); 178 // Add line below for smooth cubic ramp 179 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 180 break; 181 } 182 case GrClipEdgeType::kFillBW: { 183 fragBuilder->codeAppendf("%s = half(%s.x * %s.x - %s.y * %s.z);", 184 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); 185 fragBuilder->codeAppendf("%s = half(%s < 0.0);", 186 edgeAlpha.c_str(), edgeAlpha.c_str()); 187 break; 188 } 189 default: 190 SK_ABORT("Shouldn't get here"); 191 } 192 193 // TODO should we really be doing this? 194 if (gp.coverageScale() != 0xff) { 195 const char* coverageScale; 196 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 197 kFloat_GrSLType, 198 "Coverage", 199 &coverageScale); 200 fragBuilder->codeAppendf("%s = half4(half(%s) * %s);", 201 args.fOutputCoverage, coverageScale, edgeAlpha.c_str()); 202 } else { 203 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); 204 } 205 } 206 207 void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp, 208 const GrShaderCaps&, 209 GrProcessorKeyBuilder* b) { 210 const GrConicEffect& ce = gp.cast<GrConicEffect>(); 211 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 212 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0; 213 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; 214 key |= ComputePosKey(ce.viewMatrix()) << 5; 215 b->add32(key); 216 } 217 218 ////////////////////////////////////////////////////////////////////////////// 219 220 constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[]; 221 222 GrConicEffect::~GrConicEffect() {} 223 224 void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, 225 GrProcessorKeyBuilder* b) const { 226 GrGLConicEffect::GenKey(*this, caps, b); 227 } 228 229 GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) const { 230 return new GrGLConicEffect(*this); 231 } 232 233 GrConicEffect::GrConicEffect(const SkPMColor4f& 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 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes)); 244 } 245 246 ////////////////////////////////////////////////////////////////////////////// 247 248 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect); 249 250 #if GR_TEST_UTILS 251 sk_sp<GrGeometryProcessor> GrConicEffect::TestCreate(GrProcessorTestData* d) { 252 sk_sp<GrGeometryProcessor> gp; 253 do { 254 GrClipEdgeType edgeType = 255 static_cast<GrClipEdgeType>( 256 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); 257 gp = GrConicEffect::Make(SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), 258 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(), 259 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); 260 } while (nullptr == gp); 261 return gp; 262 } 263 #endif 264 265 ////////////////////////////////////////////////////////////////////////////// 266 // Quad 267 ////////////////////////////////////////////////////////////////////////////// 268 269 class GrGLQuadEffect : public GrGLSLGeometryProcessor { 270 public: 271 GrGLQuadEffect(const GrGeometryProcessor&); 272 273 void onEmitCode(EmitArgs&, GrGPArgs*) override; 274 275 static inline void GenKey(const GrGeometryProcessor&, 276 const GrShaderCaps&, 277 GrProcessorKeyBuilder*); 278 279 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 280 FPCoordTransformIter&& transformIter) override { 281 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>(); 282 283 if (!qe.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(qe.viewMatrix())) { 284 fViewMatrix = qe.viewMatrix(); 285 float viewMatrix[3 * 3]; 286 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 287 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 288 } 289 290 if (qe.color() != fColor) { 291 pdman.set4fv(fColorUniform, 1, qe.color().vec()); 292 fColor = qe.color(); 293 } 294 295 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) { 296 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale())); 297 fCoverageScale = qe.coverageScale(); 298 } 299 this->setTransformDataHelper(qe.localMatrix(), pdman, &transformIter); 300 } 301 302 private: 303 SkMatrix fViewMatrix; 304 SkPMColor4f fColor; 305 uint8_t fCoverageScale; 306 GrClipEdgeType fEdgeType; 307 UniformHandle fColorUniform; 308 UniformHandle fCoverageScaleUniform; 309 UniformHandle fViewMatrixUniform; 310 311 typedef GrGLSLGeometryProcessor INHERITED; 312 }; 313 314 GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor) 315 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) { 316 const GrQuadEffect& ce = processor.cast<GrQuadEffect>(); 317 fEdgeType = ce.getEdgeType(); 318 } 319 320 void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 321 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 322 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>(); 323 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 324 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 325 326 // emit attributes 327 varyingHandler->emitAttributes(gp); 328 329 GrGLSLVarying v(kHalf4_GrSLType); 330 varyingHandler->addVarying("HairQuadEdge", &v); 331 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name()); 332 333 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 334 // Setup pass through color 335 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform); 336 337 // Setup position 338 this->writeOutputPosition(vertBuilder, 339 uniformHandler, 340 gpArgs, 341 gp.inPosition().name(), 342 gp.viewMatrix(), 343 &fViewMatrixUniform); 344 345 // emit transforms with position 346 this->emitTransforms(vertBuilder, 347 varyingHandler, 348 uniformHandler, 349 gp.inPosition().asShaderVar(), 350 gp.localMatrix(), 351 args.fFPCoordTransformHandler); 352 353 fragBuilder->codeAppendf("half edgeAlpha;"); 354 355 switch (fEdgeType) { 356 case GrClipEdgeType::kHairlineAA: { 357 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn()); 358 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn()); 359 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," 360 " 2.0 * %s.x * duvdy.x - duvdy.y);", 361 v.fsIn(), v.fsIn()); 362 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", 363 v.fsIn(), v.fsIn(), v.fsIn()); 364 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));"); 365 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);"); 366 // Add line below for smooth cubic ramp 367 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 368 break; 369 } 370 case GrClipEdgeType::kFillAA: { 371 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn()); 372 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn()); 373 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y," 374 " 2.0 * %s.x * duvdy.x - duvdy.y);", 375 v.fsIn(), v.fsIn()); 376 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", 377 v.fsIn(), v.fsIn(), v.fsIn()); 378 fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));"); 379 fragBuilder->codeAppend("edgeAlpha = saturate(0.5 - edgeAlpha);"); 380 // Add line below for smooth cubic ramp 381 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); 382 break; 383 } 384 case GrClipEdgeType::kFillBW: { 385 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);", 386 v.fsIn(), v.fsIn(), v.fsIn()); 387 fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);"); 388 break; 389 } 390 default: 391 SK_ABORT("Shouldn't get here"); 392 } 393 394 if (0xff != gp.coverageScale()) { 395 const char* coverageScale; 396 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 397 kHalf_GrSLType, 398 "Coverage", 399 &coverageScale); 400 fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage, 401 coverageScale); 402 } else { 403 fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage); 404 } 405 } 406 407 void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp, 408 const GrShaderCaps&, 409 GrProcessorKeyBuilder* b) { 410 const GrQuadEffect& ce = gp.cast<GrQuadEffect>(); 411 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 412 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0; 413 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0; 414 key |= ComputePosKey(ce.viewMatrix()) << 5; 415 b->add32(key); 416 } 417 418 ////////////////////////////////////////////////////////////////////////////// 419 420 constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[]; 421 422 GrQuadEffect::~GrQuadEffect() {} 423 424 void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps, 425 GrProcessorKeyBuilder* b) const { 426 GrGLQuadEffect::GenKey(*this, caps, b); 427 } 428 429 GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const { 430 return new GrGLQuadEffect(*this); 431 } 432 433 GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage, 434 GrClipEdgeType edgeType, const SkMatrix& localMatrix, 435 bool usesLocalCoords) 436 : INHERITED(kGrQuadEffect_ClassID) 437 , fColor(color) 438 , fViewMatrix(viewMatrix) 439 , fLocalMatrix(localMatrix) 440 , fUsesLocalCoords(usesLocalCoords) 441 , fCoverageScale(coverage) 442 , fEdgeType(edgeType) { 443 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes)); 444 } 445 446 ////////////////////////////////////////////////////////////////////////////// 447 448 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect); 449 450 #if GR_TEST_UTILS 451 sk_sp<GrGeometryProcessor> GrQuadEffect::TestCreate(GrProcessorTestData* d) { 452 sk_sp<GrGeometryProcessor> gp; 453 do { 454 GrClipEdgeType edgeType = static_cast<GrClipEdgeType>( 455 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); 456 gp = GrQuadEffect::Make(SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)), 457 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(), 458 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool()); 459 } while (nullptr == gp); 460 return gp; 461 } 462 #endif 463