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 "SkTLazy.h" |
15 #include "glsl/GrGLSLFragmentProcessor.h" | 16 #include "glsl/GrGLSLFragmentProcessor.h" |
16 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 17 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
17 #include "glsl/GrGLSLProgramBuilder.h" | |
18 #include "glsl/GrGLSLProgramDataManager.h" | 18 #include "glsl/GrGLSLProgramDataManager.h" |
| 19 #include "glsl/GrGLSLUniformHandler.h" |
19 | 20 |
20 // The effects defined here only handle rrect radii >= kRadiusMin. | 21 // The effects defined here only handle rrect radii >= kRadiusMin. |
21 static const SkScalar kRadiusMin = SK_ScalarHalf; | 22 static const SkScalar kRadiusMin = SK_ScalarHalf; |
22 | 23 |
23 ////////////////////////////////////////////////////////////////////////////// | 24 ////////////////////////////////////////////////////////////////////////////// |
24 | 25 |
25 class CircularRRectEffect : public GrFragmentProcessor { | 26 class CircularRRectEffect : public GrFragmentProcessor { |
26 public: | 27 public: |
27 | 28 |
28 enum CornerFlags { | 29 enum CornerFlags { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 SkRRect fPrevRRect; | 144 SkRRect fPrevRRect; |
144 typedef GrGLSLFragmentProcessor INHERITED; | 145 typedef GrGLSLFragmentProcessor INHERITED; |
145 }; | 146 }; |
146 | 147 |
147 GLCircularRRectEffect::GLCircularRRectEffect(const GrProcessor& ) { | 148 GLCircularRRectEffect::GLCircularRRectEffect(const GrProcessor& ) { |
148 fPrevRRect.setEmpty(); | 149 fPrevRRect.setEmpty(); |
149 } | 150 } |
150 | 151 |
151 void GLCircularRRectEffect::emitCode(EmitArgs& args) { | 152 void GLCircularRRectEffect::emitCode(EmitArgs& args) { |
152 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>(); | 153 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>(); |
| 154 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
153 const char *rectName; | 155 const char *rectName; |
154 const char *radiusPlusHalfName; | 156 const char *radiusPlusHalfName; |
155 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri
ght, and bottom | 157 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri
ght, and bottom |
156 // edges correspond to components x, y, z, and w, respectively. When a side
of the rrect has | 158 // edges correspond to components x, y, z, and w, respectively. When a side
of the rrect has |
157 // only rectangular corners, that side's value corresponds to the rect edge'
s value outset by | 159 // only rectangular corners, that side's value corresponds to the rect edge'
s value outset by |
158 // half a pixel. | 160 // half a pixel. |
159 fInnerRectUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragmen
t_Visibility, | 161 fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme
nt_Visibility, |
160 kVec4f_GrSLType, kDefault_GrSL
Precision, | 162 kVec4f_GrSLType, kDefault_GrS
LPrecision, |
161 "innerRect", | 163 "innerRect", |
162 &rectName); | 164 &rectName); |
163 fRadiusPlusHalfUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFr
agment_Visibility, | 165 fRadiusPlusHalfUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kF
ragment_Visibility, |
164 kFloat_GrSLType, kDefault
_GrSLPrecision, | 166 kFloat_GrSLType, kDefaul
t_GrSLPrecision, |
165 "radiusPlusHalf", | 167 "radiusPlusHalf", |
166 &radiusPlusHalfName); | 168 &radiusPlusHalfName); |
167 | 169 |
168 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | 170 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
169 const char* fragmentPos = fragBuilder->fragmentPosition(); | 171 const char* fragmentPos = fragBuilder->fragmentPosition(); |
170 // At each quarter-circle corner we compute a vector that is the offset of t
he fragment position | 172 // At each quarter-circle corner we compute a vector that is the offset of t
he fragment position |
171 // from the circle center. The vector is pinned in x and y to be in the quar
ter-plane relevant | 173 // from the circle center. The vector is pinned in x and y to be in the quar
ter-plane relevant |
172 // to that corner. This means that points near the interior near the rrect t
op edge will have | 174 // to that corner. This means that points near the interior near the rrect t
op edge will have |
173 // a vector that points straight up for both the TL left and TR corners. Com
puting an | 175 // a vector that points straight up for both the TL left and TR corners. Com
puting an |
174 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, | 176 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, |
175 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of | 177 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of |
176 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will | 178 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 SkRRect fPrevRRect; | 499 SkRRect fPrevRRect; |
498 typedef GrGLSLFragmentProcessor INHERITED; | 500 typedef GrGLSLFragmentProcessor INHERITED; |
499 }; | 501 }; |
500 | 502 |
501 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { | 503 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { |
502 fPrevRRect.setEmpty(); | 504 fPrevRRect.setEmpty(); |
503 } | 505 } |
504 | 506 |
505 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { | 507 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { |
506 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); | 508 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>(); |
| 509 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
507 const char *rectName; | 510 const char *rectName; |
508 // The inner rect is the rrect bounds inset by the x/y radii | 511 // The inner rect is the rrect bounds inset by the x/y radii |
509 fInnerRectUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragmen
t_Visibility, | 512 fInnerRectUniform = uniformHandler->addUniform(GrGLSLUniformHandler::kFragme
nt_Visibility, |
510 kVec4f_GrSLType, kDefault_GrSLPrecis
ion, | 513 kVec4f_GrSLType, kDefault_GrS
LPrecision, |
511 "innerRect", | 514 "innerRect", |
512 &rectName); | 515 &rectName); |
513 | 516 |
514 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | 517 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
515 const char* fragmentPos = fragBuilder->fragmentPosition(); | 518 const char* fragmentPos = fragBuilder->fragmentPosition(); |
516 // At each quarter-ellipse corner we compute a vector that is the offset of
the fragment pos | 519 // At each quarter-ellipse corner we compute a vector that is the offset of
the fragment pos |
517 // to the ellipse center. The vector is pinned in x and y to be in the quart
er-plane relevant | 520 // to the ellipse center. The vector is pinned in x and y to be in the quart
er-plane relevant |
518 // to that corner. This means that points near the interior near the rrect t
op edge will have | 521 // to that corner. This means that points near the interior near the rrect t
op edge will have |
519 // a vector that points straight up for both the TL left and TR corners. Com
puting an | 522 // a vector that points straight up for both the TL left and TR corners. Com
puting an |
520 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, | 523 // alpha from this vector at either the TR or TL corner will give the correc
t result. Similarly, |
521 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of | 524 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of |
522 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dii > 0.5 they will | 525 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dii > 0.5 they will |
523 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. | 526 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. |
524 // | 527 // |
525 // The code below is a simplified version of the above that performs maxs on
the vector | 528 // The code below is a simplified version of the above that performs maxs on
the vector |
526 // components before computing distances and alpha values so that only one d
istance computation | 529 // components before computing distances and alpha values so that only one d
istance computation |
527 // need be computed to determine the min alpha. | 530 // need be computed to determine the min alpha. |
528 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragm
entPos); | 531 fragBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragm
entPos); |
529 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, re
ctName); | 532 fragBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, re
ctName); |
530 // The uniforms with the inv squared radii are highp to prevent underflow. | 533 // The uniforms with the inv squared radii are highp to prevent underflow. |
531 switch (erre.getRRect().getType()) { | 534 switch (erre.getRRect().getType()) { |
532 case SkRRect::kSimple_Type: { | 535 case SkRRect::kSimple_Type: { |
533 const char *invRadiiXYSqdName; | 536 const char *invRadiiXYSqdName; |
534 fInvRadiiSqdUniform = args.fBuilder->addUniform( | 537 fInvRadiiSqdUniform = uniformHandler->addUniform( |
535 GrGLSLProgramBuilder::k
Fragment_Visibility, | 538 GrGLSLUniformHandler::k
Fragment_Visibility, |
536 kVec2f_GrSLType, kHigh_
GrSLPrecision, | 539 kVec2f_GrSLType, kHigh_
GrSLPrecision, |
537 "invRadiiXY", | 540 "invRadiiXY", |
538 &invRadiiXYSqdName); | 541 &invRadiiXYSqdName); |
539 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n
"); | 542 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n
"); |
540 // Z is the x/y offsets divided by squared radii. | 543 // Z is the x/y offsets divided by squared radii. |
541 fragBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdNa
me); | 544 fragBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdNa
me); |
542 break; | 545 break; |
543 } | 546 } |
544 case SkRRect::kNinePatch_Type: { | 547 case SkRRect::kNinePatch_Type: { |
545 const char *invRadiiLTRBSqdName; | 548 const char *invRadiiLTRBSqdName; |
546 fInvRadiiSqdUniform = args.fBuilder->addUniform( | 549 fInvRadiiSqdUniform = uniformHandler->addUniform( |
547 GrGLSLProgramBuilder::k
Fragment_Visibility, | 550 GrGLSLUniformHandler::k
Fragment_Visibility, |
548 kVec4f_GrSLType, kHigh_
GrSLPrecision, | 551 kVec4f_GrSLType, kHigh_
GrSLPrecision, |
549 "invRadiiLTRB", | 552 "invRadiiLTRB", |
550 &invRadiiLTRBSqdName); | 553 &invRadiiLTRBSqdName); |
551 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n
"); | 554 fragBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n
"); |
552 // Z is the x/y offsets divided by squared radii. We only care about
the (at most) one | 555 // Z is the x/y offsets divided by squared radii. We only care about
the (at most) one |
553 // corner where both the x and y offsets are positive, hence the max
es. (The inverse | 556 // corner where both the x and y offsets are positive, hence the max
es. (The inverse |
554 // squared radii will always be positive.) | 557 // squared radii will always be positive.) |
555 fragBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 *
%s.zw), 0.0);\n", | 558 fragBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 *
%s.zw), 0.0);\n", |
556 invRadiiLTRBSqdName, invRadiiLTRBSqdName); | 559 invRadiiLTRBSqdName, invRadiiLTRBSqdName); |
557 break; | 560 break; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 if (rrect.isNinePatch()) { | 726 if (rrect.isNinePatch()) { |
724 return EllipticalRRectEffect::Create(edgeType, rrect); | 727 return EllipticalRRectEffect::Create(edgeType, rrect); |
725 } | 728 } |
726 return nullptr; | 729 return nullptr; |
727 } | 730 } |
728 } | 731 } |
729 } | 732 } |
730 | 733 |
731 return nullptr; | 734 return nullptr; |
732 } | 735 } |
OLD | NEW |