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 |