| 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 |