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