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

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

Issue 1251173002: Added GrGLFragmentProcessor::EmitArgs struct for use with emitCode() (Closed) Base URL: https://skia.googlesource.com/skia@composeshader_gpu
Patch Set: Created 5 years, 5 months 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') | src/gpu/effects/GrSimpleTextureEffect.cpp » ('j') | 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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } while (NULL == fp); 121 } while (NULL == fp);
122 return fp; 122 return fp;
123 } 123 }
124 124
125 ////////////////////////////////////////////////////////////////////////////// 125 //////////////////////////////////////////////////////////////////////////////
126 126
127 class GLCircularRRectEffect : public GrGLFragmentProcessor { 127 class GLCircularRRectEffect : public GrGLFragmentProcessor {
128 public: 128 public:
129 GLCircularRRectEffect(const GrProcessor&); 129 GLCircularRRectEffect(const GrProcessor&);
130 130
131 virtual void emitCode(GrGLFPBuilder* builder, 131 virtual void emitCode(EmitArgs&) override;
132 const GrFragmentProcessor& fp,
133 const char* outputColor,
134 const char* inputColor,
135 const TransformedCoordsArray&,
136 const TextureSamplerArray&) override;
137 132
138 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*); 133 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
139 134
140 void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 135 void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
141 136
142 private: 137 private:
143 GrGLProgramDataManager::UniformHandle fInnerRectUniform; 138 GrGLProgramDataManager::UniformHandle fInnerRectUniform;
144 GrGLProgramDataManager::UniformHandle fRadiusPlusHalfUniform; 139 GrGLProgramDataManager::UniformHandle fRadiusPlusHalfUniform;
145 SkRRect fPrevRRect; 140 SkRRect fPrevRRect;
146 typedef GrGLFragmentProcessor INHERITED; 141 typedef GrGLFragmentProcessor INHERITED;
147 }; 142 };
148 143
149 GLCircularRRectEffect::GLCircularRRectEffect(const GrProcessor& ) { 144 GLCircularRRectEffect::GLCircularRRectEffect(const GrProcessor& ) {
150 fPrevRRect.setEmpty(); 145 fPrevRRect.setEmpty();
151 } 146 }
152 147
153 void GLCircularRRectEffect::emitCode(GrGLFPBuilder* builder, 148 void GLCircularRRectEffect::emitCode(EmitArgs& args) {
154 const GrFragmentProcessor& fp, 149 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>();
155 const char* outputColor,
156 const char* inputColor,
157 const TransformedCoordsArray&,
158 const TextureSamplerArray& samplers) {
159 const CircularRRectEffect& crre = fp.cast<CircularRRectEffect>();
160 const char *rectName; 150 const char *rectName;
161 const char *radiusPlusHalfName; 151 const char *radiusPlusHalfName;
162 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom 152 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom
163 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has 153 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
164 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by 154 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by
165 // half a pixel. 155 // half a pixel.
166 fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi lity, 156 fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_ Visibility,
167 kVec4f_GrSLType, kDefault_GrSLPrecis ion, 157 kVec4f_GrSLType, kDefault_GrSLPrecis ion,
168 "innerRect", 158 "innerRect",
169 &rectName); 159 &rectName);
170 fRadiusPlusHalfUniform = builder->addUniform(GrGLProgramBuilder::kFragment_V isibility, 160 fRadiusPlusHalfUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag ment_Visibility,
171 kFloat_GrSLType, kDefault_GrSLP recision, 161 kFloat_GrSLType, kDefault_GrSLP recision,
172 "radiusPlusHalf", 162 "radiusPlusHalf",
173 &radiusPlusHalfName); 163 &radiusPlusHalfName);
174 164
175 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 165 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
176 const char* fragmentPos = fsBuilder->fragmentPosition(); 166 const char* fragmentPos = fsBuilder->fragmentPosition();
177 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position 167 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position
178 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant 168 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant
179 // to that corner. This means that points near the interior near the rrect t op edge will have 169 // to that corner. This means that points near the interior near the rrect t op edge will have
180 // a vector that points straight up for both the TL left and TR corners. Com puting an 170 // a vector that points straight up for both the TL left and TR corners. Com puting an
181 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, 171 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly,
182 // fragments near the other three edges will get the correct AA. Fragments i n the interior of 172 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
183 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will 173 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will
184 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. 174 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
185 // The code below is a simplified version of the above that performs maxs on the vector 175 // The code below is a simplified version of the above that performs maxs on the vector
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 fragmentPos, rectName); 262 fragmentPos, rectName);
273 fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n", 263 fsBuilder->codeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n",
274 radiusPlusHalfName); 264 radiusPlusHalfName);
275 break; 265 break;
276 } 266 }
277 267
278 if (kInverseFillAA_GrProcessorEdgeType == crre.getEdgeType()) { 268 if (kInverseFillAA_GrProcessorEdgeType == crre.getEdgeType()) {
279 fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); 269 fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
280 } 270 }
281 271
282 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, 272 fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
283 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); 273 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha") ).c_str());
284 } 274 }
285 275
286 void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&, 276 void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&,
287 GrProcessorKeyBuilder* b) { 277 GrProcessorKeyBuilder* b) {
288 const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>(); 278 const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>();
289 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8); 279 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
290 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType()); 280 b->add32((crre.getCircularCornerFlags() << 3) | crre.getEdgeType());
291 } 281 }
292 282
293 void GLCircularRRectEffect::setData(const GrGLProgramDataManager& pdman, 283 void GLCircularRRectEffect::setData(const GrGLProgramDataManager& pdman,
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } while (NULL == fp); 466 } while (NULL == fp);
477 return fp; 467 return fp;
478 } 468 }
479 469
480 ////////////////////////////////////////////////////////////////////////////// 470 //////////////////////////////////////////////////////////////////////////////
481 471
482 class GLEllipticalRRectEffect : public GrGLFragmentProcessor { 472 class GLEllipticalRRectEffect : public GrGLFragmentProcessor {
483 public: 473 public:
484 GLEllipticalRRectEffect(const GrProcessor&); 474 GLEllipticalRRectEffect(const GrProcessor&);
485 475
486 virtual void emitCode(GrGLFPBuilder* builder, 476 virtual void emitCode(EmitArgs&) override;
487 const GrFragmentProcessor& effect,
488 const char* outputColor,
489 const char* inputColor,
490 const TransformedCoordsArray&,
491 const TextureSamplerArray&) override;
492 477
493 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*); 478 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
494 479
495 void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 480 void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
496 481
497 private: 482 private:
498 GrGLProgramDataManager::UniformHandle fInnerRectUniform; 483 GrGLProgramDataManager::UniformHandle fInnerRectUniform;
499 GrGLProgramDataManager::UniformHandle fInvRadiiSqdUniform; 484 GrGLProgramDataManager::UniformHandle fInvRadiiSqdUniform;
500 SkRRect fPrevRRect; 485 SkRRect fPrevRRect;
501 typedef GrGLFragmentProcessor INHERITED; 486 typedef GrGLFragmentProcessor INHERITED;
502 }; 487 };
503 488
504 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) { 489 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrProcessor& effect) {
505 fPrevRRect.setEmpty(); 490 fPrevRRect.setEmpty();
506 } 491 }
507 492
508 void GLEllipticalRRectEffect::emitCode(GrGLFPBuilder* builder, 493 void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
509 const GrFragmentProcessor& effect, 494 const EllipticalRRectEffect& erre = args.fFp.cast<EllipticalRRectEffect>();
510 const char* outputColor,
511 const char* inputColor,
512 const TransformedCoordsArray&,
513 const TextureSamplerArray& samplers) {
514 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
515 const char *rectName; 495 const char *rectName;
516 // The inner rect is the rrect bounds inset by the x/y radii 496 // The inner rect is the rrect bounds inset by the x/y radii
517 fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibi lity, 497 fInnerRectUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_ Visibility,
518 kVec4f_GrSLType, kDefault_GrSLPrecis ion, 498 kVec4f_GrSLType, kDefault_GrSLPrecis ion,
519 "innerRect", 499 "innerRect",
520 &rectName); 500 &rectName);
521 501
522 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 502 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
523 const char* fragmentPos = fsBuilder->fragmentPosition(); 503 const char* fragmentPos = fsBuilder->fragmentPosition();
524 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos 504 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
525 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant 505 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant
526 // to that corner. This means that points near the interior near the rrect t op edge will have 506 // to that corner. This means that points near the interior near the rrect t op edge will have
527 // a vector that points straight up for both the TL left and TR corners. Com puting an 507 // a vector that points straight up for both the TL left and TR corners. Com puting an
528 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, 508 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly,
529 // fragments near the other three edges will get the correct AA. Fragments i n the interior of 509 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
530 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will 510 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will
531 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. 511 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
532 // The code below is a simplified version of the above that performs maxs on the vector 512 // The code below is a simplified version of the above that performs maxs on the vector
533 // components before computing distances and alpha values so that only one d istance computation 513 // components before computing distances and alpha values so that only one d istance computation
534 // need be computed to determine the min alpha. 514 // need be computed to determine the min alpha.
535 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); 515 fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos);
536 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); 516 fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name);
537 switch (erre.getRRect().getType()) { 517 switch (erre.getRRect().getType()) {
538 case SkRRect::kSimple_Type: { 518 case SkRRect::kSimple_Type: {
539 const char *invRadiiXYSqdName; 519 const char *invRadiiXYSqdName;
540 fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragm ent_Visibility, 520 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder:: kFragment_Visibility,
541 kVec2f_GrSLType, kDefault_ GrSLPrecision, 521 kVec2f_GrSLType, kDefault_ GrSLPrecision,
542 "invRadiiXY", 522 "invRadiiXY",
543 &invRadiiXYSqdName); 523 &invRadiiXYSqdName);
544 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; 524 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ;
545 // Z is the x/y offsets divided by squared radii. 525 // Z is the x/y offsets divided by squared radii.
546 fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName ); 526 fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName );
547 break; 527 break;
548 } 528 }
549 case SkRRect::kNinePatch_Type: { 529 case SkRRect::kNinePatch_Type: {
550 const char *invRadiiLTRBSqdName; 530 const char *invRadiiLTRBSqdName;
551 fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragm ent_Visibility, 531 fInvRadiiSqdUniform = args.fBuilder->addUniform(GrGLProgramBuilder:: kFragment_Visibility,
552 kVec4f_GrSLType, kDefault_ GrSLPrecision, 532 kVec4f_GrSLType, kDefault_ GrSLPrecision,
553 "invRadiiLTRB", 533 "invRadiiLTRB",
554 &invRadiiLTRBSqdName); 534 &invRadiiLTRBSqdName);
555 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; 535 fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ;
556 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one 536 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
557 // corner where both the x and y offsets are positive, hence the max es. (The inverse 537 // corner where both the x and y offsets are positive, hence the max es. (The inverse
558 // squared radii will always be positive.) 538 // squared radii will always be positive.)
559 fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s .zw), 0.0);\n", 539 fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s .zw), 0.0);\n",
560 invRadiiLTRBSqdName, invRadiiLTRBSqdName); 540 invRadiiLTRBSqdName, invRadiiLTRBSqdName);
561 break; 541 break;
562 } 542 }
563 default: 543 default:
564 SkFAIL("RRect should always be simple or nine-patch."); 544 SkFAIL("RRect should always be simple or nine-patch.");
565 } 545 }
566 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. 546 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
567 fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); 547 fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
568 // grad_dot is the squared length of the gradient of the implicit. 548 // grad_dot is the squared length of the gradient of the implicit.
569 fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); 549 fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
570 // avoid calling inversesqrt on zero. 550 // avoid calling inversesqrt on zero.
571 fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); 551 fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
572 fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n"); 552 fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n");
573 553
574 if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) { 554 if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
575 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n"); 555 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n");
576 } else { 556 } else {
577 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n"); 557 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n");
578 } 558 }
579 559
580 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, 560 fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
581 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); 561 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha") ).c_str());
582 } 562 }
583 563
584 void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps &, 564 void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps &,
585 GrProcessorKeyBuilder* b) { 565 GrProcessorKeyBuilder* b) {
586 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>(); 566 const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
587 GR_STATIC_ASSERT(kLast_GrProcessorEdgeType < (1 << 3)); 567 GR_STATIC_ASSERT(kLast_GrProcessorEdgeType < (1 << 3));
588 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3); 568 b->add32(erre.getRRect().getType() | erre.getEdgeType() << 3);
589 } 569 }
590 570
591 void GLEllipticalRRectEffect::setData(const GrGLProgramDataManager& pdman, 571 void GLEllipticalRRectEffect::setData(const GrGLProgramDataManager& pdman,
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 if (rrect.isNinePatch()) { 707 if (rrect.isNinePatch()) {
728 return EllipticalRRectEffect::Create(edgeType, rrect); 708 return EllipticalRRectEffect::Create(edgeType, rrect);
729 } 709 }
730 return NULL; 710 return NULL;
731 } 711 }
732 } 712 }
733 } 713 }
734 714
735 return NULL; 715 return NULL;
736 } 716 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrOvalEffect.cpp ('k') | src/gpu/effects/GrSimpleTextureEffect.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698