| 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 "SkFlattenableBuffers.h" | 12 #include "SkFlattenableBuffers.h" |
| 13 #include "SkMaskFilter.h" | 13 #include "SkMaskFilter.h" |
| 14 #include "SkRRect.h" | 14 #include "SkRRect.h" |
| 15 #include "SkRTConf.h" | 15 #include "SkRTConf.h" |
| 16 #include "SkStringUtils.h" | 16 #include "SkStringUtils.h" |
| 17 #include "SkStrokeRec.h" | 17 #include "SkStrokeRec.h" |
| 18 | 18 |
| 19 #if SK_SUPPORT_GPU | 19 #if SK_SUPPORT_GPU |
| 20 #include "GrContext.h" | 20 #include "GrContext.h" |
| 21 #include "GrTexture.h" | 21 #include "GrTexture.h" |
| 22 #include "GrEffect.h" | |
| 23 #include "gl/GrGLEffect.h" | |
| 24 #include "effects/GrSimpleTextureEffect.h" | 22 #include "effects/GrSimpleTextureEffect.h" |
| 25 #include "GrTBackendEffectFactory.h" | |
| 26 #include "SkGrPixelRef.h" | 23 #include "SkGrPixelRef.h" |
| 27 #endif | 24 #endif |
| 28 | 25 |
| 29 class SkBlurMaskFilterImpl : public SkMaskFilter { | 26 class SkBlurMaskFilterImpl : public SkMaskFilter { |
| 30 public: | 27 public: |
| 31 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t f
lags); | 28 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t f
lags); |
| 32 | 29 |
| 33 // overrides from SkMaskFilter | 30 // overrides from SkMaskFilter |
| 34 virtual SkMask::Format getFormat() const SK_OVERRIDE; | 31 virtual SkMask::Format getFormat() const SK_OVERRIDE; |
| 35 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, | 32 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
| 36 SkIPoint* margin) const SK_OVERRIDE; | 33 SkIPoint* margin) const SK_OVERRIDE; |
| 37 | 34 |
| 38 #if SK_SUPPORT_GPU | 35 #if SK_SUPPORT_GPU |
| 39 virtual bool canFilterMaskGPU(const SkRect& devBounds, | 36 virtual bool canFilterMaskGPU(const SkRect& devBounds, |
| 40 const SkIRect& clipBounds, | 37 const SkIRect& clipBounds, |
| 41 const SkMatrix& ctm, | 38 const SkMatrix& ctm, |
| 42 SkRect* maskRect) const SK_OVERRIDE; | 39 SkRect* maskRect) const SK_OVERRIDE; |
| 43 virtual bool directFilterMaskGPU(GrContext* context, | |
| 44 GrPaint* grp, | |
| 45 const SkStrokeRec& strokeRec, | |
| 46 const SkPath& path) const SK_OVERRIDE; | |
| 47 | |
| 48 virtual bool filterMaskGPU(GrTexture* src, | 40 virtual bool filterMaskGPU(GrTexture* src, |
| 49 const SkMatrix& ctm, | 41 const SkMatrix& ctm, |
| 50 const SkRect& maskRect, | 42 const SkRect& maskRect, |
| 51 GrTexture** result, | 43 GrTexture** result, |
| 52 bool canOverwriteSrc) const SK_OVERRIDE; | 44 bool canOverwriteSrc) const SK_OVERRIDE; |
| 53 #endif | 45 #endif |
| 54 | 46 |
| 55 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; | 47 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
| 56 | 48 |
| 57 SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) | 49 SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 | 496 |
| 505 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { | 497 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { |
| 506 this->INHERITED::flatten(buffer); | 498 this->INHERITED::flatten(buffer); |
| 507 buffer.writeScalar(fSigma); | 499 buffer.writeScalar(fSigma); |
| 508 buffer.writeInt(fBlurStyle); | 500 buffer.writeInt(fBlurStyle); |
| 509 buffer.writeUInt(fBlurFlags); | 501 buffer.writeUInt(fBlurFlags); |
| 510 } | 502 } |
| 511 | 503 |
| 512 #if SK_SUPPORT_GPU | 504 #if SK_SUPPORT_GPU |
| 513 | 505 |
| 514 class GrGLRectBlurEffect; | |
| 515 | |
| 516 class GrRectBlurEffect : public GrEffect { | |
| 517 public: | |
| 518 virtual ~GrRectBlurEffect(); | |
| 519 | |
| 520 static const char* Name() { return "RectBlur"; } | |
| 521 | |
| 522 typedef GrGLRectBlurEffect GLEffect; | |
| 523 | |
| 524 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | |
| 525 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | |
| 526 | |
| 527 /** | |
| 528 * Create a simple filter effect with custom bicubic coefficients. | |
| 529 */ | |
| 530 static GrEffectRef* Create(GrContext *context, const SkRect& rect, | |
| 531 float sigma) { | |
| 532 GrTexture *horizontalScanline, *verticalScanline; | |
| 533 bool createdScanlines = CreateScanlineTextures(context, sigma, | |
| 534 SkScalarCeilToInt(rect.wi
dth()), | |
| 535 SkScalarCeilToInt(rect.he
ight()), | |
| 536 &horizontalScanline, &ver
ticalScanline); | |
| 537 if (!createdScanlines) { | |
| 538 return NULL; | |
| 539 } | |
| 540 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, | |
| 541 horizontalScanline,
verticalScanline))); | |
| 542 return CreateEffectRef(effect); | |
| 543 } | |
| 544 | |
| 545 unsigned int getWidth() const { return fWidth; } | |
| 546 unsigned int getHeight() const { return fHeight; } | |
| 547 float getSigma() const { return fSigma; } | |
| 548 | |
| 549 private: | |
| 550 GrRectBlurEffect(const SkRect& rect, float sigma, | |
| 551 GrTexture *horizontal_scanline, GrTexture *vertical_scanlin
e); | |
| 552 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | |
| 553 | |
| 554 static bool CreateScanlineTextures(GrContext *context, float sigma, | |
| 555 unsigned int width, unsigned int height, | |
| 556 GrTexture **horizontalScanline, | |
| 557 GrTexture **verticalScanline); | |
| 558 | |
| 559 unsigned int fWidth, fHeight; | |
| 560 float fSigma; | |
| 561 GrTextureAccess fHorizontalScanlineAccess; | |
| 562 GrTextureAccess fVerticalScanlineAccess; | |
| 563 GrCoordTransform fTransform; | |
| 564 | |
| 565 GR_DECLARE_EFFECT_TEST; | |
| 566 | |
| 567 typedef GrEffect INHERITED; | |
| 568 }; | |
| 569 | |
| 570 class GrGLRectBlurEffect : public GrGLEffect { | |
| 571 public: | |
| 572 GrGLRectBlurEffect(const GrBackendEffectFactory& factory, | |
| 573 const GrDrawEffect&); | |
| 574 virtual void emitCode(GrGLShaderBuilder*, | |
| 575 const GrDrawEffect&, | |
| 576 EffectKey, | |
| 577 const char* outputColor, | |
| 578 const char* inputColor, | |
| 579 const TransformedCoordsArray&, | |
| 580 const TextureSamplerArray&) SK_OVERRIDE; | |
| 581 | |
| 582 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | |
| 583 | |
| 584 private: | |
| 585 typedef GrGLUniformManager::UniformHandle UniformHandle; | |
| 586 | |
| 587 UniformHandle fWidthUni; | |
| 588 UniformHandle fHeightUni; | |
| 589 | |
| 590 typedef GrGLEffect INHERITED; | |
| 591 }; | |
| 592 | |
| 593 GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, co
nst GrDrawEffect&) | |
| 594 : INHERITED(factory) { | |
| 595 } | |
| 596 | |
| 597 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, | |
| 598 const GrDrawEffect&, | |
| 599 EffectKey key, | |
| 600 const char* outputColor, | |
| 601 const char* inputColor, | |
| 602 const TransformedCoordsArray& coords, | |
| 603 const TextureSamplerArray& samplers) { | |
| 604 | |
| 605 SkString texture_coords = builder->ensureFSCoords2D(coords, 0); | |
| 606 | |
| 607 if (inputColor) { | |
| 608 builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor); | |
| 609 } else { | |
| 610 builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;"); | |
| 611 } | |
| 612 | |
| 613 builder->fsCodeAppendf("\tvec4 horiz = "); | |
| 614 builder->fsAppendTextureLookup( samplers[0], texture_coords.c_str() ); | |
| 615 builder->fsCodeAppendf(";\n"); | |
| 616 builder->fsCodeAppendf("\tvec4 vert = "); | |
| 617 builder->fsAppendTextureLookup( samplers[1], texture_coords.c_str() ); | |
| 618 builder->fsCodeAppendf(";\n"); | |
| 619 | |
| 620 builder->fsCodeAppendf("\tfloat final = (horiz*vert).r;\n"); | |
| 621 builder->fsCodeAppendf("\t%s = final*src;\n", outputColor); | |
| 622 } | |
| 623 | |
| 624 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, | |
| 625 const GrDrawEffect& drawEffect) { | |
| 626 } | |
| 627 | |
| 628 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma, | |
| 629 unsigned int width, unsigned int h
eight, | |
| 630 GrTexture **horizontalScanline, | |
| 631 GrTexture **verticalScanline) { | |
| 632 GrTextureParams params; | |
| 633 GrTextureDesc texDesc; | |
| 634 | |
| 635 unsigned int profile_size = SkScalarFloorToInt(6*sigma); | |
| 636 | |
| 637 texDesc.fWidth = width; | |
| 638 texDesc.fHeight = 1; | |
| 639 texDesc.fConfig = kAlpha_8_GrPixelConfig; | |
| 640 | |
| 641 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai
n(); | |
| 642 GrCacheID::Key key; | |
| 643 memset(&key, 0, sizeof(key)); | |
| 644 key.fData32[0] = profile_size; | |
| 645 key.fData32[1] = width; | |
| 646 key.fData32[2] = 1; | |
| 647 GrCacheID horizontalCacheID(gBlurProfileDomain, key); | |
| 648 | |
| 649 uint8_t *profile = NULL; | |
| 650 SkAutoTDeleteArray<uint8_t> ada(profile); | |
| 651 | |
| 652 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID,
¶ms); | |
| 653 | |
| 654 if (NULL == *horizontalScanline) { | |
| 655 | |
| 656 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
| 657 | |
| 658 SkAutoTMalloc<uint8_t> horizontalPixels(width); | |
| 659 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, width, sig
ma); | |
| 660 | |
| 661 *horizontalScanline = context->createTexture(¶ms, texDesc, horizonta
lCacheID, | |
| 662 horizontalPixels, 0); | |
| 663 | |
| 664 if (NULL == *horizontalScanline) { | |
| 665 return false; | |
| 666 } | |
| 667 } | |
| 668 | |
| 669 texDesc.fWidth = 1; | |
| 670 texDesc.fHeight = height; | |
| 671 key.fData32[1] = 1; | |
| 672 key.fData32[2] = height; | |
| 673 GrCacheID verticalCacheID(gBlurProfileDomain, key); | |
| 674 | |
| 675 *verticalScanline = context->findAndRefTexture(texDesc, verticalCacheID, &pa
rams); | |
| 676 if (NULL == *verticalScanline) { | |
| 677 if (NULL == profile) { | |
| 678 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
| 679 } | |
| 680 | |
| 681 SkAutoTMalloc<uint8_t> verticalPixels(height); | |
| 682 SkBlurMask::ComputeBlurredScanline(verticalPixels, profile, height, sigm
a); | |
| 683 | |
| 684 *verticalScanline = context->createTexture(¶ms, texDesc, verticalCac
heID, | |
| 685 verticalPixels, 0); | |
| 686 | |
| 687 if (NULL == *verticalScanline) { | |
| 688 return false; | |
| 689 } | |
| 690 | |
| 691 } | |
| 692 return true; | |
| 693 } | |
| 694 | |
| 695 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, | |
| 696 GrTexture *horizontal_scanline, GrTexture *ve
rtical_scanline) | |
| 697 : INHERITED(), | |
| 698 fWidth(horizontal_scanline->width()), | |
| 699 fHeight(vertical_scanline->width()), | |
| 700 fSigma(sigma), | |
| 701 fHorizontalScanlineAccess(horizontal_scanline), | |
| 702 fVerticalScanlineAccess(vertical_scanline) { | |
| 703 SkMatrix mat; | |
| 704 mat.setRectToRect(rect, SkRect::MakeWH(1,1), SkMatrix::kFill_ScaleToFit); | |
| 705 fTransform = GrCoordTransform(kLocal_GrCoordSet, mat); | |
| 706 this->addTextureAccess(&fHorizontalScanlineAccess); | |
| 707 this->addTextureAccess(&fVerticalScanlineAccess); | |
| 708 this->addCoordTransform(&fTransform); | |
| 709 } | |
| 710 | |
| 711 GrRectBlurEffect::~GrRectBlurEffect() { | |
| 712 } | |
| 713 | |
| 714 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { | |
| 715 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); | |
| 716 } | |
| 717 | |
| 718 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { | |
| 719 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); | |
| 720 return this->getWidth() == s.getWidth() && | |
| 721 this->getHeight() == s.getHeight() && | |
| 722 this->getSigma() == s.getSigma(); | |
| 723 } | |
| 724 | |
| 725 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali
dFlags) const { | |
| 726 *validFlags = 0; | |
| 727 return; | |
| 728 } | |
| 729 | |
| 730 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); | |
| 731 | |
| 732 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, | |
| 733 GrContext* context, | |
| 734 const GrDrawTargetCaps&, | |
| 735 GrTexture**) { | |
| 736 float sigma = random->nextRangeF(3,8); | |
| 737 float width = random->nextRangeF(200,300); | |
| 738 float height = random->nextRangeF(200,300); | |
| 739 return GrRectBlurEffect::Create(context, SkRect::MakeWH(width, height), sigm
a); | |
| 740 } | |
| 741 | |
| 742 | |
| 743 bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context, | |
| 744 GrPaint* grp, | |
| 745 const SkStrokeRec& strokeRec, | |
| 746 const SkPath& path) const { | |
| 747 if (fBlurStyle != SkBlurMaskFilter::kNormal_BlurStyle) { | |
| 748 return false; | |
| 749 } | |
| 750 | |
| 751 SkRect rect; | |
| 752 if (!path.isRect(&rect)) { | |
| 753 return false; | |
| 754 } | |
| 755 | |
| 756 if (!strokeRec.isFillStyle()) { | |
| 757 return false; | |
| 758 } | |
| 759 | |
| 760 SkMatrix ctm = context->getMatrix(); | |
| 761 SkScalar xformedSigma = this->computeXformedSigma(ctm); | |
| 762 rect.outset(3*xformedSigma, 3*xformedSigma); | |
| 763 | |
| 764 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( | |
| 765 context, rect, xformedSigma)); | |
| 766 if (!effect) { | |
| 767 return false; | |
| 768 } | |
| 769 | |
| 770 GrContext::AutoMatrix am; | |
| 771 if (!am.setIdentity(context, grp)) { | |
| 772 return false; | |
| 773 } | |
| 774 | |
| 775 | |
| 776 grp->addCoverageEffect(effect); | |
| 777 | |
| 778 context->drawRect(*grp, rect); | |
| 779 return true; | |
| 780 } | |
| 781 | |
| 782 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, | 506 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, |
| 783 const SkIRect& clipBounds, | 507 const SkIRect& clipBounds, |
| 784 const SkMatrix& ctm, | 508 const SkMatrix& ctm, |
| 785 SkRect* maskRect) const { | 509 SkRect* maskRect) const { |
| 786 SkScalar xformedSigma = this->computeXformedSigma(ctm); | 510 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
| 787 if (xformedSigma <= 0) { | 511 if (xformedSigma <= 0) { |
| 788 return false; | 512 return false; |
| 789 } | 513 } |
| 790 | 514 |
| 791 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); | 515 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 } else { | 617 } else { |
| 894 str->append("None"); | 618 str->append("None"); |
| 895 } | 619 } |
| 896 str->append("))"); | 620 str->append("))"); |
| 897 } | 621 } |
| 898 #endif | 622 #endif |
| 899 | 623 |
| 900 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 624 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
| 901 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 625 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
| 902 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 626 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |