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 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
496 | 504 |
497 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { | 505 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { |
498 this->INHERITED::flatten(buffer); | 506 this->INHERITED::flatten(buffer); |
499 buffer.writeScalar(fSigma); | 507 buffer.writeScalar(fSigma); |
500 buffer.writeInt(fBlurStyle); | 508 buffer.writeInt(fBlurStyle); |
501 buffer.writeUInt(fBlurFlags); | 509 buffer.writeUInt(fBlurFlags); |
502 } | 510 } |
503 | 511 |
504 #if SK_SUPPORT_GPU | 512 #if SK_SUPPORT_GPU |
505 | 513 |
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 fTrivialTransform; | |
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 // builder->fsCodeAppendf("\t%s = vec4(%s.r,%s.g,0,1);\n", outputColor, text ure_coords.c_str(), texture_coords.c_str()); | |
bsalomon
2014/01/27 19:07:00
should we remove this line?
| |
623 } | |
624 | |
625 void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman, | |
626 const GrDrawEffect& drawEffect) { | |
627 } | |
628 | |
629 bool GrRectBlurEffect::CreateScanlineTextures(GrContext *context, float sigma, | |
630 unsigned int width, unsigned int h eight, | |
631 GrTexture **horizontalScanline, | |
632 GrTexture **verticalScanline) { | |
633 GrTextureParams params; | |
634 GrTextureDesc texDesc; | |
635 | |
636 unsigned int profile_size = SkScalarFloorToInt(6*sigma); | |
637 | |
638 texDesc.fWidth = width; | |
639 texDesc.fHeight = 1; | |
640 texDesc.fConfig = kAlpha_8_GrPixelConfig; | |
641 | |
642 static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomai n(); | |
643 GrCacheID::Key key; | |
644 memset(&key, 0, sizeof(key)); | |
645 key.fData32[0] = profile_size; | |
646 key.fData32[1] = width; | |
647 key.fData32[2] = 1; | |
648 GrCacheID horizontalCacheID(gBlurProfileDomain, key); | |
bsalomon
2014/01/27 19:07:00
should we make both the horizontal and vertical te
| |
649 | |
650 uint8_t *profile = NULL; | |
651 SkAutoTDeleteArray<uint8_t> ada(profile); | |
652 | |
653 *horizontalScanline = context->findAndRefTexture(texDesc, horizontalCacheID, ¶ms); | |
654 | |
655 if (NULL == *horizontalScanline) { | |
656 | |
657 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
658 | |
659 SkAutoTMalloc<uint8_t> horizontalPixels(width); | |
660 SkBlurMask::ComputeBlurredScanline(horizontalPixels, profile, width, sig ma); | |
661 | |
662 *horizontalScanline = context->createTexture(¶ms, texDesc, horizonta lCacheID, | |
663 horizontalPixels, 0); | |
664 | |
665 if (NULL == *horizontalScanline) { | |
666 return false; | |
667 } | |
668 } | |
669 | |
670 texDesc.fWidth = 1; | |
671 texDesc.fHeight = height; | |
672 key.fData32[1] = 1; | |
673 key.fData32[2] = height; | |
674 GrCacheID verticalCacheID(gBlurProfileDomain, key); | |
675 | |
676 *verticalScanline = context->findAndRefTexture(texDesc, verticalCacheID, &pa rams); | |
677 if (NULL == *verticalScanline) { | |
678 if (NULL == profile) { | |
679 SkBlurMask::ComputeBlurProfile(sigma, &profile); | |
680 } | |
681 | |
682 SkAutoTMalloc<uint8_t> verticalPixels(height); | |
683 SkBlurMask::ComputeBlurredScanline(verticalPixels, profile, height, sigm a); | |
684 | |
685 *verticalScanline = context->createTexture(¶ms, texDesc, verticalCac heID, | |
686 verticalPixels, 0); | |
687 | |
688 if (NULL == *verticalScanline) { | |
689 return false; | |
690 } | |
691 | |
692 } | |
693 return true; | |
694 } | |
695 | |
696 GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, | |
697 GrTexture *horizontal_scanline, GrTexture *ve rtical_scanline) | |
698 : INHERITED(), | |
699 fWidth(horizontal_scanline->width()), | |
700 fHeight(vertical_scanline->width()), | |
701 fSigma(sigma), | |
702 fHorizontalScanlineAccess(horizontal_scanline), | |
703 fVerticalScanlineAccess(vertical_scanline) { | |
704 SkMatrix mat; | |
705 mat.setRectToRect(rect, SkRect::MakeWH(1,1), SkMatrix::kFill_ScaleToFit); | |
706 fTrivialTransform = GrCoordTransform(kLocal_GrCoordSet, mat); | |
bsalomon
2014/01/27 19:07:00
Is this the right name for this now (trivial)?
| |
707 this->addTextureAccess(&fHorizontalScanlineAccess); | |
708 this->addTextureAccess(&fVerticalScanlineAccess); | |
709 this->addCoordTransform(&fTrivialTransform); | |
710 } | |
711 | |
712 GrRectBlurEffect::~GrRectBlurEffect() { | |
713 } | |
714 | |
715 const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const { | |
716 return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance(); | |
717 } | |
718 | |
719 bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const { | |
720 const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase); | |
721 return this->getWidth() == s.getWidth() && | |
722 this->getHeight() == s.getHeight() && | |
723 this->getSigma() == s.getSigma(); | |
724 } | |
725 | |
726 void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* vali dFlags) const { | |
727 *validFlags = 0; | |
728 return; | |
729 } | |
730 | |
731 GR_DEFINE_EFFECT_TEST(GrRectBlurEffect); | |
732 | |
733 GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random, | |
734 GrContext* context, | |
735 const GrDrawTargetCaps&, | |
736 GrTexture**) { | |
737 float sigma = random->nextRangeF(3,8); | |
738 float width = random->nextRangeF(200,300); | |
739 float height = random->nextRangeF(200,300); | |
740 return GrRectBlurEffect::Create(context, SkRect::MakeWH(width, height), sigm a); | |
741 } | |
742 | |
743 | |
744 bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context, | |
745 GrPaint* grp, | |
746 const SkStrokeRec& strokeRec, | |
747 const SkPath& path) const { | |
748 if (fBlurStyle != SkBlurMaskFilter::kNormal_BlurStyle) { | |
749 return false; | |
750 } | |
751 | |
752 SkRect rect; | |
753 if (!path.isRect(&rect)) { | |
754 return false; | |
755 } | |
756 | |
757 if (!strokeRec.isFillStyle()) { | |
758 return false; | |
759 } | |
760 | |
761 GrContext::AutoMatrix am; | |
762 if (!am.setIdentity(context, grp)) { | |
763 return false; | |
764 } | |
765 | |
766 SkMatrix ctm = context->getMatrix(); | |
bsalomon
2014/01/27 19:07:00
this is now guaranteed to be identity because of t
| |
767 SkScalar xformedSigma = this->computeXformedSigma(ctm); | |
768 rect.outset(3*xformedSigma, 3*xformedSigma); | |
769 | |
770 SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create( | |
771 context, rect, xformedSigma)); | |
772 if (!effect) { | |
773 return false; | |
774 } | |
775 grp->addCoverageEffect(effect); | |
776 | |
777 context->drawRect(*grp, rect); | |
778 // context->drawRectToRect(*grp, rect, SkRect::MakeWH(1,1)); | |
779 return true; | |
780 } | |
781 | |
506 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, | 782 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, |
507 const SkIRect& clipBounds, | 783 const SkIRect& clipBounds, |
508 const SkMatrix& ctm, | 784 const SkMatrix& ctm, |
509 SkRect* maskRect) const { | 785 SkRect* maskRect) const { |
510 SkScalar xformedSigma = this->computeXformedSigma(ctm); | 786 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
511 if (xformedSigma <= 0) { | 787 if (xformedSigma <= 0) { |
512 return false; | 788 return false; |
513 } | 789 } |
514 | 790 |
515 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); | 791 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 } else { | 893 } else { |
618 str->append("None"); | 894 str->append("None"); |
619 } | 895 } |
620 str->append("))"); | 896 str->append("))"); |
621 } | 897 } |
622 #endif | 898 #endif |
623 | 899 |
624 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 900 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
625 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 901 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
626 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 902 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |