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

Side by Side Diff: src/effects/gradients/SkTwoPointRadialGradient.cpp

Issue 25645006: Allow gradient optimization with perspective (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: updated skipped tests Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/effects/gradients/SkTwoPointConicalGradient.cpp ('k') | src/gpu/GrEffect.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 /* 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/effects/gradients/SkTwoPointConicalGradient.cpp ('k') | src/gpu/GrEffect.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698