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

Side by Side Diff: src/effects/SkBlurMaskFilter.cpp

Issue 341543005: Fifth attempt to land faster rect blur. Remove unnecessary conditionals from the shader. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 6 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 | « expectations/gm/ignored-tests.txt ('k') | src/gpu/gl/GrGLShaderBuilder.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 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
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 "SkBlurMaskFilter.h" 9 #include "SkBlurMaskFilter.h"
10 #include "SkBlurMask.h" 10 #include "SkBlurMask.h"
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 typedef GrGLRectBlurEffect GLEffect; 550 typedef GrGLRectBlurEffect GLEffect;
551 551
552 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 552 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
553 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; 553 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
554 554
555 /** 555 /**
556 * Create a simple filter effect with custom bicubic coefficients. 556 * Create a simple filter effect with custom bicubic coefficients.
557 */ 557 */
558 static GrEffectRef* Create(GrContext *context, const SkRect& rect, 558 static GrEffectRef* Create(GrContext *context, const SkRect& rect,
559 float sigma) { 559 float sigma) {
560 GrTexture *horizontalScanline = NULL, *verticalScanline = NULL; 560 GrTexture *blurProfileTexture = NULL;
561 bool createdScanlines = CreateScanlineTextures(context, sigma, 561 int doubleProfileSize = SkScalarCeilToInt(12*sigma);
562 SkScalarCeilToInt(rect.wi dth()), 562
563 SkScalarCeilToInt(rect.he ight()), 563 if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.heigh t()) {
564 &horizontalScanline, &ver ticalScanline); 564 // if the blur sigma is too large so the gaussian overlaps the whole
565 SkAutoTUnref<GrTexture> hunref(horizontalScanline), vunref(verticalScan line); 565 // rect in either direction, fall back to CPU path for now.
566 if (!createdScanlines) { 566
567 return NULL; 567 return NULL;
568 } 568 }
569 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, 569
570 horizontalScanline, verticalScanline))); 570 bool createdBlurProfileTexture = CreateBlurProfileTexture(context, sigma , &blurProfileTexture);
571 SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
572 if (!createdBlurProfileTexture) {
573 return NULL;
574 }
575 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, blurPr ofileTexture)));
571 return CreateEffectRef(effect); 576 return CreateEffectRef(effect);
572 } 577 }
573 578
574 unsigned int getWidth() const { return fWidth; } 579 const SkRect& getRect() const { return fRect; }
575 unsigned int getHeight() const { return fHeight; }
576 float getSigma() const { return fSigma; } 580 float getSigma() const { return fSigma; }
577 const GrCoordTransform& getTransform() const { return fTransform; }
578 581
579 private: 582 private:
580 GrRectBlurEffect(const SkRect& rect, float sigma, 583 GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile);
581 GrTexture *horizontal_scanline, GrTexture *vertical_scanlin e);
582 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 584 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
583 585
584 static bool CreateScanlineTextures(GrContext *context, float sigma, 586 static bool CreateBlurProfileTexture(GrContext *context, float sigma,
585 unsigned int width, unsigned int height, 587 GrTexture **blurProfileTexture);
586 GrTexture **horizontalScanline,
587 GrTexture **verticalScanline);
588 588
589 unsigned int fWidth, fHeight; 589 SkRect fRect;
590 float fSigma; 590 float fSigma;
591 GrTextureAccess fHorizontalScanlineAccess; 591 GrTextureAccess fBlurProfileAccess;
592 GrTextureAccess fVerticalScanlineAccess;
593 GrCoordTransform fTransform;
594 592
595 GR_DECLARE_EFFECT_TEST; 593 GR_DECLARE_EFFECT_TEST;
596 594
597 typedef GrEffect INHERITED; 595 typedef GrEffect INHERITED;
598 }; 596 };
599 597
600 class GrGLRectBlurEffect : public GrGLEffect { 598 class GrGLRectBlurEffect : public GrGLEffect {
601 public: 599 public:
602 GrGLRectBlurEffect(const GrBackendEffectFactory& factory, 600 GrGLRectBlurEffect(const GrBackendEffectFactory& factory,
603 const GrDrawEffect&); 601 const GrDrawEffect&);
604 virtual void emitCode(GrGLShaderBuilder*, 602 virtual void emitCode(GrGLShaderBuilder*,
605 const GrDrawEffect&, 603 const GrDrawEffect&,
606 EffectKey, 604 EffectKey,
607 const char* outputColor, 605 const char* outputColor,
608 const char* inputColor, 606 const char* inputColor,
609 const TransformedCoordsArray&, 607 const TransformedCoordsArray&,
610 const TextureSamplerArray&) SK_OVERRIDE; 608 const TextureSamplerArray&) SK_OVERRIDE;
611 609
612 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; 610 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
613 611
614 private: 612 private:
615 typedef GrGLUniformManager::UniformHandle UniformHandle; 613 typedef GrGLUniformManager::UniformHandle UniformHandle;
616 614
617 UniformHandle fWidthUni; 615 UniformHandle fProxyRectUniform;
618 UniformHandle fHeightUni; 616 UniformHandle fProfileSizeUniform;
619 617
620 typedef GrGLEffect INHERITED; 618 typedef GrGLEffect INHERITED;
621 }; 619 };
622 620
621
622
623 GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, co nst GrDrawEffect&) 623 GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, co nst GrDrawEffect&)
624 : INHERITED(factory) { 624 : INHERITED(factory) {
625 } 625 }
626 626
627 void OutputRectBlurProfileLookup(GrGLShaderBuilder* builder,
628 const GrGLShaderBuilder::TextureSampler& sample r,
629 const char *output,
630 const char *profileSize, const char *loc,
631 const char *blurred_width,
632 const char *sharp_width) {
633 builder->fsCodeAppendf("\tfloat %s;\n", output);
634 builder->fsCodeAppendf("\t\t{\n");
635 builder->fsCodeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/ %s;\n",
636 loc, blurred_width, sharp_width, profileSize);
637 builder->fsCodeAppendf("\t\t\t%s = ", output);
638 builder->fsAppendTextureLookup(sampler, "vec2(coord,0.5)");
639 builder->fsCodeAppend(".a;\n");
640 builder->fsCodeAppendf("\t\t}\n");
641 }
642
627 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, 643 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
628 const GrDrawEffect&, 644 const GrDrawEffect&,
629 EffectKey key, 645 EffectKey key,
630 const char* outputColor, 646 const char* outputColor,
631 const char* inputColor, 647 const char* inputColor,
632 const TransformedCoordsArray& coords, 648 const TransformedCoordsArray& coords,
633 const TextureSamplerArray& samplers) { 649 const TextureSamplerArray& samplers) {
634 650
635 SkString texture_coords = builder->ensureFSCoords2D(coords, 0); 651 const char *rectName;
652 const char *profileSizeName;
653
654 fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
655 kVec4f_GrSLType,
656 "proxyRect",
657 &rectName);
658 fProfileSizeUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility,
659 kFloat_GrSLType,
660 "profileSize",
661 &profileSizeName);
662
663 const char *fragmentPos = builder->fragmentPosition();
636 664
637 if (inputColor) { 665 if (inputColor) {
638 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor); 666 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor);
639 } else { 667 } else {
640 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;"); 668 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;");
641 } 669 }
642 670
643 builder->fsCodeAppendf("\tvec4 horiz = "); 671 builder->fsCodeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPo s, rectName );
644 builder->fsAppendTextureLookup( samplers[0], texture_coords.c_str() ); 672 builder->fsCodeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName) ;
645 builder->fsCodeAppendf(";\n"); 673 builder->fsCodeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName );
646 builder->fsCodeAppendf("\tvec4 vert = ");
647 builder->fsAppendTextureLookup( samplers[1], texture_coords.c_str() );
648 builder->fsCodeAppendf(";\n");
649 674
650 builder->fsCodeAppendf("\tfloat final = (horiz*vert).r;\n"); 675 builder->fsCodeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName);
651 builder->fsCodeAppendf("\t%s = final*src;\n", outputColor); 676 builder->fsCodeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n" , profileSizeName);
677 builder->fsCodeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
678
679 OutputRectBlurProfileLookup(builder, samplers[0], "horiz_lookup", profileSiz eName, "translatedPos.x", "width", "wh.x");
680 OutputRectBlurProfileLookup(builder, samplers[0], "vert_lookup", profileSize Name, "translatedPos.y", "height", "wh.y");
681
682 builder->fsCodeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n");
683 builder->fsCodeAppendf("\t%s = src * vec4(final);\n", outputColor );
652 } 684 }
653 685
654 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, 686 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman,
655 const GrDrawEffect& drawEffect) { 687 const GrDrawEffect& drawEffect) {
688 const GrRectBlurEffect& rbe = drawEffect.castEffect<GrRectBlurEffect>();
689 SkRect rect = rbe.getRect();
690
691 uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBott om);
692 uman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
656 } 693 }
657 694
658 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma, 695 bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
659 unsigned int width, unsigned int h eight, 696 GrTexture **blurProfileTexture) {
660 GrTexture **horizontalScanline,
661 GrTexture **verticalScanline) {
662 GrTextureParams params; 697 GrTextureParams params;
663 GrTextureDesc texDesc; 698 GrTextureDesc texDesc;
664 699
665 unsigned int profile_size = SkScalarFloorToInt(6*sigma); 700 unsigned int profile_size = SkScalarCeilToInt(6*sigma);
666 701
667 texDesc.fWidth = width; 702 texDesc.fWidth = profile_size;
668 texDesc.fHeight = 1; 703 texDesc.fHeight = 1;
669 texDesc.fConfig = kAlpha_8_GrPixelConfig; 704 texDesc.fConfig = kAlpha_8_GrPixelConfig;
670 705
671 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n(); 706 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n();
672 GrCacheID::Key key; 707 GrCacheID::Key key;
673 memset(&key, 0, sizeof(key)); 708 memset(&key, 0, sizeof(key));
674 key.fData32[0] = profile_size; 709 key.fData32[0] = profile_size;
675 key.fData32[1] = width; 710 key.fData32[1] = 1;
676 key.fData32[2] = 1; 711 GrCacheID blurProfileKey(gBlurProfileDomain, key);
677 GrCacheID horizontalCacheID(gBlurProfileDomain, key);
678 712
679 uint8_t *profile = NULL; 713 uint8_t *profile = NULL;
680 SkAutoTDeleteArray<uint8_t> ada(NULL); 714 SkAutoTDeleteArray<uint8_t> ada(NULL);
681 715
682 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID, &params); 716 *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &p arams);
683 717
684 if (NULL == *horizontalScanline) { 718 if (NULL == *blurProfileTexture) {
685 719
686 SkBlurMask::ComputeBlurProfile(sigma, &profile); 720 SkBlurMask::ComputeBlurProfile(sigma, &profile);
687 ada.reset(profile); 721 ada.reset(profile);
688 722
689 SkAutoTMalloc<uint8_t> horizontalPixels(width); 723 *blurProfileTexture = context->createTexture(&params, texDesc, blurProfi leKey,
690 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, width, sig ma); 724 profile, 0);
691 725
692 *horizontalScanline = context->createTexture(&params, texDesc, horizonta lCacheID, 726 if (NULL == *blurProfileTexture) {
693 horizontalPixels, 0);
694
695 if (NULL == *horizontalScanline) {
696 return false; 727 return false;
697 } 728 }
698 } 729 }
699 730
700 texDesc.fWidth = 1;
701 texDesc.fHeight = height;
702 key.fData32[1] = 1;
703 key.fData32[2] = height;
704 GrCacheID verticalCacheID(gBlurProfileDomain, key);
705
706 *verticalScanline = context->findAndRefTexture(texDesc, verticalCacheID, &pa rams);
707 if (NULL == *verticalScanline) {
708 if (NULL == profile) {
709 SkBlurMask::ComputeBlurProfile(sigma, &profile);
710 ada.reset(profile);
711 }
712
713 SkAutoTMalloc<uint8_t> verticalPixels(height);
714 SkBlurMask::ComputeBlurredScanline(verticalPixels, profile, height, sigm a);
715
716 *verticalScanline = context->createTexture(&params, texDesc, verticalCac heID,
717 verticalPixels, 0);
718
719 if (NULL == *verticalScanline) {
720 SkSafeSetNull(*horizontalScanline);
721 return false;
722 }
723
724 }
725 return true; 731 return true;
726 } 732 }
727 733
728 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, 734 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
729 GrTexture *horizontal_scanline, GrTexture *ve rtical_scanline) 735 GrTexture *blur_profile)
730 : INHERITED(), 736 : INHERITED(),
731 fWidth(horizontal_scanline->width()), 737 fRect(rect),
732 fHeight(vertical_scanline->width()),
733 fSigma(sigma), 738 fSigma(sigma),
734 fHorizontalScanlineAccess(horizontal_scanline), 739 fBlurProfileAccess(blur_profile) {
735 fVerticalScanlineAccess(vertical_scanline) { 740 this->addTextureAccess(&fBlurProfileAccess);
736 SkMatrix mat; 741 this->setWillReadFragmentPosition();
737 mat.setRectToRect(rect, SkRect::MakeWH(1,1), SkMatrix::kFill_ScaleToFit);
738 fTransform.reset(kLocal_GrCoordSet, mat);
739 this->addTextureAccess(&fHorizontalScanlineAccess);
740 this->addTextureAccess(&fVerticalScanlineAccess);
741 this->addCoordTransform(&fTransform);
742 } 742 }
743 743
744 GrRectBlurEffect::~GrRectBlurEffect() { 744 GrRectBlurEffect::~GrRectBlurEffect() {
745 } 745 }
746 746
747 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { 747 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const {
748 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); 748 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance();
749 } 749 }
750 750
751 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { 751 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const {
752 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); 752 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase);
753 return this->getWidth() == s.getWidth() && 753 return this->getSigma() == s.getSigma() && this->getRect() == s.getRect();
754 this->getHeight() == s.getHeight() &&
755 this->getSigma() == s.getSigma() &&
756 this->getTransform() == s.getTransform();
757 } 754 }
758 755
759 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { 756 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const {
760 *validFlags = 0; 757 *validFlags = 0;
761 return; 758 return;
762 } 759 }
763 760
764 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); 761 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect);
765 762
766 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, 763 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random,
(...skipping 19 matching lines...) Expand all
786 if (!path.isRect(&rect)) { 783 if (!path.isRect(&rect)) {
787 return false; 784 return false;
788 } 785 }
789 786
790 if (!strokeRec.isFillStyle()) { 787 if (!strokeRec.isFillStyle()) {
791 return false; 788 return false;
792 } 789 }
793 790
794 SkMatrix ctm = context->getMatrix(); 791 SkMatrix ctm = context->getMatrix();
795 SkScalar xformedSigma = this->computeXformedSigma(ctm); 792 SkScalar xformedSigma = this->computeXformedSigma(ctm);
796 rect.outset(3*xformedSigma, 3*xformedSigma); 793
794 int pad=SkScalarCeilToInt(6*xformedSigma)/2;
795 rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
797 796
798 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( 797 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create(
799 context, rect, xformedSigma)); 798 context, rect, xformedSigma));
800 if (!effect) { 799 if (!effect) {
801 return false; 800 return false;
802 } 801 }
803 802
804 GrContext::AutoMatrix am; 803 GrContext::AutoMatrix am;
805 if (!am.setIdentity(context, grp)) { 804 if (!am.setIdentity(context, grp)) {
806 return false; 805 return false;
807 } 806 }
808 807
809
810 grp->addCoverageEffect(effect); 808 grp->addCoverageEffect(effect);
811 809
812 context->drawRect(*grp, rect); 810 context->drawRect(*grp, rect);
813 return true; 811 return true;
814 } 812 }
815 813
816 class GrGLRRectBlurEffect; 814 class GrGLRRectBlurEffect;
817 815
818 class GrRRectBlurEffect : public GrEffect { 816 class GrRRectBlurEffect : public GrEffect {
819 public: 817 public:
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 } else { 1207 } else {
1210 str->append("None"); 1208 str->append("None");
1211 } 1209 }
1212 str->append("))"); 1210 str->append("))");
1213 } 1211 }
1214 #endif 1212 #endif
1215 1213
1216 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1214 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1217 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1215 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1218 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1216 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | src/gpu/gl/GrGLShaderBuilder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698