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

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

Issue 316273004: Faster GPU rect blur that doesn't require computing vertical and horizontal (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: missed a GM to ignore 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') | no next file » | 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("\t\tfloat coord = (0.5 * (abs(2*%s - %s) - %s))/%s;\ n",
634 loc, blurred_width, sharp_width, profileSize);
635 builder->fsCodeAppendf("\t\t%s = ", output);
636 builder->fsAppendTextureLookup(sampler, "vec2(coord,0.5)");
637 builder->fsCodeAppend(";\n");
638 }
639
627 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, 640 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
628 const GrDrawEffect&, 641 const GrDrawEffect&,
629 EffectKey key, 642 EffectKey key,
630 const char* outputColor, 643 const char* outputColor,
631 const char* inputColor, 644 const char* inputColor,
632 const TransformedCoordsArray& coords, 645 const TransformedCoordsArray& coords,
633 const TextureSamplerArray& samplers) { 646 const TextureSamplerArray& samplers) {
634 647
635 SkString texture_coords = builder->ensureFSCoords2D(coords, 0); 648 const char *rectName;
649 const char *profileSizeName;
650
651 fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
652 kVec4f_GrSLType,
653 "proxyRect",
654 &rectName);
655 fProfileSizeUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visib ility,
656 kFloat_GrSLType,
657 "profileSize",
658 &profileSizeName);
659
660 const char *fragmentPos = builder->fragmentPosition();
636 661
637 if (inputColor) { 662 if (inputColor) {
638 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor); 663 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor);
639 } else { 664 } else {
640 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;"); 665 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;");
641 } 666 }
642 667
643 builder->fsCodeAppendf("\tvec4 horiz = "); 668 builder->fsCodeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPo s, rectName );
644 builder->fsAppendTextureLookup( samplers[0], texture_coords.c_str() ); 669 builder->fsCodeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName) ;
645 builder->fsCodeAppendf(";\n"); 670 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 671
650 builder->fsCodeAppendf("\tfloat final = (horiz*vert).r;\n"); 672 builder->fsCodeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName);
651 builder->fsCodeAppendf("\t%s = final*src;\n", outputColor); 673 builder->fsCodeAppendf("\tfloat center = 2.0 * floor(%s/2 + .25) - 1;\n", pr ofileSizeName);
674 builder->fsCodeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
675
676 builder->fsCodeAppendf("\tfloat horiz_lookup;\n");
677 builder->fsCodeAppendf("\tif (%s <= smallDims.x) {\n", profileSizeName);
678 OutputRectBlurProfileLookup(builder, samplers[0], "horiz_lookup", profileSiz eName, "translatedPos.x", "width", "wh.x");
679 builder->fsCodeAppendf("\t}\n");
680
681 builder->fsCodeAppendf("\tfloat vert_lookup;\n");
682 builder->fsCodeAppendf("\tif (%s <= smallDims.y) {\n", profileSizeName);
683 OutputRectBlurProfileLookup(builder, samplers[0], "vert_lookup", profileSize Name, "translatedPos.y", "height", "wh.y");
684 builder->fsCodeAppendf("\t}\n");
685
686 builder->fsCodeAppendf("\tfloat final = 1.0 - horiz_lookup * vert_lookup;\n" );
687
688 builder->fsCodeAppendf("\t%s = vec4(final, final, final, 1);\n", outputColor );
652 } 689 }
653 690
654 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, 691 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman,
655 const GrDrawEffect& drawEffect) { 692 const GrDrawEffect& drawEffect) {
693 const GrRectBlurEffect& rbe = drawEffect.castEffect<GrRectBlurEffect>();
694 SkRect rect = rbe.getRect();
695
696 uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBott om);
697 uman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
656 } 698 }
657 699
658 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma, 700 bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
659 unsigned int width, unsigned int h eight, 701 GrTexture **blurProfileTexture) {
660 GrTexture **horizontalScanline,
661 GrTexture **verticalScanline) {
662 GrTextureParams params; 702 GrTextureParams params;
663 GrTextureDesc texDesc; 703 GrTextureDesc texDesc;
664 704
665 unsigned int profile_size = SkScalarFloorToInt(6*sigma); 705 unsigned int profile_size = SkScalarCeilToInt(6*sigma);
666 706
667 texDesc.fWidth = width; 707 texDesc.fWidth = profile_size;
668 texDesc.fHeight = 1; 708 texDesc.fHeight = 1;
669 texDesc.fConfig = kAlpha_8_GrPixelConfig; 709 texDesc.fConfig = kAlpha_8_GrPixelConfig;
670 710
671 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n(); 711 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n();
672 GrCacheID::Key key; 712 GrCacheID::Key key;
673 memset(&key, 0, sizeof(key)); 713 memset(&key, 0, sizeof(key));
674 key.fData32[0] = profile_size; 714 key.fData32[0] = profile_size;
675 key.fData32[1] = width; 715 key.fData32[1] = 1;
676 key.fData32[2] = 1; 716 GrCacheID blurProfileKey(gBlurProfileDomain, key);
677 GrCacheID horizontalCacheID(gBlurProfileDomain, key);
678 717
679 uint8_t *profile = NULL; 718 uint8_t *profile = NULL;
680 SkAutoTDeleteArray<uint8_t> ada(NULL); 719 SkAutoTDeleteArray<uint8_t> ada(NULL);
681 720
682 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID, &params); 721 *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &p arams);
683 722
684 if (NULL == *horizontalScanline) { 723 if (NULL == *blurProfileTexture) {
685 724
686 SkBlurMask::ComputeBlurProfile(sigma, &profile); 725 SkBlurMask::ComputeBlurProfile(sigma, &profile);
687 ada.reset(profile); 726 ada.reset(profile);
688 727
689 SkAutoTMalloc<uint8_t> horizontalPixels(width); 728 *blurProfileTexture = context->createTexture(&params, texDesc, blurProfi leKey,
690 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, width, sig ma); 729 profile, 0);
691 730
692 *horizontalScanline = context->createTexture(&params, texDesc, horizonta lCacheID, 731 if (NULL == *blurProfileTexture) {
693 horizontalPixels, 0);
694
695 if (NULL == *horizontalScanline) {
696 return false; 732 return false;
697 } 733 }
698 } 734 }
699 735
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; 736 return true;
726 } 737 }
727 738
728 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, 739 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
729 GrTexture *horizontal_scanline, GrTexture *ve rtical_scanline) 740 GrTexture *blur_profile)
730 : INHERITED(), 741 : INHERITED(),
731 fWidth(horizontal_scanline->width()), 742 fRect(rect),
732 fHeight(vertical_scanline->width()),
733 fSigma(sigma), 743 fSigma(sigma),
734 fHorizontalScanlineAccess(horizontal_scanline), 744 fBlurProfileAccess(blur_profile) {
735 fVerticalScanlineAccess(vertical_scanline) { 745 this->addTextureAccess(&fBlurProfileAccess);
736 SkMatrix mat; 746 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 } 747 }
743 748
744 GrRectBlurEffect::~GrRectBlurEffect() { 749 GrRectBlurEffect::~GrRectBlurEffect() {
745 } 750 }
746 751
747 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { 752 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const {
748 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); 753 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance();
749 } 754 }
750 755
751 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { 756 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const {
752 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); 757 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase);
753 return this->getWidth() == s.getWidth() && 758 return this->getSigma() == s.getSigma();
754 this->getHeight() == s.getHeight() &&
755 this->getSigma() == s.getSigma() &&
756 this->getTransform() == s.getTransform();
757 } 759 }
758 760
759 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { 761 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const {
760 *validFlags = 0; 762 *validFlags = 0;
761 return; 763 return;
762 } 764 }
763 765
764 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); 766 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect);
765 767
766 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, 768 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random,
(...skipping 19 matching lines...) Expand all
786 if (!path.isRect(&rect)) { 788 if (!path.isRect(&rect)) {
787 return false; 789 return false;
788 } 790 }
789 791
790 if (!strokeRec.isFillStyle()) { 792 if (!strokeRec.isFillStyle()) {
791 return false; 793 return false;
792 } 794 }
793 795
794 SkMatrix ctm = context->getMatrix(); 796 SkMatrix ctm = context->getMatrix();
795 SkScalar xformedSigma = this->computeXformedSigma(ctm); 797 SkScalar xformedSigma = this->computeXformedSigma(ctm);
796 rect.outset(3*xformedSigma, 3*xformedSigma); 798
799 float pad=SkScalarCeilToScalar(6*xformedSigma)/2.0f;
800 rect.outset(pad, pad);
797 801
798 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( 802 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create(
799 context, rect, xformedSigma)); 803 context, rect, xformedSigma));
800 if (!effect) { 804 if (!effect) {
801 return false; 805 return false;
802 } 806 }
803 807
804 GrContext::AutoMatrix am; 808 GrContext::AutoMatrix am;
805 if (!am.setIdentity(context, grp)) { 809 if (!am.setIdentity(context, grp)) {
806 return false; 810 return false;
807 } 811 }
808 812
809
810 grp->addCoverageEffect(effect); 813 grp->addCoverageEffect(effect);
811 814
812 context->drawRect(*grp, rect); 815 context->drawRect(*grp, rect);
813 return true; 816 return true;
814 } 817 }
815 818
816 class GrGLRRectBlurEffect; 819 class GrGLRRectBlurEffect;
817 820
818 class GrRRectBlurEffect : public GrEffect { 821 class GrRRectBlurEffect : public GrEffect {
819 public: 822 public:
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 } else { 1212 } else {
1210 str->append("None"); 1213 str->append("None");
1211 } 1214 }
1212 str->append("))"); 1215 str->append("))");
1213 } 1216 }
1214 #endif 1217 #endif
1215 1218
1216 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1219 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1217 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1220 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1218 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1221 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698