Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "GrFragmentProcessor.h" | 11 #include "GrFragmentProcessor.h" |
| 12 #include "GrInvariantOutput.h" | 12 #include "GrInvariantOutput.h" |
| 13 #include "GrOvalEffect.h" | 13 #include "GrOvalEffect.h" |
| 14 #include "SkRRect.h" | 14 #include "SkRRect.h" |
| 15 #include "gl/GrGLFragmentProcessor.h" | 15 #include "gl/GrGLFragmentProcessor.h" |
| 16 #include "gl/builders/GrGLProgramBuilder.h" | 16 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 17 #include "glsl/GrGLSLProgramBuilder.h" | |
| 17 #include "glsl/GrGLSLProgramDataManager.h" | 18 #include "glsl/GrGLSLProgramDataManager.h" |
| 18 | 19 |
| 19 // The effects defined here only handle rrect radii >= kRadiusMin. | 20 // The effects defined here only handle rrect radii >= kRadiusMin. |
| 20 static const SkScalar kRadiusMin = SK_ScalarHalf; | 21 static const SkScalar kRadiusMin = SK_ScalarHalf; |
| 21 | 22 |
| 22 ////////////////////////////////////////////////////////////////////////////// | 23 ////////////////////////////////////////////////////////////////////////////// |
| 23 | 24 |
| 24 class CircularRRectEffect : public GrFragmentProcessor { | 25 class CircularRRectEffect : public GrFragmentProcessor { |
| 25 public: | 26 public: |
| 26 | 27 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 } | 149 } |
| 149 | 150 |
| 150 void GLCircularRRectEffect::emitCode(EmitArgs& args) { | 151 void GLCircularRRectEffect::emitCode(EmitArgs& args) { |
| 151 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>(); | 152 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>(); |
| 152 const char *rectName; | 153 const char *rectName; |
| 153 const char *radiusPlusHalfName; | 154 const char *radiusPlusHalfName; |
| 154 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom | 155 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom |
| 155 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has | 156 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has |
| 156 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by | 157 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by |
| 157 // half a pixel. | 158 // half a pixel. |
| 158 fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_ Visibility, | 159 fInnerRectUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragmen t_Visibility, |
| 159 kVec4f_GrSLType, kDefault_GrSLPrecis ion, | 160 kVec4f_GrSLType, kDefault_GrSLPrecis ion, |
| 160 "innerRect", | 161 "innerRect", |
| 161 &rectName); | 162 &rectName); |
| 162 fRadiusPlusHalfUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag ment_Visibility, | 163 fRadiusPlusHalfUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFr agment_Visibility, |
| 163 kFloat_GrSLType, kDefault_GrSLP recision, | 164 kFloat_GrSLType, kDefault_GrSLP recision, |
| 164 "radiusPlusHalf", | 165 "radiusPlusHalf", |
| 165 &radiusPlusHalfName); | 166 &radiusPlusHalfName); |
| 166 | 167 |
| 167 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); | 168 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder() ; |
| 168 const char* fragmentPos = fsBuilder->fragmentPosition(); | 169 const char* fragmentPos = fsBuilder->fragmentPosition(); |
| 169 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position | 170 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position |
| 170 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant | 171 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant |
| 171 // to that corner. This means that points near the interior near the rrect t op edge will have | 172 // to that corner. This means that points near the interior near the rrect t op edge will have |
| 172 // a vector that points straight up for both the TL left and TR corners. Com puting an | 173 // a vector that points straight up for both the TL left and TR corners. Com puting an |
| 173 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, | 174 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, |
| 174 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | 175 // fragments near the other three edges will get the correct AA. Fragments i n the interior of |
| 175 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will | 176 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will |
| 176 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | 177 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. |
| 177 // The code below is a simplified version of the above that performs maxs on the vector | 178 // The code below is a simplified version of the above that performs maxs on the vector |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 } | 358 } |
| 358 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); | 359 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); |
| 359 pdman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 360 pdman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
| 360 fPrevRRect = rrect; | 361 fPrevRRect = rrect; |
| 361 } | 362 } |
| 362 } | 363 } |
| 363 | 364 |
| 364 //////////////////////////////////////////////////////////////////////////////// //////////////////// | 365 //////////////////////////////////////////////////////////////////////////////// //////////////////// |
| 365 | 366 |
| 366 void CircularRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, | 367 void CircularRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, |
| 367 GrProcessorKeyBuilder* b) const { | 368 GrProcessorKeyBuilder* b) const { |
| 368 GLCircularRRectEffect::GenKey(*this, caps, b); | 369 GLCircularRRectEffect::GenKey(*this, caps, b); |
| 369 } | 370 } |
| 370 | 371 |
| 371 GrGLFragmentProcessor* CircularRRectEffect::onCreateGLInstance() const { | 372 GrGLFragmentProcessor* CircularRRectEffect::onCreateGLInstance() const { |
| 372 return new GLCircularRRectEffect(*this); | 373 return new GLCircularRRectEffect(*this); |
| 373 } | 374 } |
| 374 | 375 |
| 375 ////////////////////////////////////////////////////////////////////////////// | 376 ////////////////////////////////////////////////////////////////////////////// |
| 376 | 377 |
| 377 class EllipticalRRectEffect : public GrFragmentProcessor { | 378 class EllipticalRRectEffect : public GrFragmentProcessor { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 }; | 491 }; |
| 491 | 492 |
| 492 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { | 493 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { |
| 493 fPrevRRect.setEmpty(); | 494 fPrevRRect.setEmpty(); |
| 494 } | 495 } |
| 495 | 496 |
| 496 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { | 497 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { |
| 497 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); | 498 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); |
| 498 const char *rectName; | 499 const char *rectName; |
| 499 // The inner rect is the rrect bounds inset by the x/y radii | 500 // The inner rect is the rrect bounds inset by the x/y radii |
| 500 fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_ Visibility, | 501 fInnerRectUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragmen t_Visibility, |
| 501 kVec4f_GrSLType, kDefault_GrSLPrecis ion, | 502 kVec4f_GrSLType, kDefault_GrSLPrecis ion, |
| 502 "innerRect", | 503 "innerRect", |
| 503 &rectName); | 504 &rectName); |
| 504 | 505 |
| 505 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); | 506 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder() ; |
| 506 const char* fragmentPos = fsBuilder->fragmentPosition(); | 507 const char* fragmentPos = fsBuilder->fragmentPosition(); |
| 507 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos | 508 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos |
| 508 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant | 509 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant |
| 509 // to that corner. This means that points near the interior near the rrect t op edge will have | 510 // to that corner. This means that points near the interior near the rrect t op edge will have |
| 510 // a vector that points straight up for both the TL left and TR corners. Com puting an | 511 // a vector that points straight up for both the TL left and TR corners. Com puting an |
| 511 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, | 512 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, |
| 512 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | 513 // fragments near the other three edges will get the correct AA. Fragments i n the interior of |
| 513 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will | 514 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will |
| 514 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | 515 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. |
| 515 // | 516 // |
| 516 // The code below is a simplified version of the above that performs maxs on the vector | 517 // The code below is a simplified version of the above that performs maxs on the vector |
| 517 // components before computing distances and alpha values so that only one d istance computation | 518 // components before computing distances and alpha values so that only one d istance computation |
| 518 // need be computed to determine the min alpha. | 519 // need be computed to determine the min alpha. |
| 519 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); | 520 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); |
| 520 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); | 521 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); |
| 521 // The uniforms with the inv squared radii are highp to prevent underflow. | 522 // The uniforms with the inv squared radii are highp to prevent underflow. |
| 522 switch (erre.getRRect().getType()) { | 523 switch (erre.getRRect().getType()) { |
| 523 case SkRRect::kSimple_Type: { | 524 case SkRRect::kSimple_Type: { |
| 524 const char *invRadiiXYSqdName; | 525 const char *invRadiiXYSqdName; |
| 525 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder:: kFragment_Visibility, | 526 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder ::kFragment_Visibility, |
|
joshualitt
2015/11/11 20:49:18
\n
egdaniel
2015/11/11 20:52:43
Done.
| |
| 526 kVec2f_GrSLType, kHigh_GrS LPrecision, | 527 kVec2f_GrSLType, kHigh_GrS LPrecision, |
| 527 "invRadiiXY", | 528 "invRadiiXY", |
| 528 &invRadiiXYSqdName); | 529 &invRadiiXYSqdName); |
| 529 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; | 530 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; |
| 530 // Z is the x/y offsets divided by squared radii. | 531 // Z is the x/y offsets divided by squared radii. |
| 531 fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName ); | 532 fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName ); |
| 532 break; | 533 break; |
| 533 } | 534 } |
| 534 case SkRRect::kNinePatch_Type: { | 535 case SkRRect::kNinePatch_Type: { |
| 535 const char *invRadiiLTRBSqdName; | 536 const char *invRadiiLTRBSqdName; |
| 536 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder:: kFragment_Visibility, | 537 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder ::kFragment_Visibility, |
|
joshualitt
2015/11/11 20:49:18
\n
egdaniel
2015/11/11 20:52:43
Done.
| |
| 537 kVec4f_GrSLType, kHigh_GrS LPrecision, | 538 kVec4f_GrSLType, kHigh_GrS LPrecision, |
| 538 "invRadiiLTRB", | 539 "invRadiiLTRB", |
| 539 &invRadiiLTRBSqdName); | 540 &invRadiiLTRBSqdName); |
| 540 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; | 541 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; |
| 541 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one | 542 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one |
| 542 // corner where both the x and y offsets are positive, hence the max es. (The inverse | 543 // corner where both the x and y offsets are positive, hence the max es. (The inverse |
| 543 // squared radii will always be positive.) | 544 // squared radii will always be positive.) |
| 544 fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s .zw), 0.0);\n", | 545 fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s .zw), 0.0);\n", |
| 545 invRadiiLTRBSqdName, invRadiiLTRBSqdName); | 546 invRadiiLTRBSqdName, invRadiiLTRBSqdName); |
| 546 break; | 547 break; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 SkFAIL("RRect should always be simple or nine-patch."); | 607 SkFAIL("RRect should always be simple or nine-patch."); |
| 607 } | 608 } |
| 608 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); | 609 pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect. fBottom); |
| 609 fPrevRRect = rrect; | 610 fPrevRRect = rrect; |
| 610 } | 611 } |
| 611 } | 612 } |
| 612 | 613 |
| 613 //////////////////////////////////////////////////////////////////////////////// //////////////////// | 614 //////////////////////////////////////////////////////////////////////////////// //////////////////// |
| 614 | 615 |
| 615 void EllipticalRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, | 616 void EllipticalRRectEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, |
| 616 GrProcessorKeyBuilder* b) const { | 617 GrProcessorKeyBuilder* b) const { |
| 617 GLEllipticalRRectEffect::GenKey(*this, caps, b); | 618 GLEllipticalRRectEffect::GenKey(*this, caps, b); |
| 618 } | 619 } |
| 619 | 620 |
| 620 GrGLFragmentProcessor* EllipticalRRectEffect::onCreateGLInstance() const { | 621 GrGLFragmentProcessor* EllipticalRRectEffect::onCreateGLInstance() const { |
| 621 return new GLEllipticalRRectEffect(*this); | 622 return new GLEllipticalRRectEffect(*this); |
| 622 } | 623 } |
| 623 | 624 |
| 624 ////////////////////////////////////////////////////////////////////////////// | 625 ////////////////////////////////////////////////////////////////////////////// |
| 625 | 626 |
| 626 GrFragmentProcessor* GrRRectEffect::Create(GrPrimitiveEdgeType edgeType, const S kRRect& rrect) { | 627 GrFragmentProcessor* GrRRectEffect::Create(GrPrimitiveEdgeType edgeType, const S kRRect& rrect) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 if (rrect.isNinePatch()) { | 713 if (rrect.isNinePatch()) { |
| 713 return EllipticalRRectEffect::Create(edgeType, rrect); | 714 return EllipticalRRectEffect::Create(edgeType, rrect); |
| 714 } | 715 } |
| 715 return nullptr; | 716 return nullptr; |
| 716 } | 717 } |
| 717 } | 718 } |
| 718 } | 719 } |
| 719 | 720 |
| 720 return nullptr; | 721 return nullptr; |
| 721 } | 722 } |
| OLD | NEW |