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 |