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

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

Issue 333763002: Revert of third try at landing improved blur rect; this time with more correctness (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 *blurProfileTexture = NULL; 560 GrTexture *horizontalScanline = NULL, *verticalScanline = NULL;
561 int doubleProfileSize = SkScalarCeilToInt(12*sigma); 561 bool createdScanlines = CreateScanlineTextures(context, sigma,
562 562 SkScalarCeilToInt(rect.wi dth()),
563 if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.heigh t()) { 563 SkScalarCeilToInt(rect.he ight()),
564 // if the blur sigma is too large so the gaussian overlaps the whole 564 &horizontalScanline, &ver ticalScanline);
565 // rect in either direction, fall back to CPU path for now. 565 SkAutoTUnref<GrTexture> hunref(horizontalScanline), vunref(verticalScan line);
566 566 if (!createdScanlines) {
567 return NULL; 567 return NULL;
568 } 568 }
569 569 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma,
570 bool createdBlurProfileTexture = CreateBlurProfileTexture(context, sigma , &blurProfileTexture); 570 horizontalScanline, verticalScanline)));
571 SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
572 if (!createdBlurProfileTexture) {
573 return NULL;
574 }
575 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, blurPr ofileTexture)));
576 return CreateEffectRef(effect); 571 return CreateEffectRef(effect);
577 } 572 }
578 573
579 const SkRect& getRect() const { return fRect; } 574 unsigned int getWidth() const { return fWidth; }
575 unsigned int getHeight() const { return fHeight; }
580 float getSigma() const { return fSigma; } 576 float getSigma() const { return fSigma; }
577 const GrCoordTransform& getTransform() const { return fTransform; }
581 578
582 private: 579 private:
583 GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile); 580 GrRectBlurEffect(const SkRect& rect, float sigma,
581 GrTexture *horizontal_scanline, GrTexture *vertical_scanlin e);
584 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 582 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
585 583
586 static bool CreateBlurProfileTexture(GrContext *context, float sigma, 584 static bool CreateScanlineTextures(GrContext *context, float sigma,
587 GrTexture **blurProfileTexture); 585 unsigned int width, unsigned int height,
586 GrTexture **horizontalScanline,
587 GrTexture **verticalScanline);
588 588
589 SkRect fRect; 589 unsigned int fWidth, fHeight;
590 float fSigma; 590 float fSigma;
591 GrTextureAccess fBlurProfileAccess; 591 GrTextureAccess fHorizontalScanlineAccess;
592 GrTextureAccess fVerticalScanlineAccess;
593 GrCoordTransform fTransform;
592 594
593 GR_DECLARE_EFFECT_TEST; 595 GR_DECLARE_EFFECT_TEST;
594 596
595 typedef GrEffect INHERITED; 597 typedef GrEffect INHERITED;
596 }; 598 };
597 599
598 class GrGLRectBlurEffect : public GrGLEffect { 600 class GrGLRectBlurEffect : public GrGLEffect {
599 public: 601 public:
600 GrGLRectBlurEffect(const GrBackendEffectFactory& factory, 602 GrGLRectBlurEffect(const GrBackendEffectFactory& factory,
601 const GrDrawEffect&); 603 const GrDrawEffect&);
602 virtual void emitCode(GrGLShaderBuilder*, 604 virtual void emitCode(GrGLShaderBuilder*,
603 const GrDrawEffect&, 605 const GrDrawEffect&,
604 EffectKey, 606 EffectKey,
605 const char* outputColor, 607 const char* outputColor,
606 const char* inputColor, 608 const char* inputColor,
607 const TransformedCoordsArray&, 609 const TransformedCoordsArray&,
608 const TextureSamplerArray&) SK_OVERRIDE; 610 const TextureSamplerArray&) SK_OVERRIDE;
609 611
610 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; 612 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
611 613
612 private: 614 private:
613 typedef GrGLUniformManager::UniformHandle UniformHandle; 615 typedef GrGLUniformManager::UniformHandle UniformHandle;
614 616
615 UniformHandle fProxyRectUniform; 617 UniformHandle fWidthUni;
616 UniformHandle fProfileSizeUniform; 618 UniformHandle fHeightUni;
617 619
618 typedef GrGLEffect INHERITED; 620 typedef GrGLEffect INHERITED;
619 }; 621 };
620 622
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.0*%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(".a;\n");
638 }
639
640 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, 627 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
641 const GrDrawEffect&, 628 const GrDrawEffect&,
642 EffectKey key, 629 EffectKey key,
643 const char* outputColor, 630 const char* outputColor,
644 const char* inputColor, 631 const char* inputColor,
645 const TransformedCoordsArray& coords, 632 const TransformedCoordsArray& coords,
646 const TextureSamplerArray& samplers) { 633 const TextureSamplerArray& samplers) {
647 634
648 const char *rectName; 635 SkString texture_coords = builder->ensureFSCoords2D(coords, 0);
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();
661 636
662 if (inputColor) { 637 if (inputColor) {
663 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor); 638 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor);
664 } else { 639 } else {
665 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;"); 640 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;");
666 } 641 }
667 642
668 builder->fsCodeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPo s, rectName ); 643 builder->fsCodeAppendf("\tvec4 horiz = ");
669 builder->fsCodeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName) ; 644 builder->fsAppendTextureLookup( samplers[0], texture_coords.c_str() );
670 builder->fsCodeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName ); 645 builder->fsCodeAppendf(";\n");
646 builder->fsCodeAppendf("\tvec4 vert = ");
647 builder->fsAppendTextureLookup( samplers[1], texture_coords.c_str() );
648 builder->fsCodeAppendf(";\n");
671 649
672 builder->fsCodeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName); 650 builder->fsCodeAppendf("\tfloat final = (horiz*vert).r;\n");
673 builder->fsCodeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n" , profileSizeName); 651 builder->fsCodeAppendf("\t%s = final*src;\n", outputColor);
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 = horiz_lookup * vert_lookup;\n");
687
688 builder->fsCodeAppendf("\t%s = src * vec4(final);\n", outputColor );
689 } 652 }
690 653
691 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, 654 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman,
692 const GrDrawEffect& drawEffect) { 655 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()));
698 } 656 }
699 657
700 bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma, 658 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma,
701 GrTexture **blurProfileTexture) { 659 unsigned int width, unsigned int h eight,
660 GrTexture **horizontalScanline,
661 GrTexture **verticalScanline) {
702 GrTextureParams params; 662 GrTextureParams params;
703 GrTextureDesc texDesc; 663 GrTextureDesc texDesc;
704 664
705 unsigned int profile_size = SkScalarCeilToInt(6*sigma); 665 unsigned int profile_size = SkScalarFloorToInt(6*sigma);
706 666
707 texDesc.fWidth = profile_size; 667 texDesc.fWidth = width;
708 texDesc.fHeight = 1; 668 texDesc.fHeight = 1;
709 texDesc.fConfig = kAlpha_8_GrPixelConfig; 669 texDesc.fConfig = kAlpha_8_GrPixelConfig;
710 670
711 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n(); 671 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n();
712 GrCacheID::Key key; 672 GrCacheID::Key key;
713 memset(&key, 0, sizeof(key)); 673 memset(&key, 0, sizeof(key));
714 key.fData32[0] = profile_size; 674 key.fData32[0] = profile_size;
715 key.fData32[1] = 1; 675 key.fData32[1] = width;
716 GrCacheID blurProfileKey(gBlurProfileDomain, key); 676 key.fData32[2] = 1;
677 GrCacheID horizontalCacheID(gBlurProfileDomain, key);
717 678
718 uint8_t *profile = NULL; 679 uint8_t *profile = NULL;
719 SkAutoTDeleteArray<uint8_t> ada(NULL); 680 SkAutoTDeleteArray<uint8_t> ada(NULL);
720 681
721 *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &p arams); 682 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID, &params);
722 683
723 if (NULL == *blurProfileTexture) { 684 if (NULL == *horizontalScanline) {
724 685
725 SkBlurMask::ComputeBlurProfile(sigma, &profile); 686 SkBlurMask::ComputeBlurProfile(sigma, &profile);
726 ada.reset(profile); 687 ada.reset(profile);
727 688
728 *blurProfileTexture = context->createTexture(&params, texDesc, blurProfi leKey, 689 SkAutoTMalloc<uint8_t> horizontalPixels(width);
729 profile, 0); 690 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, width, sig ma);
730 691
731 if (NULL == *blurProfileTexture) { 692 *horizontalScanline = context->createTexture(&params, texDesc, horizonta lCacheID,
693 horizontalPixels, 0);
694
695 if (NULL == *horizontalScanline) {
732 return false; 696 return false;
733 } 697 }
734 } 698 }
735 699
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 }
736 return true; 725 return true;
737 } 726 }
738 727
739 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, 728 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
740 GrTexture *blur_profile) 729 GrTexture *horizontal_scanline, GrTexture *ve rtical_scanline)
741 : INHERITED(), 730 : INHERITED(),
742 fRect(rect), 731 fWidth(horizontal_scanline->width()),
732 fHeight(vertical_scanline->width()),
743 fSigma(sigma), 733 fSigma(sigma),
744 fBlurProfileAccess(blur_profile) { 734 fHorizontalScanlineAccess(horizontal_scanline),
745 this->addTextureAccess(&fBlurProfileAccess); 735 fVerticalScanlineAccess(vertical_scanline) {
746 this->setWillReadFragmentPosition(); 736 SkMatrix mat;
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);
747 } 742 }
748 743
749 GrRectBlurEffect::~GrRectBlurEffect() { 744 GrRectBlurEffect::~GrRectBlurEffect() {
750 } 745 }
751 746
752 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { 747 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const {
753 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); 748 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance();
754 } 749 }
755 750
756 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { 751 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const {
757 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); 752 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase);
758 return this->getSigma() == s.getSigma() && this->getRect() == s.getRect(); 753 return this->getWidth() == s.getWidth() &&
754 this->getHeight() == s.getHeight() &&
755 this->getSigma() == s.getSigma() &&
756 this->getTransform() == s.getTransform();
759 } 757 }
760 758
761 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { 759 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const {
762 *validFlags = 0; 760 *validFlags = 0;
763 return; 761 return;
764 } 762 }
765 763
766 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); 764 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect);
767 765
768 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, 766 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random,
(...skipping 19 matching lines...) Expand all
788 if (!path.isRect(&rect)) { 786 if (!path.isRect(&rect)) {
789 return false; 787 return false;
790 } 788 }
791 789
792 if (!strokeRec.isFillStyle()) { 790 if (!strokeRec.isFillStyle()) {
793 return false; 791 return false;
794 } 792 }
795 793
796 SkMatrix ctm = context->getMatrix(); 794 SkMatrix ctm = context->getMatrix();
797 SkScalar xformedSigma = this->computeXformedSigma(ctm); 795 SkScalar xformedSigma = this->computeXformedSigma(ctm);
798 796 rect.outset(3*xformedSigma, 3*xformedSigma);
799 int pad=SkScalarCeilToInt(6*xformedSigma)/2;
800 rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
801 797
802 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( 798 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create(
803 context, rect, xformedSigma)); 799 context, rect, xformedSigma));
804 if (!effect) { 800 if (!effect) {
805 return false; 801 return false;
806 } 802 }
807 803
808 GrContext::AutoMatrix am; 804 GrContext::AutoMatrix am;
809 if (!am.setIdentity(context, grp)) { 805 if (!am.setIdentity(context, grp)) {
810 return false; 806 return false;
811 } 807 }
812 808
809
813 grp->addCoverageEffect(effect); 810 grp->addCoverageEffect(effect);
814 811
815 context->drawRect(*grp, rect); 812 context->drawRect(*grp, rect);
816 return true; 813 return true;
817 } 814 }
818 815
819 class GrGLRRectBlurEffect; 816 class GrGLRRectBlurEffect;
820 817
821 class GrRRectBlurEffect : public GrEffect { 818 class GrRRectBlurEffect : public GrEffect {
822 public: 819 public:
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 } else { 1209 } else {
1213 str->append("None"); 1210 str->append("None");
1214 } 1211 }
1215 str->append("))"); 1212 str->append("))");
1216 } 1213 }
1217 #endif 1214 #endif
1218 1215
1219 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1216 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1220 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1217 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1221 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1218 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