| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkTwoPointRadialGradient.h" | 9 #include "SkTwoPointRadialGradient.h" |
| 10 | 10 |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 const char* outputColor, | 390 const char* outputColor, |
| 391 const char* inputColor, | 391 const char* inputColor, |
| 392 const TransformedCoordsArray&, | 392 const TransformedCoordsArray&, |
| 393 const TextureSamplerArray&) SK_OVERRIDE; | 393 const TextureSamplerArray&) SK_OVERRIDE; |
| 394 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 394 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
| 395 | 395 |
| 396 static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); | 396 static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); |
| 397 | 397 |
| 398 protected: | 398 protected: |
| 399 | 399 |
| 400 UniformHandle fVSParamUni; | 400 UniformHandle fParamUni; |
| 401 UniformHandle fFSParamUni; | |
| 402 | 401 |
| 403 const char* fVSVaryingName; | 402 const char* fVSVaryingName; |
| 404 const char* fFSVaryingName; | 403 const char* fFSVaryingName; |
| 405 | 404 |
| 406 bool fIsDegenerate; | 405 bool fIsDegenerate; |
| 407 | 406 |
| 408 // @{ | 407 // @{ |
| 409 /// Values last uploaded as uniforms | 408 /// Values last uploaded as uniforms |
| 410 | 409 |
| 411 SkScalar fCachedCenter; | 410 SkScalar fCachedCenter; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 this->fPosRoot == s.fPosRoot); | 455 this->fPosRoot == s.fPosRoot); |
| 457 } | 456 } |
| 458 | 457 |
| 459 GrRadial2Gradient(GrContext* ctx, | 458 GrRadial2Gradient(GrContext* ctx, |
| 460 const SkTwoPointRadialGradient& shader, | 459 const SkTwoPointRadialGradient& shader, |
| 461 const SkMatrix& matrix, | 460 const SkMatrix& matrix, |
| 462 SkShader::TileMode tm) | 461 SkShader::TileMode tm) |
| 463 : INHERITED(ctx, shader, matrix, tm) | 462 : INHERITED(ctx, shader, matrix, tm) |
| 464 , fCenterX1(shader.getCenterX1()) | 463 , fCenterX1(shader.getCenterX1()) |
| 465 , fRadius0(shader.getStartRadius()) | 464 , fRadius0(shader.getStartRadius()) |
| 466 , fPosRoot(shader.getDiffRadius() < 0) { } | 465 , fPosRoot(shader.getDiffRadius() < 0) { |
| 466 // We pass the linear part of the quadratic as a varying. |
| 467 // float b = 2.0 * (fCenterX1 * x - fRadius0 * z) |
| 468 fBTransform = this->getCoordTransform(); |
| 469 SkMatrix& bMatrix = *fBTransform.accessMatrix(); |
| 470 bMatrix[SkMatrix::kMScaleX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatr
ix::kMScaleX]) - |
| 471 SkScalarMul(fRadius0, bMatrix[SkMatri
x::kMPersp0])); |
| 472 bMatrix[SkMatrix::kMSkewX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatri
x::kMSkewX]) - |
| 473 SkScalarMul(fRadius0, bMatrix[SkMatrix
::kMPersp1])); |
| 474 bMatrix[SkMatrix::kMTransX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatr
ix::kMTransX]) - |
| 475 SkScalarMul(fRadius0, bMatrix[SkMatri
x::kMPersp2])); |
| 476 this->addCoordTransform(&fBTransform); |
| 477 } |
| 467 | 478 |
| 468 GR_DECLARE_EFFECT_TEST; | 479 GR_DECLARE_EFFECT_TEST; |
| 469 | 480 |
| 470 // @{ | 481 // @{ |
| 471 // Cache of values - these can change arbitrarily, EXCEPT | 482 // Cache of values - these can change arbitrarily, EXCEPT |
| 472 // we shouldn't change between degenerate and non-degenerate?! | 483 // we shouldn't change between degenerate and non-degenerate?! |
| 473 | 484 |
| 474 SkScalar fCenterX1; | 485 GrCoordTransform fBTransform; |
| 475 SkScalar fRadius0; | 486 SkScalar fCenterX1; |
| 476 SkBool8 fPosRoot; | 487 SkScalar fRadius0; |
| 488 SkBool8 fPosRoot; |
| 477 | 489 |
| 478 // @} | 490 // @} |
| 479 | 491 |
| 480 typedef GrGradientEffect INHERITED; | 492 typedef GrGradientEffect INHERITED; |
| 481 }; | 493 }; |
| 482 | 494 |
| 483 ///////////////////////////////////////////////////////////////////// | 495 ///////////////////////////////////////////////////////////////////// |
| 484 | 496 |
| 485 GR_DEFINE_EFFECT_TEST(GrRadial2Gradient); | 497 GR_DEFINE_EFFECT_TEST(GrRadial2Gradient); |
| 486 | 498 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 | 540 |
| 529 void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, | 541 void GrGLRadial2Gradient::emitCode(GrGLShaderBuilder* builder, |
| 530 const GrDrawEffect& drawEffect, | 542 const GrDrawEffect& drawEffect, |
| 531 EffectKey key, | 543 EffectKey key, |
| 532 const char* outputColor, | 544 const char* outputColor, |
| 533 const char* inputColor, | 545 const char* inputColor, |
| 534 const TransformedCoordsArray& coords, | 546 const TransformedCoordsArray& coords, |
| 535 const TextureSamplerArray& samplers) { | 547 const TextureSamplerArray& samplers) { |
| 536 | 548 |
| 537 this->emitUniforms(builder, key); | 549 this->emitUniforms(builder, key); |
| 538 // 2 copies of uniform array, 1 for each of vertex & fragment shader, | 550 fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility
, |
| 539 // to work around Xoom bug. Doesn't seem to cause performance decrease | 551 kFloat_GrSLType, "Radial2FSParams", 6); |
| 540 // in test apps, but need to keep an eye on it. | |
| 541 fVSParamUni = builder->addUniformArray(GrGLShaderBuilder::kVertex_Visibility
, | |
| 542 kFloat_GrSLType, "Radial2VSParams", 6
); | |
| 543 fFSParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibili
ty, | |
| 544 kFloat_GrSLType, "Radial2FSParams", 6
); | |
| 545 | 552 |
| 546 // For radial gradients without perspective we can pass the linear | 553 SkString cName("c"); |
| 547 // part of the quadratic as a varying. | 554 SkString ac4Name("ac4"); |
| 548 GrGLShaderBuilder::VertexBuilder* vertexBuilder = | 555 SkString rootName("root"); |
| 549 (kVec2f_GrSLType == coords[0].type()) ? builder->getVertexBuilder() : NU
LL; | 556 SkString t; |
| 550 if (NULL != vertexBuilder) { | 557 SkString p0; |
| 551 vertexBuilder->addVarying(kFloat_GrSLType, "Radial2BCoeff", | 558 SkString p1; |
| 552 &fVSVaryingName, &fFSVaryingName); | 559 SkString p2; |
| 560 SkString p3; |
| 561 SkString p4; |
| 562 SkString p5; |
| 563 builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0); |
| 564 builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1); |
| 565 builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2); |
| 566 builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3); |
| 567 builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4); |
| 568 builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5); |
| 569 |
| 570 // We interpolate the linear component in coords[1]. |
| 571 SkASSERT(coords[0].type() == coords[1].type()); |
| 572 const char* coords2D; |
| 573 SkString bVar; |
| 574 if (kVec3f_GrSLType == coords[0].type()) { |
| 575 builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\
n", |
| 576 coords[0].c_str(), coords[1].c_str(), coords[0].c
_str()); |
| 577 coords2D = "interpolants.xy"; |
| 578 bVar = "interpolants.z"; |
| 579 } else { |
| 580 coords2D = coords[0].c_str(); |
| 581 bVar.printf("%s.x", coords[1].c_str()); |
| 553 } | 582 } |
| 554 | 583 |
| 555 // VS | 584 // c = (x^2)+(y^2) - params[4] |
| 556 { | 585 builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", |
| 557 SkString p2; | 586 cName.c_str(), coords2D, coords2D, p4.c_str()); |
| 558 SkString p3; | |
| 559 builder->getUniformVariable(fVSParamUni).appendArrayAccess(2, &p2); | |
| 560 builder->getUniformVariable(fVSParamUni).appendArrayAccess(3, &p3); | |
| 561 | 587 |
| 562 // For radial gradients without perspective we can pass the linear | 588 // If we aren't degenerate, emit some extra code, and accept a slightly |
| 563 // part of the quadratic as a varying. | 589 // more complex coord. |
| 564 if (NULL != vertexBuilder) { | 590 if (!fIsDegenerate) { |
| 565 // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3]) | 591 |
| 566 vertexBuilder->vsCodeAppendf("\t%s = 2.0 *(%s * %s.x - %s);\n", | 592 // ac4 = 4.0 * params[0] * c |
| 567 fVSVaryingName, p2.c_str(), | 593 builder->fsCodeAppendf("\tfloat %s = %s * 4.0 * %s;\n", |
| 568 coords[0].getVSName().c_str(), p3.c_s
tr()); | 594 ac4Name.c_str(), p0.c_str(), |
| 569 } | 595 cName.c_str()); |
| 596 |
| 597 // root = sqrt(b^2-4ac) |
| 598 // (abs to avoid exception due to fp precision) |
| 599 builder->fsCodeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", |
| 600 rootName.c_str(), bVar.c_str(), bVar.c_str(), |
| 601 ac4Name.c_str()); |
| 602 |
| 603 // t is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] |
| 604 t.printf("(-%s + %s * %s) * %s", bVar.c_str(), p5.c_str(), |
| 605 rootName.c_str(), p1.c_str()); |
| 606 } else { |
| 607 // t is: -c/b |
| 608 t.printf("-%s / %s", cName.c_str(), bVar.c_str()); |
| 570 } | 609 } |
| 571 | 610 |
| 572 // FS | 611 this->emitColor(builder, t.c_str(), key, outputColor, inputColor, samplers); |
| 573 { | |
| 574 SkString coords2D = builder->ensureFSCoords2D(coords, 0); | |
| 575 SkString cName("c"); | |
| 576 SkString ac4Name("ac4"); | |
| 577 SkString rootName("root"); | |
| 578 SkString t; | |
| 579 SkString p0; | |
| 580 SkString p1; | |
| 581 SkString p2; | |
| 582 SkString p3; | |
| 583 SkString p4; | |
| 584 SkString p5; | |
| 585 builder->getUniformVariable(fFSParamUni).appendArrayAccess(0, &p0); | |
| 586 builder->getUniformVariable(fFSParamUni).appendArrayAccess(1, &p1); | |
| 587 builder->getUniformVariable(fFSParamUni).appendArrayAccess(2, &p2); | |
| 588 builder->getUniformVariable(fFSParamUni).appendArrayAccess(3, &p3); | |
| 589 builder->getUniformVariable(fFSParamUni).appendArrayAccess(4, &p4); | |
| 590 builder->getUniformVariable(fFSParamUni).appendArrayAccess(5, &p5); | |
| 591 | |
| 592 // If we we're able to interpolate the linear component, | |
| 593 // bVar is the varying; otherwise compute it | |
| 594 SkString bVar; | |
| 595 if (NULL != vertexBuilder) { | |
| 596 bVar = fFSVaryingName; | |
| 597 } else { | |
| 598 bVar = "b"; | |
| 599 builder->fsCodeAppendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", | |
| 600 bVar.c_str(), p2.c_str(), coords2D.c_str(), p
3.c_str()); | |
| 601 } | |
| 602 | |
| 603 // c = (x^2)+(y^2) - params[4] | |
| 604 builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", | |
| 605 cName.c_str(), | |
| 606 coords2D.c_str(), | |
| 607 coords2D.c_str(), | |
| 608 p4.c_str()); | |
| 609 | |
| 610 // If we aren't degenerate, emit some extra code, and accept a slightly | |
| 611 // more complex coord. | |
| 612 if (!fIsDegenerate) { | |
| 613 | |
| 614 // ac4 = 4.0 * params[0] * c | |
| 615 builder->fsCodeAppendf("\tfloat %s = %s * 4.0 * %s;\n", | |
| 616 ac4Name.c_str(), p0.c_str(), | |
| 617 cName.c_str()); | |
| 618 | |
| 619 // root = sqrt(b^2-4ac) | |
| 620 // (abs to avoid exception due to fp precision) | |
| 621 builder->fsCodeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", | |
| 622 rootName.c_str(), bVar.c_str(), bVar.c_str(), | |
| 623 ac4Name.c_str()); | |
| 624 | |
| 625 // t is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] | |
| 626 t.printf("(-%s + %s * %s) * %s", bVar.c_str(), p5.c_str(), | |
| 627 rootName.c_str(), p1.c_str()); | |
| 628 } else { | |
| 629 // t is: -c/b | |
| 630 t.printf("-%s / %s", cName.c_str(), bVar.c_str()); | |
| 631 } | |
| 632 | |
| 633 this->emitColor(builder, t.c_str(), key, outputColor, inputColor, sample
rs); | |
| 634 } | |
| 635 } | 612 } |
| 636 | 613 |
| 637 void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman, | 614 void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman, |
| 638 const GrDrawEffect& drawEffect) { | 615 const GrDrawEffect& drawEffect) { |
| 639 INHERITED::setData(uman, drawEffect); | 616 INHERITED::setData(uman, drawEffect); |
| 640 const GrRadial2Gradient& data = drawEffect.castEffect<GrRadial2Gradient>(); | 617 const GrRadial2Gradient& data = drawEffect.castEffect<GrRadial2Gradient>(); |
| 641 SkASSERT(data.isDegenerate() == fIsDegenerate); | 618 SkASSERT(data.isDegenerate() == fIsDegenerate); |
| 642 SkScalar centerX1 = data.center(); | 619 SkScalar centerX1 = data.center(); |
| 643 SkScalar radius0 = data.radius(); | 620 SkScalar radius0 = data.radius(); |
| 644 if (fCachedCenter != centerX1 || | 621 if (fCachedCenter != centerX1 || |
| 645 fCachedRadius != radius0 || | 622 fCachedRadius != radius0 || |
| 646 fCachedPosRoot != data.isPosRoot()) { | 623 fCachedPosRoot != data.isPosRoot()) { |
| 647 | 624 |
| 648 SkScalar a = SkScalarMul(centerX1, centerX1) - SK_Scalar1; | 625 SkScalar a = SkScalarMul(centerX1, centerX1) - SK_Scalar1; |
| 649 | 626 |
| 650 // When we're in the degenerate (linear) case, the second | 627 // When we're in the degenerate (linear) case, the second |
| 651 // value will be INF but the program doesn't read it. (We | 628 // value will be INF but the program doesn't read it. (We |
| 652 // use the same 6 uniforms even though we don't need them | 629 // use the same 6 uniforms even though we don't need them |
| 653 // all in the linear case just to keep the code complexity | 630 // all in the linear case just to keep the code complexity |
| 654 // down). | 631 // down). |
| 655 float values[6] = { | 632 float values[6] = { |
| 656 SkScalarToFloat(a), | 633 SkScalarToFloat(a), |
| 657 1 / (2.f * SkScalarToFloat(a)), | 634 1 / (2.f * SkScalarToFloat(a)), |
| 658 SkScalarToFloat(centerX1), | 635 SkScalarToFloat(centerX1), |
| 659 SkScalarToFloat(radius0), | 636 SkScalarToFloat(radius0), |
| 660 SkScalarToFloat(SkScalarMul(radius0, radius0)), | 637 SkScalarToFloat(SkScalarMul(radius0, radius0)), |
| 661 data.isPosRoot() ? 1.f : -1.f | 638 data.isPosRoot() ? 1.f : -1.f |
| 662 }; | 639 }; |
| 663 | 640 |
| 664 uman.set1fv(fVSParamUni, 0, 6, values); | 641 uman.set1fv(fParamUni, 0, 6, values); |
| 665 uman.set1fv(fFSParamUni, 0, 6, values); | |
| 666 fCachedCenter = centerX1; | 642 fCachedCenter = centerX1; |
| 667 fCachedRadius = radius0; | 643 fCachedRadius = radius0; |
| 668 fCachedPosRoot = data.isPosRoot(); | 644 fCachedPosRoot = data.isPosRoot(); |
| 669 } | 645 } |
| 670 } | 646 } |
| 671 | 647 |
| 672 GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrDrawEffect& drawEffect
, | 648 GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrDrawEffect& drawEffect
, |
| 673 const GrGLCaps&) { | 649 const GrGLCaps&) { |
| 674 enum { | 650 enum { |
| 675 kIsDegenerate = 1 << kBaseKeyBitCnt, | 651 kIsDegenerate = 1 << kBaseKeyBitCnt, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 706 } | 682 } |
| 707 | 683 |
| 708 #else | 684 #else |
| 709 | 685 |
| 710 GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext*, const SkPaint&) c
onst { | 686 GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext*, const SkPaint&) c
onst { |
| 711 SkDEBUGFAIL("Should not call in GPU-less build"); | 687 SkDEBUGFAIL("Should not call in GPU-less build"); |
| 712 return NULL; | 688 return NULL; |
| 713 } | 689 } |
| 714 | 690 |
| 715 #endif | 691 #endif |
| OLD | NEW |