diff options
author | 2014-04-28 14:44:54 +0000 | |
---|---|---|
committer | 2014-04-28 14:44:54 +0000 | |
commit | c76a4b2a81b5c502ded23dee1e0c5d762028d5cf (patch) | |
tree | 21dd269997915875e307d03f5f6bde98b20e1c9d /src/effects | |
parent | cced37d2c3e49231e6a155721e0dd59e58e67bab (diff) |
Revert of Fast path for blurred round rects -- blur a small 9patch rect on the CPU (https://codereview.chromium.org/248613004/)
Reason for revert:
Looks like this causes unit tests to fail with a zero constructor like this one: http://108.170.220.120:10117/builders/Test-Win7-ShuttleA-HD2000-x86-Release/builds/2326/steps/RunTests/logs/stdio
Original issue's description:
> Fast path for blurred round rects -- blur a small 9patch rect on the CPU
> And nonlinearly stretch the resulting texture across proxy geometry.
>
> BUG=
>
> Committed: http://code.google.com/p/skia/source/detail?r=14392
R=bsalomon@google.com, reed@google.com, humper@google.com
TBR=bsalomon@google.com, humper@google.com, reed@google.com
NOTREECHECKS=true
NOTRY=true
BUG=
Author: caryclark@google.com
Review URL: https://codereview.chromium.org/258893010
git-svn-id: http://skia.googlecode.com/svn/trunk@14400 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/SkBlurMask.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkBlurMask.h | 9 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 281 |
3 files changed, 6 insertions, 288 deletions
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp index f33817adee..9712ecc475 100644 --- a/src/effects/SkBlurMask.cpp +++ b/src/effects/SkBlurMask.cpp @@ -477,14 +477,14 @@ void SkMask_FreeImage(uint8_t* image) { bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, Style style, Quality quality, - SkIPoint* margin, bool force_quality) { + SkIPoint* margin) { if (src.fFormat != SkMask::kA8_Format) { return false; } // Force high quality off for small radii (performance) - if (!force_quality && sigma <= SkIntToScalar(2)) { + if (sigma <= SkIntToScalar(2)) { quality = kLow_Quality; } diff --git a/src/effects/SkBlurMask.h b/src/effects/SkBlurMask.h index d4cd3d1ea3..eb67d4c9f8 100644 --- a/src/effects/SkBlurMask.h +++ b/src/effects/SkBlurMask.h @@ -40,16 +40,9 @@ public: SkIPoint *margin = NULL, SkMask::CreateMode createMode = SkMask::kComputeBoundsAndRenderImage_CreateMode); - - // forceQuality will prevent BoxBlur from falling back to the low quality approach when sigma - // is very small -- this can be used predict the margin bump ahead of time without completely - // replicating the internal logic. This permits not only simpler caching of blurred results, - // but also being able to predict precisely at what pixels the blurred profile of e.g. a - // rectangle will lie. - static bool BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, Style style, Quality quality, - SkIPoint* margin = NULL, bool forceQuality = false); + SkIPoint* margin = NULL); // the "ground truth" blur does a gaussian convolution; it's slow // but useful for comparison purposes. diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 4bc48ab741..ff98daf048 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -25,7 +25,6 @@ #include "effects/GrSimpleTextureEffect.h" #include "GrTBackendEffectFactory.h" #include "SkGrPixelRef.h" -#include "SkDraw.h" #endif class SkBlurMaskFilterImpl : public SkMaskFilter { @@ -261,9 +260,9 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) { } #ifdef SK_IGNORE_FAST_RRECT_BLUR -SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" ); +SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", false, "Use the faster analytic blur approach for ninepatch rects" ); #else -SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects" ); +SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", true, "Use the faster analytic blur approach for ninepatch round rects" ); #endif SkMaskFilter::FilterReturn @@ -820,285 +819,11 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context, return true; } -class GrGLRRectBlurEffect; - -class GrRRectBlurEffect : public GrEffect { -public: - - static GrEffectRef* Create(GrContext* context, float sigma, const SkRRect&); - - virtual ~GrRRectBlurEffect() {}; - static const char* Name() { return "GrRRectBlur"; } - - const SkRRect& getRRect() const { return fRRect; } - float getSigma() const { return fSigma; } - - typedef GrGLRRectBlurEffect GLEffect; - - virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; - -private: - GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture); - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; - - SkRRect fRRect; - float fSigma; - GrTextureAccess fNinePatchAccess; - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - - -GrEffectRef* GrRRectBlurEffect::Create(GrContext* context, float sigma, const SkRRect& rrect) { - if (!rrect.isSimpleCircular()) { - SkDebugf( "not simple circular\n" ); - return NULL; - } - - // Make sure we can successfully ninepatch this rrect -- the blur sigma has to be - // sufficiently small relative to both the size of the corner radius and the - // width (and height) of the rrect. - - unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f); - unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x()); - if (cornerRadius + blurRadius > rrect.width()/2 || - cornerRadius + blurRadius > rrect.height()/2) { - return NULL; - } - - static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain(); - GrCacheID::Key key; - memset(&key, 0, sizeof(key)); - key.fData32[0] = blurRadius; - key.fData32[1] = cornerRadius; - GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key); - - GrTextureParams params; - params.setFilterMode(GrTextureParams::kBilerp_FilterMode); - - unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1; - unsigned int texSide = smallRectSide + 2*blurRadius; - GrTextureDesc texDesc; - texDesc.fWidth = texSide; - texDesc.fHeight = texSide; - texDesc.fConfig = kAlpha_8_GrPixelConfig; - - GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, ¶ms); - - if (NULL == blurNinePatchTexture) { - SkMask mask; - - mask.fBounds = SkIRect::MakeWH(smallRectSide, smallRectSide); - mask.fFormat = SkMask::kA8_Format; - mask.fRowBytes = mask.fBounds.width(); - mask.fImage = SkMask::AllocImage(mask.computeTotalImageSize()); - SkAutoMaskFreeImage amfi(mask.fImage); - - memset(mask.fImage, 0, mask.computeTotalImageSize()); - - SkRect smallRect; - smallRect.setWH(SkIntToScalar(smallRectSide), SkIntToScalar(smallRectSide)); - - SkRRect smallRRect; - smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius)); - - SkPath path; - path.addRRect( smallRRect ); - - SkDraw::DrawToMask(path, &mask.fBounds, NULL, NULL, &mask, SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style); - - SkMask blurred_mask; - SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, SkBlurMask::kNormal_Style, SkBlurMask::kHigh_Quality, NULL, true ); - - blurNinePatchTexture = context->createTexture(¶ms, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0); - } - - if (NULL == blurNinePatchTexture) { - return NULL; - } - - return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrRRectBlurEffect, - (sigma, rrect, blurNinePatchTexture)))); -} - -void GrRRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { - *validFlags = 0; -} - -const GrBackendEffectFactory& GrRRectBlurEffect::getFactory() const { - return GrTBackendEffectFactory<GrRRectBlurEffect>::getInstance(); -} - -GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture) - : fRRect(rrect), - fSigma(sigma), - fNinePatchAccess(ninePatchTexture) { - this->addTextureAccess(&fNinePatchAccess); - this->setWillReadFragmentPosition(); -} - -bool GrRRectBlurEffect::onIsEqual(const GrEffect& other) const { - const GrRRectBlurEffect& rrbe = CastEffect<GrRRectBlurEffect>(other); - return fRRect.getSimpleRadii().fX == rrbe.fRRect.getSimpleRadii().fX && fSigma == rrbe.fSigma; -} - -////////////////////////////////////////////////////////////////////////////// - -GR_DEFINE_EFFECT_TEST(GrRRectBlurEffect); - -GrEffectRef* GrRRectBlurEffect::TestCreate(SkRandom* random, - GrContext* context, - const GrDrawTargetCaps& caps, - GrTexture*[]) { - SkScalar w = random->nextRangeScalar(20.f, 1000.f); - SkScalar h = random->nextRangeScalar(20.f, 1000.f); - SkScalar r = random->nextRangeF(1.f, 9.f); - SkScalar sigma = random->nextRangeF(1.f,20.f); - SkRRect rrect; - rrect.setRectXY(SkRect::MakeWH(w, h), r, r); - return GrRRectBlurEffect::Create(context, sigma, rrect); -} - -////////////////////////////////////////////////////////////////////////////// - -class GrGLRRectBlurEffect : public GrGLEffect { -public: - GrGLRRectBlurEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TransformedCoordsArray&, - const TextureSamplerArray&) SK_OVERRIDE; - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; - -private: - GrGLUniformManager::UniformHandle fProxyRectUniform; - GrGLUniformManager::UniformHandle fCornerRadiusUniform; - GrGLUniformManager::UniformHandle fBlurRadiusUniform; - typedef GrGLEffect INHERITED; -}; - -GrGLRRectBlurEffect::GrGLRRectBlurEffect(const GrBackendEffectFactory& factory, - const GrDrawEffect& drawEffect) - : INHERITED (factory) { -} - -void GrGLRRectBlurEffect::emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TransformedCoordsArray&, - const TextureSamplerArray& samplers) { - const char *rectName; - const char *cornerRadiusName; - const char *blurRadiusName; - - // The proxy rect has left, top, right, and bottom edges correspond to - // components x, y, z, and w, respectively. - - fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, - kVec4f_GrSLType, - "proxyRect", - &rectName); - fCornerRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, - kFloat_GrSLType, - "cornerRadius", - &cornerRadiusName); - fBlurRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, - kFloat_GrSLType, - "blurRadius", - &blurRadiusName); - const char* fragmentPos = builder->fragmentPosition(); - - // warp the fragment position to the appropriate part of the 9patch blur texture - - builder->fsCodeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName); - builder->fsCodeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName); - builder->fsCodeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName ); - builder->fsCodeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName ); - - builder->fsCodeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" ); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n"); - builder->fsCodeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n"); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x -= middle.x;\n"); - builder->fsCodeAppendf("\t\t}\n"); - - builder->fsCodeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" ); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n"); - builder->fsCodeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n"); - builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y -= middle.y;\n"); - builder->fsCodeAppendf("\t\t}\n"); - - builder->fsCodeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n"); - builder->fsCodeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n"); - - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->fsAppendTextureLookupAndModulate(inputColor, samplers[0], "texCoord"); - builder->fsCodeAppend(";\n"); -} - -void GrGLRRectBlurEffect::setData(const GrGLUniformManager& uman, - const GrDrawEffect& drawEffect) { - const GrRRectBlurEffect& brre = drawEffect.castEffect<GrRRectBlurEffect>(); - SkRRect rrect = brre.getRRect(); - - float blurRadius = 3.f*SkScalarCeilToScalar(brre.getSigma()-1/6.0f); - uman.set1f(fBlurRadiusUniform, blurRadius); - - SkRect rect = rrect.getBounds(); - rect.outset(blurRadius, blurRadius); - uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); - - SkScalar radius = 0; - SkASSERT(rrect.isSimpleCircular() || rrect.isRect()); - radius = rrect.getSimpleRadii().fX; - uman.set1f(fCornerRadiusUniform, radius); -} - - bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, GrPaint* grp, const SkStrokeRec& strokeRec, const SkRRect& rrect) const { - if (fBlurStyle != SkBlurMaskFilter::kNormal_BlurStyle) { - return false; - } - - if (!strokeRec.isFillStyle()) { - return false; - } - - SkRect proxy_rect = rrect.rect(); - SkMatrix ctm = context->getMatrix(); - SkScalar xformedSigma = this->computeXformedSigma(ctm); - float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); - proxy_rect.outset(extra, extra); - - SkAutoTUnref<GrEffectRef> effect(GrRRectBlurEffect::Create( - context, xformedSigma, rrect)); - if (!effect) { - return false; - } - - GrContext::AutoMatrix am; - if (!am.setIdentity(context, grp)) { - return false; - } - - grp->addCoverageEffect(effect); - - context->drawRect(*grp, proxy_rect); - return true; + return false; } bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, |