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 |