Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: src/gpu/effects/GrRRectEffect.cpp

Issue 1517573002: Do elliptical clips in normalized space on devices with a "real" mediump (Closed) Base URL: https://skia.googlesource.com/skia.git@circlecorner
Patch Set: fix Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/GrOvalEffect.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "GrRRectEffect.h" 8 #include "GrRRectEffect.h"
9 9
10 #include "GrConvexPolyEffect.h" 10 #include "GrConvexPolyEffect.h"
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 virtual void emitCode(EmitArgs&) override; 491 virtual void emitCode(EmitArgs&) override;
492 492
493 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*); 493 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
494 494
495 protected: 495 protected:
496 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override ; 496 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override ;
497 497
498 private: 498 private:
499 GrGLSLProgramDataManager::UniformHandle fInnerRectUniform; 499 GrGLSLProgramDataManager::UniformHandle fInnerRectUniform;
500 GrGLSLProgramDataManager::UniformHandle fInvRadiiSqdUniform; 500 GrGLSLProgramDataManager::UniformHandle fInvRadiiSqdUniform;
501 SkRRect fPrevRRect; 501 GrGLSLProgramDataManager::UniformHandle fScaleUniform;
502 SkRRect fPrevRRect;
502 typedef GrGLSLFragmentProcessor INHERITED; 503 typedef GrGLSLFragmentProcessor INHERITED;
503 }; 504 };
504 505
505 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { 506 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) {
506 fPrevRRect.setEmpty(); 507 fPrevRRect.setEmpty();
507 } 508 }
508 509
509 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { 510 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
510 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); 511 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>();
511 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 512 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
(...skipping 11 matching lines...) Expand all
523 // to that corner. This means that points near the interior near the rrect t op edge will have 524 // to that corner. This means that points near the interior near the rrect t op edge will have
524 // a vector that points straight up for both the TL left and TR corners. Com puting an 525 // a vector that points straight up for both the TL left and TR corners. Com puting an
525 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, 526 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly,
526 // fragments near the other three edges will get the correct AA. Fragments i n the interior of 527 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
527 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will 528 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will
528 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. 529 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
529 // 530 //
530 // The code below is a simplified version of the above that performs maxs on the vector 531 // The code below is a simplified version of the above that performs maxs on the vector
531 // components before computing distances and alpha values so that only one d istance computation 532 // components before computing distances and alpha values so that only one d istance computation
532 // need be computed to determine the min alpha. 533 // need be computed to determine the min alpha.
533 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragm entPos); 534 fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos );
534 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, re ctName); 535 fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName );
536
537 // If we're on a device with a "real" mediump then we'll do the distance com putation in a space
538 // that is normalized by the largest radius. The scale uniform will be scale , 1/scale. The
539 // radii uniform values are already in this normalized space.
540 const char* scaleName = nullptr;
541 if (args.fGLSLCaps->floatPrecisionVaries()) {
542 fScaleUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme nt_Visibility,
543 kVec2f_GrSLType, kDefault_GrS LPrecision,
544 "scale", &scaleName);
545 }
546
535 // The uniforms with the inv squared radii are highp to prevent underflow. 547 // The uniforms with the inv squared radii are highp to prevent underflow.
536 switch (erre.getRRect().getType()) { 548 switch (erre.getRRect().getType()) {
537 case SkRRect::kSimple_Type: { 549 case SkRRect::kSimple_Type: {
538 const char *invRadiiXYSqdName; 550 const char *invRadiiXYSqdName;
539 fInvRadiiSqdUniform = uniformHandler->addUniform( 551 fInvRadiiSqdUniform = uniformHandler->addUniform(
540 GrGLSLUniformHandler::k Fragment_Visibility, 552 GrGLSLUniformHandler::k Fragment_Visibility,
541 kVec2f_GrSLType, kHigh_ GrSLPrecision, 553 kVec2f_GrSLType, kDefau lt_GrSLPrecision,
542 "invRadiiXY", 554 "invRadiiXY",
543 &invRadiiXYSqdName); 555 &invRadiiXYSqdName);
544 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n "); 556 fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);");
557 if (scaleName) {
558 fragBuilder->codeAppendf("dxy *= %s.y;", scaleName);
559 }
545 // Z is the x/y offsets divided by squared radii. 560 // Z is the x/y offsets divided by squared radii.
546 fragBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdNa me); 561 fragBuilder->codeAppendf("vec2 Z = dxy * %s.xy;", invRadiiXYSqdName) ;
547 break; 562 break;
548 } 563 }
549 case SkRRect::kNinePatch_Type: { 564 case SkRRect::kNinePatch_Type: {
550 const char *invRadiiLTRBSqdName; 565 const char *invRadiiLTRBSqdName;
551 fInvRadiiSqdUniform = uniformHandler->addUniform( 566 fInvRadiiSqdUniform = uniformHandler->addUniform(
552 GrGLSLUniformHandler::k Fragment_Visibility, 567 GrGLSLUniformHandler::k Fragment_Visibility,
553 kVec4f_GrSLType, kHigh_ GrSLPrecision, 568 kVec4f_GrSLType, kDefau lt_GrSLPrecision,
554 "invRadiiLTRB", 569 "invRadiiLTRB",
555 &invRadiiLTRBSqdName); 570 &invRadiiLTRBSqdName);
556 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n "); 571 if (scaleName) {
572 fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName);
573 fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName);
574 }
575 fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);");
557 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one 576 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
558 // corner where both the x and y offsets are positive, hence the max es. (The inverse 577 // corner where both the x and y offsets are positive, hence the max es. (The inverse
559 // squared radii will always be positive.) 578 // squared radii will always be positive.)
560 fragBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n", 579 fragBuilder->codeAppendf("vec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.z w), 0.0);",
561 invRadiiLTRBSqdName, invRadiiLTRBSqdName); 580 invRadiiLTRBSqdName, invRadiiLTRBSqdName);
581
562 break; 582 break;
563 } 583 }
564 default: 584 default:
565 SkFAIL("RRect should always be simple or nine-patch."); 585 SkFAIL("RRect should always be simple or nine-patch.");
566 } 586 }
567 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. 587 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
568 fragBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); 588 fragBuilder->codeAppend("float implicit = dot(Z, dxy) - 1.0;");
569 // grad_dot is the squared length of the gradient of the implicit. 589 // grad_dot is the squared length of the gradient of the implicit.
570 fragBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); 590 fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);");
571 // avoid calling inversesqrt on zero. 591 // avoid calling inversesqrt on zero.
572 fragBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); 592 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
573 fragBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(gra d_dot);\n"); 593 fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot );");
594 if (scaleName) {
595 fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
596 }
574 597
575 if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) { 598 if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
576 fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); 599 fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0 );");
577 } else { 600 } else {
578 fragBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); 601 fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0 );");
579 } 602 }
580 603
581 fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor, 604 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
582 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha ")).c_str()); 605 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha ")).c_str());
583 } 606 }
584 607
585 void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps &, 608 void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps &,
586 GrProcessorKeyBuilder* b) { 609 GrProcessorKeyBuilder* b) {
587 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>(); 610 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
588 GR_STATIC_ASSERT(kLast_GrProcessorEdgeType < (1 << 3)); 611 GR_STATIC_ASSERT(kLast_GrProcessorEdgeType < (1 << 3));
589 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3); 612 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3);
590 } 613 }
591 614
592 void GLEllipticalRRectEffect::onSetData(const GrGLSLProgramDataManager& pdman, 615 void GLEllipticalRRectEffect::onSetData(const GrGLSLProgramDataManager& pdman,
593 const GrProcessor& effect) { 616 const GrProcessor& effect) {
594 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>(); 617 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
595 const SkRRect& rrect = erre.getRRect(); 618 const SkRRect& rrect = erre.getRRect();
619 // If we're using a scale factor to work around precision issues, choose the largest radius
620 // as the scale factor. The inv radii need to be pre-adjusted by the scale f actor.
596 if (rrect != fPrevRRect) { 621 if (rrect != fPrevRRect) {
597 SkRect rect = rrect.getBounds(); 622 SkRect rect = rrect.getBounds();
598 const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner); 623 const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner);
599 SkASSERT(r0.fX >= kRadiusMin); 624 SkASSERT(r0.fX >= kRadiusMin);
600 SkASSERT(r0.fY >= kRadiusMin); 625 SkASSERT(r0.fY >= kRadiusMin);
601 switch (erre.getRRect().getType()) { 626 switch (erre.getRRect().getType()) {
602 case SkRRect::kSimple_Type: 627 case SkRRect::kSimple_Type:
603 rect.inset(r0.fX, r0.fY); 628 rect.inset(r0.fX, r0.fY);
604 pdman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), 629 if (fScaleUniform.isValid()) {
605 1.f / (r0.fY * r0.fY)); 630 if (r0.fX > r0.fY) {
631 pdman.set2f(fInvRadiiSqdUniform, 1.f, (r0.fX * r0.fX) / (r0.fY * r0.fY));
632 pdman.set2f(fScaleUniform, r0.fX, 1.f / r0.fX);
633 } else {
634 pdman.set2f(fInvRadiiSqdUniform, (r0.fY * r0.fY) / (r0.f X * r0.fX), 1.f);
635 pdman.set2f(fScaleUniform, r0.fY, 1.f / r0.fY);
636 }
637 } else {
638 pdman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
639 1.f / (r0.fY * r0.fY));
640 }
606 break; 641 break;
607 case SkRRect::kNinePatch_Type: { 642 case SkRRect::kNinePatch_Type: {
608 const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner); 643 const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner);
609 SkASSERT(r1.fX >= kRadiusMin); 644 SkASSERT(r1.fX >= kRadiusMin);
610 SkASSERT(r1.fY >= kRadiusMin); 645 SkASSERT(r1.fY >= kRadiusMin);
611 rect.fLeft += r0.fX; 646 rect.fLeft += r0.fX;
612 rect.fTop += r0.fY; 647 rect.fTop += r0.fY;
613 rect.fRight -= r1.fX; 648 rect.fRight -= r1.fX;
614 rect.fBottom -= r1.fY; 649 rect.fBottom -= r1.fY;
615 pdman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), 650 if (fScaleUniform.isValid()) {
616 1.f / (r0.fY * r0.fY), 651 float scale = SkTMax(SkTMax(r0.fX, r0.fY), SkTMax(r1.fX, r1. fY));
617 1.f / (r1.fX * r1.fX), 652 float scaleSqd = scale * scale;
618 1.f / (r1.fY * r1.fY)); 653 pdman.set4f(fInvRadiiSqdUniform, scaleSqd / (r0.fX * r0.fX),
654 scaleSqd / (r0.fY * r0.fY),
655 scaleSqd / (r1.fX * r1.fX),
656 scaleSqd / (r1.fY * r1.fY)) ;
657 pdman.set2f(fScaleUniform, scale, 1.f / scale);
658 } else {
659 pdman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
660 1.f / (r0.fY * r0.fY),
661 1.f / (r1.fX * r1.fX),
662 1.f / (r1.fY * r1.fY));
663 }
619 break; 664 break;
620 } 665 }
621 default: 666 default:
622 SkFAIL("RRect should always be simple or nine-patch."); 667 SkFAIL("RRect should always be simple or nine-patch.");
623 } 668 }
624 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); 669 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom);
625 fPrevRRect = rrect; 670 fPrevRRect = rrect;
626 } 671 }
627 } 672 }
628 673
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 if (rrect.isNinePatch()) { 773 if (rrect.isNinePatch()) {
729 return EllipticalRRectEffect::Create(edgeType, rrect); 774 return EllipticalRRectEffect::Create(edgeType, rrect);
730 } 775 }
731 return nullptr; 776 return nullptr;
732 } 777 }
733 } 778 }
734 } 779 }
735 780
736 return nullptr; 781 return nullptr;
737 } 782 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrOvalEffect.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698