OLD | NEW |
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" |
11 #include "SkGpuBlurUtils.h" | 11 #include "SkGpuBlurUtils.h" |
12 #include "SkReadBuffer.h" | 12 #include "SkReadBuffer.h" |
13 #include "SkWriteBuffer.h" | 13 #include "SkWriteBuffer.h" |
14 #include "SkMaskFilter.h" | 14 #include "SkMaskFilter.h" |
15 #include "SkRRect.h" | 15 #include "SkRRect.h" |
16 #include "SkRTConf.h" | 16 #include "SkRTConf.h" |
17 #include "SkStringUtils.h" | 17 #include "SkStringUtils.h" |
18 #include "SkStrokeRec.h" | 18 #include "SkStrokeRec.h" |
19 | 19 |
20 #if SK_SUPPORT_GPU | 20 #if SK_SUPPORT_GPU |
| 21 #include "GrCircleBlurFragmentProcessor.h" |
21 #include "GrContext.h" | 22 #include "GrContext.h" |
22 #include "GrDrawContext.h" | 23 #include "GrDrawContext.h" |
23 #include "GrTexture.h" | 24 #include "GrTexture.h" |
24 #include "GrFragmentProcessor.h" | 25 #include "GrFragmentProcessor.h" |
25 #include "GrInvariantOutput.h" | 26 #include "GrInvariantOutput.h" |
26 #include "SkGrPixelRef.h" | 27 #include "SkGrPixelRef.h" |
27 #include "SkDraw.h" | 28 #include "SkDraw.h" |
28 #include "effects/GrSimpleTextureEffect.h" | 29 #include "effects/GrSimpleTextureEffect.h" |
29 #include "gl/GrGLFragmentProcessor.h" | 30 #include "gl/GrGLFragmentProcessor.h" |
30 #include "gl/builders/GrGLProgramBuilder.h" | 31 #include "gl/builders/GrGLProgramBuilder.h" |
31 #endif | 32 #endif |
32 | 33 |
33 SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { | 34 SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { |
34 return SkBlurMask::ConvertRadiusToSigma(radius); | 35 return SkBlurMask::ConvertRadiusToSigma(radius); |
35 } | 36 } |
36 | 37 |
37 class SkBlurMaskFilterImpl : public SkMaskFilter { | 38 class SkBlurMaskFilterImpl : public SkMaskFilter { |
38 public: | 39 public: |
39 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); | 40 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); |
40 | 41 |
41 // overrides from SkMaskFilter | 42 // overrides from SkMaskFilter |
42 SkMask::Format getFormat() const override; | 43 SkMask::Format getFormat() const override; |
43 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, | 44 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
44 SkIPoint* margin) const override; | 45 SkIPoint* margin) const override; |
45 | 46 |
46 #if SK_SUPPORT_GPU | 47 #if SK_SUPPORT_GPU |
47 bool canFilterMaskGPU(const SkRect& devBounds, | 48 bool canFilterMaskGPU(const SkRRect& devRRect, |
48 const SkIRect& clipBounds, | 49 const SkIRect& clipBounds, |
49 const SkMatrix& ctm, | 50 const SkMatrix& ctm, |
50 SkRect* maskRect) const override; | 51 SkRect* maskRect) const override; |
51 bool directFilterMaskGPU(GrTextureProvider* texProvider, | 52 bool directFilterMaskGPU(GrTextureProvider* texProvider, |
52 GrDrawContext* drawContext, | 53 GrDrawContext* drawContext, |
53 GrRenderTarget* rt, | 54 GrRenderTarget* rt, |
54 GrPaint* grp, | 55 GrPaint* grp, |
55 const GrClip&, | 56 const GrClip&, |
56 const SkMatrix& viewMatrix, | 57 const SkMatrix& viewMatrix, |
57 const SkStrokeRec& strokeRec, | 58 const SkStrokeRec& strokeRec, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 if (rec) { | 160 if (rec) { |
160 rec->fSigma = fSigma; | 161 rec->fSigma = fSigma; |
161 rec->fStyle = fBlurStyle; | 162 rec->fStyle = fBlurStyle; |
162 rec->fQuality = this->getQuality(); | 163 rec->fQuality = this->getQuality(); |
163 } | 164 } |
164 return true; | 165 return true; |
165 } | 166 } |
166 | 167 |
167 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, | 168 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, |
168 const SkMatrix& matrix, | 169 const SkMatrix& matrix, |
169 SkIPoint* margin) const{ | 170 SkIPoint* margin) const { |
170 SkScalar sigma = this->computeXformedSigma(matrix); | 171 SkScalar sigma = this->computeXformedSigma(matrix); |
171 return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(),
margin); | 172 return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(),
margin); |
172 } | 173 } |
173 | 174 |
174 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, | 175 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
175 const SkMatrix& matrix, | 176 const SkMatrix& matrix, |
176 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ | 177 SkIPoint* margin, SkMask::CreateMode c
reateMode) const { |
177 SkScalar sigma = computeXformedSigma(matrix); | 178 SkScalar sigma = computeXformedSigma(matrix); |
178 | 179 |
179 return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle, | 180 return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle, margin, createMode); |
180 margin, createMode); | |
181 } | 181 } |
182 | 182 |
183 bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r, | 183 bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r, |
184 const SkMatrix& matrix, | 184 const SkMatrix& matrix, |
185 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ | 185 SkIPoint* margin, SkMask::CreateMode c
reateMode) const { |
186 SkScalar sigma = computeXformedSigma(matrix); | 186 SkScalar sigma = computeXformedSigma(matrix); |
187 | 187 |
188 return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle, | 188 return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle, margin, createMode); |
189 margin, createMode); | |
190 } | 189 } |
191 | 190 |
192 #include "SkCanvas.h" | 191 #include "SkCanvas.h" |
193 | 192 |
194 static bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { | 193 static bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { |
195 SkASSERT(mask != nullptr); | 194 SkASSERT(mask != nullptr); |
196 | 195 |
197 mask->fBounds = bounds.roundOut(); | 196 mask->fBounds = bounds.roundOut(); |
198 mask->fRowBytes = SkAlign4(mask->fBounds.width()); | 197 mask->fRowBytes = SkAlign4(mask->fBounds.width()); |
199 mask->fFormat = SkMask::kA8_Format; | 198 mask->fFormat = SkMask::kA8_Format; |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 buffer.writeUInt(fBlurStyle); | 599 buffer.writeUInt(fBlurStyle); |
601 buffer.writeUInt(fBlurFlags); | 600 buffer.writeUInt(fBlurFlags); |
602 } | 601 } |
603 | 602 |
604 #if SK_SUPPORT_GPU | 603 #if SK_SUPPORT_GPU |
605 | 604 |
606 class GrGLRectBlurEffect; | 605 class GrGLRectBlurEffect; |
607 | 606 |
608 class GrRectBlurEffect : public GrFragmentProcessor { | 607 class GrRectBlurEffect : public GrFragmentProcessor { |
609 public: | 608 public: |
610 virtual ~GrRectBlurEffect(); | 609 ~GrRectBlurEffect() override { } |
611 | 610 |
612 const char* name() const override { return "RectBlur"; } | 611 const char* name() const override { return "RectBlur"; } |
613 | 612 |
614 /** | 613 static GrFragmentProcessor* Create(GrTextureProvider *textureProvider, |
615 * Create a simple filter effect with custom bicubic coefficients. | 614 const SkRect& rect, float sigma) { |
616 */ | |
617 static GrFragmentProcessor* Create(GrTextureProvider *textureProvider, const
SkRect& rect, | |
618 float sigma) { | |
619 GrTexture *blurProfileTexture = nullptr; | |
620 int doubleProfileSize = SkScalarCeilToInt(12*sigma); | 615 int doubleProfileSize = SkScalarCeilToInt(12*sigma); |
621 | 616 |
622 if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.heigh
t()) { | 617 if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.heigh
t()) { |
623 // if the blur sigma is too large so the gaussian overlaps the whole | 618 // if the blur sigma is too large so the gaussian overlaps the whole |
624 // rect in either direction, fall back to CPU path for now. | 619 // rect in either direction, fall back to CPU path for now. |
625 | |
626 return nullptr; | 620 return nullptr; |
627 } | 621 } |
628 | 622 |
629 bool createdBlurProfileTexture = CreateBlurProfileTexture( | 623 SkAutoTUnref<GrTexture> blurProfile(CreateBlurProfileTexture(textureProv
ider, sigma)); |
630 textureProvider, sigma, &blurProfileTexture); | 624 if (!blurProfile) { |
631 SkAutoTUnref<GrTexture> hunref(blurProfileTexture); | |
632 if (!createdBlurProfileTexture) { | |
633 return nullptr; | 625 return nullptr; |
634 } | 626 } |
635 return new GrRectBlurEffect(rect, sigma, blurProfileTexture); | 627 return new GrRectBlurEffect(rect, sigma, blurProfile); |
636 } | 628 } |
637 | 629 |
638 const SkRect& getRect() const { return fRect; } | 630 const SkRect& getRect() const { return fRect; } |
639 float getSigma() const { return fSigma; } | 631 float getSigma() const { return fSigma; } |
640 | 632 |
641 private: | 633 private: |
| 634 GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blurProfile); |
| 635 |
642 GrGLFragmentProcessor* onCreateGLInstance() const override; | 636 GrGLFragmentProcessor* onCreateGLInstance() const override; |
643 | 637 |
644 GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile); | 638 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; |
645 | |
646 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, | |
647 GrProcessorKeyBuilder* b) const override; | |
648 | 639 |
649 bool onIsEqual(const GrFragmentProcessor&) const override; | 640 bool onIsEqual(const GrFragmentProcessor&) const override; |
650 | 641 |
651 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | 642 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; |
652 | 643 |
653 static bool CreateBlurProfileTexture(GrTextureProvider*, float sigma, | 644 static GrTexture* CreateBlurProfileTexture(GrTextureProvider*, float sigma); |
654 GrTexture **blurProfileTexture); | |
655 | 645 |
656 SkRect fRect; | 646 SkRect fRect; |
657 float fSigma; | 647 float fSigma; |
658 GrTextureAccess fBlurProfileAccess; | 648 GrTextureAccess fBlurProfileAccess; |
659 | 649 |
660 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 650 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
661 | 651 |
662 typedef GrFragmentProcessor INHERITED; | 652 typedef GrFragmentProcessor INHERITED; |
663 }; | 653 }; |
664 | 654 |
665 class GrGLRectBlurEffect : public GrGLFragmentProcessor { | 655 class GrGLRectBlurEffect : public GrGLFragmentProcessor { |
666 public: | 656 public: |
667 GrGLRectBlurEffect(const GrProcessor&) {} | 657 GrGLRectBlurEffect(const GrProcessor&) {} |
668 virtual void emitCode(EmitArgs&) override; | 658 void emitCode(EmitArgs&) override; |
669 | 659 |
670 protected: | 660 protected: |
671 void onSetData(const GrGLProgramDataManager&, const GrProcessor&) override; | 661 void onSetData(const GrGLProgramDataManager&, const GrProcessor&) override; |
672 | 662 |
673 private: | 663 private: |
674 typedef GrGLProgramDataManager::UniformHandle UniformHandle; | 664 typedef GrGLProgramDataManager::UniformHandle UniformHandle; |
675 | 665 |
676 UniformHandle fProxyRectUniform; | 666 UniformHandle fProxyRectUniform; |
677 UniformHandle fProfileSizeUniform; | 667 UniformHandle fProfileSizeUniform; |
678 | 668 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "horiz_lookup", pr
ofileSizeName, | 721 OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "horiz_lookup", pr
ofileSizeName, |
732 "translatedPos.x", "width", "wh.x"); | 722 "translatedPos.x", "width", "wh.x"); |
733 OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "vert_lookup", pro
fileSizeName, | 723 OutputRectBlurProfileLookup(fsBuilder, args.fSamplers[0], "vert_lookup", pro
fileSizeName, |
734 "translatedPos.y", "height", "wh.y"); | 724 "translatedPos.y", "height", "wh.y"); |
735 | 725 |
736 fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n"); | 726 fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n"); |
737 fsBuilder->codeAppendf("\t%s = src * final;\n", args.fOutputColor ); | 727 fsBuilder->codeAppendf("\t%s = src * final;\n", args.fOutputColor ); |
738 } | 728 } |
739 | 729 |
740 void GrGLRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman, | 730 void GrGLRectBlurEffect::onSetData(const GrGLProgramDataManager& pdman, |
741 const GrProcessor& proc) { | 731 const GrProcessor& proc) { |
742 const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); | 732 const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>(); |
743 SkRect rect = rbe.getRect(); | 733 SkRect rect = rbe.getRect(); |
744 | 734 |
745 pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBot
tom); | 735 pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBot
tom); |
746 pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma())); | 736 pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma())); |
747 } | 737 } |
748 | 738 |
749 bool GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvid
er, float sigma, | 739 GrTexture* GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* texture
Provider, |
750 GrTexture **blurProfileTexture)
{ | 740 float sigma) { |
751 GrSurfaceDesc texDesc; | 741 GrSurfaceDesc texDesc; |
752 | 742 |
753 unsigned int profileSize = SkScalarCeilToInt(6*sigma); | 743 unsigned int profileSize = SkScalarCeilToInt(6*sigma); |
754 | 744 |
755 texDesc.fWidth = profileSize; | 745 texDesc.fWidth = profileSize; |
756 texDesc.fHeight = 1; | 746 texDesc.fHeight = 1; |
757 texDesc.fConfig = kAlpha_8_GrPixelConfig; | 747 texDesc.fConfig = kAlpha_8_GrPixelConfig; |
758 | 748 |
759 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 749 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
760 GrUniqueKey key; | 750 GrUniqueKey key; |
761 GrUniqueKey::Builder builder(&key, kDomain, 1); | 751 GrUniqueKey::Builder builder(&key, kDomain, 1); |
762 builder[0] = profileSize; | 752 builder[0] = profileSize; |
763 builder.finish(); | 753 builder.finish(); |
764 | 754 |
765 uint8_t *profile = nullptr; | 755 GrTexture *blurProfile = textureProvider->findAndRefTextureByUniqueKey(key); |
766 SkAutoTDeleteArray<uint8_t> ada(nullptr); | |
767 | 756 |
768 *blurProfileTexture = textureProvider->findAndRefTextureByUniqueKey(key); | 757 if (!blurProfile) { |
| 758 SkAutoTDeleteArray<uint8_t> profile(SkBlurMask::ComputeBlurProfile(sigma
)); |
769 | 759 |
770 if (nullptr == *blurProfileTexture) { | 760 blurProfile = textureProvider->createTexture(texDesc, true, profile.get(
), 0); |
771 | 761 if (blurProfile) { |
772 SkBlurMask::ComputeBlurProfile(sigma, &profile); | 762 textureProvider->assignUniqueKeyToTexture(key, blurProfile); |
773 ada.reset(profile); | |
774 | |
775 *blurProfileTexture = textureProvider->createTexture(texDesc, true, prof
ile, 0); | |
776 | |
777 if (nullptr == *blurProfileTexture) { | |
778 return false; | |
779 } | 763 } |
780 textureProvider->assignUniqueKeyToTexture(key, *blurProfileTexture); | |
781 } | 764 } |
782 | 765 |
783 return true; | 766 return blurProfile; |
784 } | 767 } |
785 | 768 |
786 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, | 769 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *b
lurProfile) |
787 GrTexture *blur_profile) | 770 : fRect(rect) |
788 : fRect(rect), | 771 , fSigma(sigma) |
789 fSigma(sigma), | 772 , fBlurProfileAccess(blurProfile) { |
790 fBlurProfileAccess(blur_profile) { | |
791 this->initClassID<GrRectBlurEffect>(); | 773 this->initClassID<GrRectBlurEffect>(); |
792 this->addTextureAccess(&fBlurProfileAccess); | 774 this->addTextureAccess(&fBlurProfileAccess); |
793 this->setWillReadFragmentPosition(); | 775 this->setWillReadFragmentPosition(); |
794 } | 776 } |
795 | 777 |
796 GrRectBlurEffect::~GrRectBlurEffect() { | |
797 } | |
798 | |
799 void GrRectBlurEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, | 778 void GrRectBlurEffect::onGetGLProcessorKey(const GrGLSLCaps& caps, |
800 GrProcessorKeyBuilder* b) const { | 779 GrProcessorKeyBuilder* b) const { |
801 GrGLRectBlurEffect::GenKey(*this, caps, b); | 780 GrGLRectBlurEffect::GenKey(*this, caps, b); |
802 } | 781 } |
803 | 782 |
804 GrGLFragmentProcessor* GrRectBlurEffect::onCreateGLInstance() const { | 783 GrGLFragmentProcessor* GrRectBlurEffect::onCreateGLInstance() const { |
805 return new GrGLRectBlurEffect(*this); | 784 return new GrGLRectBlurEffect(*this); |
806 } | 785 } |
807 | 786 |
808 bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& sBase) const { | 787 bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& sBase) const { |
(...skipping 23 matching lines...) Expand all Loading... |
832 const GrClip& clip, | 811 const GrClip& clip, |
833 const SkMatrix& viewMatrix, | 812 const SkMatrix& viewMatrix, |
834 const SkStrokeRec& strokeRec, | 813 const SkStrokeRec& strokeRec, |
835 const SkPath& path) const { | 814 const SkPath& path) const { |
836 SkASSERT(drawContext); | 815 SkASSERT(drawContext); |
837 | 816 |
838 if (fBlurStyle != kNormal_SkBlurStyle) { | 817 if (fBlurStyle != kNormal_SkBlurStyle) { |
839 return false; | 818 return false; |
840 } | 819 } |
841 | 820 |
842 SkRect rect; | 821 // TODO: we could handle blurred stroked circles |
843 if (!path.isRect(&rect)) { | |
844 return false; | |
845 } | |
846 | |
847 if (!strokeRec.isFillStyle()) { | 822 if (!strokeRec.isFillStyle()) { |
848 return false; | 823 return false; |
849 } | 824 } |
850 | 825 |
851 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); | 826 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); |
852 | 827 |
853 int pad = SkScalarCeilToInt(6*xformedSigma)/2; | 828 SkAutoTUnref<const GrFragmentProcessor> fp; |
854 rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); | |
855 | 829 |
856 SkAutoTUnref<GrFragmentProcessor> fp(GrRectBlurEffect::Create( | 830 SkRect rect; |
857 texProvider, rec
t, xformedSigma)); | 831 if (path.isRect(&rect)) { |
| 832 int pad = SkScalarCeilToInt(6*xformedSigma)/2; |
| 833 rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); |
| 834 |
| 835 fp.reset(GrRectBlurEffect::Create(texProvider, rect, xformedSigma)); |
| 836 } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.heig
ht())) { |
| 837 fp.reset(GrCircleBlurFragmentProcessor::Create(texProvider, rect, xforme
dSigma)); |
| 838 |
| 839 // expand the rect for the coverage geometry |
| 840 int pad = SkScalarCeilToInt(6*xformedSigma)/2; |
| 841 rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); |
| 842 } else { |
| 843 return false; |
| 844 } |
| 845 |
858 if (!fp) { | 846 if (!fp) { |
859 return false; | 847 return false; |
860 } | 848 } |
861 | 849 |
862 grp->addCoverageFragmentProcessor(fp); | 850 grp->addCoverageFragmentProcessor(fp); |
863 | 851 |
864 SkMatrix inverse; | 852 SkMatrix inverse; |
865 if (!viewMatrix.invert(&inverse)) { | 853 if (!viewMatrix.invert(&inverse)) { |
866 return false; | 854 return false; |
867 } | 855 } |
868 | 856 |
869 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), rec
t, inverse); | 857 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), rec
t, inverse); |
870 return true; | 858 return true; |
871 } | 859 } |
872 | 860 |
| 861 ////////////////////////////////////////////////////////////////////////////// |
| 862 |
873 class GrRRectBlurEffect : public GrFragmentProcessor { | 863 class GrRRectBlurEffect : public GrFragmentProcessor { |
874 public: | 864 public: |
875 | 865 |
876 static GrFragmentProcessor* Create(GrTextureProvider*, float sigma, const Sk
RRect&); | 866 static const GrFragmentProcessor* Create(GrTextureProvider*, float sigma, co
nst SkRRect&); |
877 | 867 |
878 virtual ~GrRRectBlurEffect() {}; | 868 virtual ~GrRRectBlurEffect() {}; |
879 const char* name() const override { return "GrRRectBlur"; } | 869 const char* name() const override { return "GrRRectBlur"; } |
880 | 870 |
881 const SkRRect& getRRect() const { return fRRect; } | 871 const SkRRect& getRRect() const { return fRRect; } |
882 float getSigma() const { return fSigma; } | 872 float getSigma() const { return fSigma; } |
883 | 873 |
884 private: | 874 private: |
885 GrGLFragmentProcessor* onCreateGLInstance() const override; | 875 GrGLFragmentProcessor* onCreateGLInstance() const override; |
886 | 876 |
887 GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture); | 877 GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture); |
888 | 878 |
889 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, | 879 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, |
890 GrProcessorKeyBuilder* b) const override; | 880 GrProcessorKeyBuilder* b) const override; |
891 | 881 |
892 bool onIsEqual(const GrFragmentProcessor& other) const override; | 882 bool onIsEqual(const GrFragmentProcessor& other) const override; |
893 | 883 |
894 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | 884 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; |
895 | 885 |
896 SkRRect fRRect; | 886 SkRRect fRRect; |
897 float fSigma; | 887 float fSigma; |
898 GrTextureAccess fNinePatchAccess; | 888 GrTextureAccess fNinePatchAccess; |
899 | 889 |
900 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 890 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
901 | 891 |
902 typedef GrFragmentProcessor INHERITED; | 892 typedef GrFragmentProcessor INHERITED; |
903 }; | 893 }; |
904 | 894 |
905 | 895 |
906 GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvider, f
loat sigma, | 896 const GrFragmentProcessor* GrRRectBlurEffect::Create(GrTextureProvider* texProvi
der, float sigma, |
907 const SkRRect& rrect) { | 897 const SkRRect& rrect) { |
| 898 if (rrect.isCircle()) { |
| 899 return GrCircleBlurFragmentProcessor::Create(texProvider, rrect.rect(),
sigma); |
| 900 } |
| 901 |
908 if (!rrect.isSimpleCircular()) { | 902 if (!rrect.isSimpleCircular()) { |
909 return nullptr; | 903 return nullptr; |
910 } | 904 } |
911 | 905 |
912 // Make sure we can successfully ninepatch this rrect -- the blur sigma has
to be | 906 // Make sure we can successfully ninepatch this rrect -- the blur sigma has
to be |
913 // sufficiently small relative to both the size of the corner radius and the | 907 // sufficiently small relative to both the size of the corner radius and the |
914 // width (and height) of the rrect. | 908 // width (and height) of the rrect. |
915 | 909 |
916 unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f); | 910 unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f); |
917 unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x()); | 911 unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x()); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 if (!strokeRec.isFillStyle()) { | 1116 if (!strokeRec.isFillStyle()) { |
1123 return false; | 1117 return false; |
1124 } | 1118 } |
1125 | 1119 |
1126 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); | 1120 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); |
1127 float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); | 1121 float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); |
1128 | 1122 |
1129 SkRect proxyRect = rrect.rect(); | 1123 SkRect proxyRect = rrect.rect(); |
1130 proxyRect.outset(extra, extra); | 1124 proxyRect.outset(extra, extra); |
1131 | 1125 |
1132 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectBlurEffect::Create(texProvider, | 1126 SkAutoTUnref<const GrFragmentProcessor> fp(GrRRectBlurEffect::Create(texProv
ider, |
1133 xformedSigma,
rrect)); | 1127 xformed
Sigma, rrect)); |
1134 if (!fp) { | 1128 if (!fp) { |
1135 return false; | 1129 return false; |
1136 } | 1130 } |
1137 | 1131 |
1138 grp->addCoverageFragmentProcessor(fp); | 1132 grp->addCoverageFragmentProcessor(fp); |
1139 | 1133 |
1140 SkMatrix inverse; | 1134 SkMatrix inverse; |
1141 if (!viewMatrix.invert(&inverse)) { | 1135 if (!viewMatrix.invert(&inverse)) { |
1142 return false; | 1136 return false; |
1143 } | 1137 } |
1144 | 1138 |
1145 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), pro
xyRect, inverse); | 1139 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), pro
xyRect, inverse); |
1146 return true; | 1140 return true; |
1147 } | 1141 } |
1148 | 1142 |
1149 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, | 1143 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, |
1150 const SkIRect& clipBounds, | 1144 const SkIRect& clipBounds, |
1151 const SkMatrix& ctm, | 1145 const SkMatrix& ctm, |
1152 SkRect* maskRect) const { | 1146 SkRect* maskRect) const { |
1153 SkScalar xformedSigma = this->computeXformedSigma(ctm); | 1147 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
1154 if (xformedSigma <= 0) { | 1148 if (xformedSigma <= 0) { |
1155 return false; | 1149 return false; |
1156 } | 1150 } |
1157 | 1151 |
1158 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); | 1152 // We always do circles on the GPU |
1159 static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); | 1153 if (!devRRect.isCircle()) { |
| 1154 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
| 1155 static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); |
1160 | 1156 |
1161 if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE && | 1157 if (devRRect.width() <= kMIN_GPU_BLUR_SIZE && |
1162 srcBounds.height() <= kMIN_GPU_BLUR_SIZE && | 1158 devRRect.height() <= kMIN_GPU_BLUR_SIZE && |
1163 xformedSigma <= kMIN_GPU_BLUR_SIGMA) { | 1159 xformedSigma <= kMIN_GPU_BLUR_SIGMA) { |
1164 // We prefer to blur small rect with small radius via CPU. | 1160 // We prefer to blur small rects with small radii on the CPU. |
1165 return false; | 1161 return false; |
| 1162 } |
1166 } | 1163 } |
1167 | 1164 |
1168 if (nullptr == maskRect) { | 1165 if (nullptr == maskRect) { |
1169 // don't need to compute maskRect | 1166 // don't need to compute maskRect |
1170 return true; | 1167 return true; |
1171 } | 1168 } |
1172 | 1169 |
1173 float sigma3 = 3 * SkScalarToFloat(xformedSigma); | 1170 float sigma3 = 3 * SkScalarToFloat(xformedSigma); |
1174 | 1171 |
1175 SkRect clipRect = SkRect::Make(clipBounds); | 1172 SkRect clipRect = SkRect::Make(clipBounds); |
1176 SkRect srcRect(srcBounds); | 1173 SkRect srcRect(devRRect.rect()); |
1177 | 1174 |
1178 // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. | 1175 // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. |
1179 srcRect.outset(sigma3, sigma3); | 1176 srcRect.outset(sigma3, sigma3); |
1180 clipRect.outset(sigma3, sigma3); | 1177 clipRect.outset(sigma3, sigma3); |
1181 if (!srcRect.intersect(clipRect)) { | 1178 if (!srcRect.intersect(clipRect)) { |
1182 srcRect.setEmpty(); | 1179 srcRect.setEmpty(); |
1183 } | 1180 } |
1184 *maskRect = srcRect; | 1181 *maskRect = srcRect; |
1185 return true; | 1182 return true; |
1186 } | 1183 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 } else { | 1263 } else { |
1267 str->append("None"); | 1264 str->append("None"); |
1268 } | 1265 } |
1269 str->append("))"); | 1266 str->append("))"); |
1270 } | 1267 } |
1271 #endif | 1268 #endif |
1272 | 1269 |
1273 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 1270 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
1274 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 1271 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
1275 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1272 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |