Chromium Code Reviews| 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 bool doFill, | |
| 46 SkPath *path) const SK_OVERRIDE; | |
| 47 | |
| 40 virtual bool filterMaskGPU(GrTexture* src, | 48 virtual bool filterMaskGPU(GrTexture* src, |
| 41 const SkRect& maskRect, | 49 const SkRect& maskRect, |
| 42 GrTexture** result, | 50 GrTexture** result, |
| 43 bool canOverwriteSrc) const; | 51 bool canOverwriteSrc) const; |
| 44 #endif | 52 #endif |
| 45 | 53 |
| 46 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; | 54 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
| 47 | 55 |
| 48 SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) | 56 SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) |
| 49 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) | 57 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 | 503 |
| 496 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { | 504 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { |
| 497 this->INHERITED::flatten(buffer); | 505 this->INHERITED::flatten(buffer); |
| 498 buffer.writeScalar(fSigma); | 506 buffer.writeScalar(fSigma); |
| 499 buffer.writeInt(fBlurStyle); | 507 buffer.writeInt(fBlurStyle); |
| 500 buffer.writeUInt(fBlurFlags); | 508 buffer.writeUInt(fBlurFlags); |
| 501 } | 509 } |
| 502 | 510 |
| 503 #if SK_SUPPORT_GPU | 511 #if SK_SUPPORT_GPU |
| 504 | 512 |
| 513 class GrGLRectBlurEffect; | |
| 514 | |
| 515 class GrRectBlurEffect : public GrEffect { | |
| 516 public: | |
| 517 virtual ~GrRectBlurEffect(); | |
| 518 | |
| 519 static const char* Name() { return "RectBlur"; } | |
| 520 | |
| 521 typedef GrGLRectBlurEffect GLEffect; | |
| 522 | |
| 523 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | |
| 524 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; | |
| 525 | |
| 526 /** | |
| 527 * Create a simple filter effect with custom bicubic coefficients. | |
| 528 */ | |
| 529 static GrEffectRef* Create(GrContext *context, unsigned int width, unsigned int height, | |
| 530 float sigma) { | |
| 531 GrTexture *horizontalScanline, *verticalScanline; | |
| 532 bool createdScanlines = CreateScanlineTextures(context, sigma, width, he ight, | |
| 533 &horizontalScanline, &ver ticalScanline); | |
| 534 if (!createdScanlines) { | |
| 535 return NULL; | |
| 536 } | |
| 537 AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (width, height, sigm a, | |
| 538 horizontalScanline, verticalScanline))); | |
| 539 return CreateEffectRef(effect); | |
| 540 } | |
| 541 | |
| 542 unsigned int getWidth() const { return fWidth; } | |
| 543 unsigned int getHeight() const { return fHeight; } | |
| 544 unsigned int getSigma() const { return fSigma; } | |
| 545 | |
| 546 private: | |
| 547 GrRectBlurEffect(unsigned int width, unsigned int height, float sigma, | |
| 548 GrTexture *horizontal_scanline, GrTexture *vertical_scanlin e); | |
| 549 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | |
| 550 | |
| 551 static bool CreateScanlineTextures(GrContext *context, float sigma, | |
| 552 unsigned int width, unsigned int height, | |
| 553 GrTexture **horizontalScanline, | |
| 554 GrTexture **verticalScanline); | |
| 555 | |
| 556 unsigned int fWidth, fHeight; | |
| 557 float fSigma; | |
| 558 GrTextureAccess fHorizontalScanlineAccess; | |
| 559 GrTextureAccess fVerticalScanlineAccess; | |
| 560 GrCoordTransform fTrivialTransform; | |
| 561 | |
| 562 GR_DECLARE_EFFECT_TEST; | |
| 563 | |
| 564 typedef GrEffect INHERITED; | |
| 565 }; | |
| 566 | |
| 567 class GrGLRectBlurEffect : public GrGLEffect { | |
| 568 public: | |
| 569 GrGLRectBlurEffect(const GrBackendEffectFactory& factory, | |
| 570 const GrDrawEffect&); | |
| 571 virtual void emitCode(GrGLShaderBuilder*, | |
| 572 const GrDrawEffect&, | |
| 573 EffectKey, | |
| 574 const char* outputColor, | |
| 575 const char* inputColor, | |
| 576 const TransformedCoordsArray&, | |
| 577 const TextureSamplerArray&) SK_OVERRIDE; | |
| 578 | |
| 579 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | |
| 580 | |
| 581 private: | |
| 582 typedef GrGLUniformManager::UniformHandle UniformHandle; | |
| 583 | |
| 584 UniformHandle fWidthUni; | |
| 585 UniformHandle fHeightUni; | |
| 586 | |
| 587 typedef GrGLEffect INHERITED; | |
| 588 }; | |
| 589 | |
| 590 GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, co nst GrDrawEffect&) | |
| 591 : INHERITED(factory) { | |
| 592 } | |
| 593 | |
| 594 void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder, | |
| 595 const GrDrawEffect&, | |
| 596 EffectKey key, | |
| 597 const char* outputColor, | |
| 598 const char* inputColor, | |
| 599 const TransformedCoordsArray& coords, | |
| 600 const TextureSamplerArray& samplers) { | |
| 601 | |
| 602 SkString texture_coords = builder->ensureFSCoords2D(coords, 0); | |
| 603 | |
| 604 builder->fsCodeAppendf("\tvec4 horiz = "); | |
| 605 builder->fsAppendTextureLookup( samplers[0], texture_coords.c_str() ); | |
| 606 builder->fsCodeAppendf(";\n"); | |
| 607 builder->fsCodeAppendf("\tvec4 vert = "); | |
| 608 builder->fsAppendTextureLookup( samplers[1], texture_coords.c_str() ); | |
| 609 builder->fsCodeAppendf(";\n"); | |
| 610 | |
| 611 builder->fsCodeAppendf("\tfloat final = (horiz*vert).r;\n"); | |
| 612 builder->fsCodeAppendf("\t%s = final*%s;\n", outputColor, inputColor); | |
|
bsalomon
2013/12/21 02:50:09
There is a weird case where inputColor may be NULL
| |
| 613 } | |
| 614 | |
| 615 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, | |
| 616 const GrDrawEffect& drawEffect) { | |
| 617 } | |
| 618 | |
| 619 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma, | |
| 620 unsigned int width, unsigned int h eight, | |
| 621 GrTexture **horizontalScanline, | |
| 622 GrTexture **verticalScanline) { | |
| 623 GrTextureParams params; | |
| 624 GrTextureDesc texDesc; | |
| 625 | |
| 626 unsigned int profile_size = 6*sigma; | |
| 627 | |
| 628 texDesc.fWidth = width; | |
| 629 texDesc.fHeight = 1; | |
| 630 texDesc.fConfig = kAlpha_8_GrPixelConfig; | |
| 631 | |
| 632 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n(); | |
| 633 GrCacheID::Key key; | |
| 634 memset(&key, 0, sizeof(key)); | |
| 635 key.fData32[0] = profile_size; | |
| 636 key.fData32[1] = width; | |
| 637 key.fData32[2] = 1; | |
| 638 GrCacheID horizontalCacheID(gBlurProfileDomain, key); | |
| 639 | |
| 640 uint8_t *profile = NULL; | |
| 641 SkAutoTDeleteArray<uint8_t> ada(profile); | |
| 642 | |
| 643 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID, ¶ms); | |
| 644 | |
| 645 if (NULL == *horizontalScanline) { | |
| 646 | |
| 647 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
| 648 | |
| 649 SkAutoTMalloc<uint8_t> horizontalPixels(width); | |
| 650 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, profile_si ze, width, sigma); | |
| 651 | |
| 652 *horizontalScanline = context->createTexture(¶ms, texDesc, horizonta lCacheID, | |
| 653 horizontalPixels, 0); | |
| 654 | |
| 655 if (NULL == *horizontalScanline) { | |
| 656 return false; | |
| 657 } | |
| 658 } | |
| 659 | |
| 660 texDesc.fWidth = 1; | |
| 661 texDesc.fHeight = height; | |
| 662 key.fData32[1] = 1; | |
|
bsalomon
2013/12/21 02:50:09
This guy doesn't also need the profile size?
humper
2013/12/23 13:26:58
He's already got it; I'm only overwriting the widt
| |
| 663 key.fData32[2] = height; | |
| 664 GrCacheID verticalCacheID(gBlurProfileDomain, key); | |
| 665 | |
| 666 *verticalScanline = context->findAndRefTexture(texDesc, verticalCacheID, &pa rams); | |
| 667 if (NULL == *verticalScanline) { | |
| 668 if (NULL == profile) { | |
| 669 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
| 670 } | |
| 671 | |
| 672 SkAutoTMalloc<uint8_t> verticalPixels(height); | |
| 673 SkBlurMask::ComputeBlurredScanline(verticalPixels, profile, profile_size , height, sigma); | |
| 674 | |
| 675 *verticalScanline = context->createTexture(¶ms, texDesc, verticalCac heID, | |
| 676 verticalPixels, 0); | |
| 677 | |
| 678 if (NULL == *verticalScanline) { | |
| 679 return false; | |
| 680 } | |
| 681 | |
| 682 } | |
| 683 return true; | |
| 684 } | |
| 685 | |
| 686 GrRectBlurEffect::GrRectBlurEffect(unsigned int width, unsigned int height, floa t sigma, | |
| 687 GrTexture *horizontal_scanline, GrTexture *ve rtical_scanline) | |
| 688 : INHERITED(), | |
| 689 fWidth(width), | |
| 690 fHeight(height), | |
| 691 fSigma(sigma), | |
| 692 fHorizontalScanlineAccess(horizontal_scanline), | |
| 693 fVerticalScanlineAccess(vertical_scanline), | |
| 694 fTrivialTransform(kLocal_GrCoordSet, SkMatrix()) { | |
|
bsalomon
2013/12/21 02:50:09
I thought SkMatrix didn't have a default cons and
humper
2013/12/23 13:26:58
Has to be the identity. I believe that's the defa
| |
| 695 this->addTextureAccess(&fHorizontalScanlineAccess); | |
| 696 this->addTextureAccess(&fVerticalScanlineAccess); | |
| 697 this->addCoordTransform(&fTrivialTransform); | |
| 698 } | |
| 699 | |
| 700 GrRectBlurEffect::~GrRectBlurEffect() { | |
| 701 } | |
| 702 | |
| 703 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { | |
| 704 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); | |
| 705 } | |
| 706 | |
| 707 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { | |
| 708 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); | |
| 709 return this->getWidth() == s.getWidth() && | |
| 710 this->getHeight() == s.getHeight() && | |
| 711 this->getSigma() == s.getSigma(); | |
| 712 } | |
| 713 | |
| 714 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { | |
| 715 // FIXME: Perhaps we can do better. | |
|
bsalomon
2013/12/21 02:50:09
I think this comment can be removed. It's not obvi
| |
| 716 *validFlags = 0; | |
| 717 return; | |
| 718 } | |
| 719 | |
| 720 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); | |
| 721 | |
| 722 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, | |
| 723 GrContext* context, | |
| 724 const GrDrawTargetCaps&, | |
| 725 GrTexture**) { | |
| 726 float sigma = random->nextRangeF(3,8); | |
| 727 unsigned int width = random->nextRangeU(200,300); | |
| 728 unsigned int height = random->nextRangeU(200,300); | |
| 729 return GrRectBlurEffect::Create(context, width, height, sigma); | |
| 730 } | |
| 731 | |
| 732 | |
| 733 bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext *context, | |
| 734 GrPaint *grp, | |
| 735 bool doFill, | |
| 736 SkPath *path) const { | |
| 737 GrContext::AutoMatrix am; | |
| 738 if (!am.setIdentity(context, grp)) { | |
| 739 return false; | |
| 740 } | |
| 741 | |
| 742 SkRect rect; | |
| 743 if (!path->isRect(&rect)) { | |
| 744 return false; | |
| 745 } | |
| 746 | |
| 747 if (!doFill) { | |
| 748 return false; | |
| 749 } | |
| 750 | |
| 751 rect.outset(3*fSigma, 3*fSigma); | |
| 752 | |
| 753 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( | |
| 754 context, rect.width(), rect.height(), fSigma)); | |
| 755 if (!effect) { | |
| 756 return false; | |
| 757 } | |
| 758 grp->addCoverageEffect(effect); | |
| 759 | |
| 760 context->drawRectToRect(*grp, rect, SkRect::MakeWH(1,1)); | |
| 761 return true; | |
| 762 } | |
| 763 | |
| 505 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, | 764 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, |
| 506 const SkIRect& clipBounds, | 765 const SkIRect& clipBounds, |
| 507 const SkMatrix& ctm, | 766 const SkMatrix& ctm, |
| 508 SkRect* maskRect) const { | 767 SkRect* maskRect) const { |
| 509 SkScalar xformedSigma = this->computeXformedSigma(ctm); | 768 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
| 510 if (xformedSigma <= 0) { | 769 if (xformedSigma <= 0) { |
| 511 return false; | 770 return false; |
| 512 } | 771 } |
| 513 | 772 |
| 514 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); | 773 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 } else { | 874 } else { |
| 616 str->append("None"); | 875 str->append("None"); |
| 617 } | 876 } |
| 618 str->append("))"); | 877 str->append("))"); |
| 619 } | 878 } |
| 620 #endif | 879 #endif |
| 621 | 880 |
| 622 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 881 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
| 623 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 882 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
| 624 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 883 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |