diff options
-rw-r--r-- | include/core/SkMaskFilter.h | 3 | ||||
-rw-r--r-- | include/effects/SkBlurMaskFilter.h | 10 | ||||
-rw-r--r-- | src/core/SkMaskFilter.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 163 | ||||
-rw-r--r-- | src/effects/SkGpuBlurUtils.cpp | 7 | ||||
-rw-r--r-- | src/effects/SkGpuBlurUtils.h | 4 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice_drawTexture.cpp | 2 | ||||
-rw-r--r-- | tests/BlurTest.cpp | 62 |
9 files changed, 60 insertions, 195 deletions
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index e30fc62548..908226c8ad 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -17,7 +17,6 @@ #include "SkStrokeRec.h" class GrClip; -class GrContext; class GrDrawContext; class GrPaint; class GrRenderTarget; @@ -123,7 +122,7 @@ public: * Try to directly render a rounded rect mask filter into the target. Returns * true if drawing was successful. */ - virtual bool directFilterRRectMaskGPU(GrContext*, + virtual bool directFilterRRectMaskGPU(GrTextureProvider* texProvider, GrDrawContext* drawContext, GrPaint* grp, const GrClip&, diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h index 4b037e70cd..3ba91774f0 100644 --- a/include/effects/SkBlurMaskFilter.h +++ b/include/effects/SkBlurMaskFilter.h @@ -65,16 +65,6 @@ public: SkScalar blurRadius); #endif - static bool ComputeBlurredRRectParams(const SkRRect& rrect, - SkScalar sigma, - SkRRect* rrectToDraw, - SkISize* widthHeight, - SkScalar xs[4], - int* numXs, - SkScalar ys[4], - int* numYs); - - SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() private: diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index 352cf71db9..fccce45a77 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -324,7 +324,7 @@ bool SkMaskFilter::canFilterMaskGPU(const SkRRect& devRRect, } -bool SkMaskFilter::directFilterRRectMaskGPU(GrContext*, +bool SkMaskFilter::directFilterRRectMaskGPU(GrTextureProvider* texProvider, GrDrawContext* drawContext, GrPaint* grp, const GrClip&, diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 31433dd2ec..4215733492 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -22,7 +22,7 @@ #include "GrTexture.h" #include "GrFragmentProcessor.h" #include "GrInvariantOutput.h" -#include "GrStyle.h" +#include "SkDraw.h" #include "effects/GrSimpleTextureEffect.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" @@ -56,7 +56,7 @@ public: const SkMatrix& viewMatrix, const SkStrokeRec& strokeRec, const SkPath& path) const override; - bool directFilterRRectMaskGPU(GrContext*, + bool directFilterRRectMaskGPU(GrTextureProvider* texProvider, GrDrawContext* drawContext, GrPaint* grp, const GrClip&, @@ -910,7 +910,7 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider, class GrRRectBlurEffect : public GrFragmentProcessor { public: - static sk_sp<GrFragmentProcessor> Make(GrContext*, float sigma, const SkRRect&); + static sk_sp<GrFragmentProcessor> Make(GrTextureProvider*, float sigma, const SkRRect&); virtual ~GrRRectBlurEffect() {}; const char* name() const override { return "GrRRectBlur"; } @@ -939,110 +939,13 @@ private: typedef GrFragmentProcessor INHERITED; }; -bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect, - SkScalar sigma, - SkRRect* rrectToDraw, - SkISize* widthHeight, - SkScalar xs[4], - int* numXs, - SkScalar ys[4], - int* numYs) { - unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f); - - const SkRect& orig = rrect.getBounds(); - const SkVector& radiiUL = rrect.radii(SkRRect::kUpperLeft_Corner); - const SkVector& radiiUR = rrect.radii(SkRRect::kUpperRight_Corner); - const SkVector& radiiLR = rrect.radii(SkRRect::kLowerRight_Corner); - const SkVector& radiiLL = rrect.radii(SkRRect::kLowerLeft_Corner); - - const int left = SkScalarCeilToInt(SkTMax<SkScalar>(radiiUL.fX, radiiLL.fX)); - const int top = SkScalarCeilToInt(SkTMax<SkScalar>(radiiUL.fY, radiiUR.fY)); - const int right = SkScalarCeilToInt(SkTMax<SkScalar>(radiiUR.fX, radiiLR.fX)); - const int bot = SkScalarCeilToInt(SkTMax<SkScalar>(radiiLL.fY, radiiLR.fY)); - - // This is a conservative check for nine-patchability - if (orig.fLeft + left + blurRadius >= orig.fRight - right - blurRadius || - orig.fTop + top + blurRadius >= orig.fBottom - bot - blurRadius) { - return false; - } - int newRRWidth, newRRHeight; - - // 3x3 case - newRRWidth = 2*blurRadius + left + right + 1; - newRRHeight = 2*blurRadius + top + bot + 1; - widthHeight->fWidth = newRRWidth + 2 * blurRadius; - widthHeight->fHeight = newRRHeight + 2 * blurRadius; - // TODO: need to return non-normalized indices - xs[0] = 0.0f; - xs[1] = (blurRadius + left) / (float) widthHeight->fWidth; - xs[2] = (blurRadius + left + 1.0f) / widthHeight->fWidth; - xs[3] = 1.0f; - *numXs = 4; - ys[0] = 0.0f; - ys[1] = (blurRadius + top) / (float) widthHeight->fHeight; - ys[2] = (blurRadius + top + 1.0f) / widthHeight->fHeight; - ys[3] = 1.0f; - *numYs = 4; - - const SkRect newRect = SkRect::MakeXYWH(SkIntToScalar(blurRadius), SkIntToScalar(blurRadius), - SkIntToScalar(newRRWidth), SkIntToScalar(newRRHeight)); - SkVector newRadii[4]; - newRadii[0] = { SkScalarCeilToScalar(radiiUL.fX), SkScalarCeilToScalar(radiiUL.fY) }; - newRadii[1] = { SkScalarCeilToScalar(radiiUR.fX), SkScalarCeilToScalar(radiiUR.fY) }; - newRadii[2] = { SkScalarCeilToScalar(radiiLR.fX), SkScalarCeilToScalar(radiiLR.fY) }; - newRadii[3] = { SkScalarCeilToScalar(radiiLL.fX), SkScalarCeilToScalar(radiiLL.fY) }; - - rrectToDraw->setRectRadii(newRect, newRadii); - return true; -} - -static sk_sp<GrTexture> make_rrect_blur_mask(GrContext* context, - const SkRRect& rrect, - float sigma) { - SkRRect rrectToDraw; - SkISize size; - SkScalar xs[4], ys[4]; - int numXs, numYs; - - SkBlurMaskFilter::ComputeBlurredRRectParams(rrect, sigma, &rrectToDraw, &size, - xs, &numXs, ys, &numYs); - - // TODO: this could be approx but the texture coords will need to be updated - sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kExact, - size.fWidth, size.fHeight, - kAlpha_8_GrPixelConfig, nullptr)); - if (!dc) { - return nullptr; - } - - GrPaint grPaint; - - dc->clear(nullptr, SK_ColorTRANSPARENT, true); - dc->drawRRect(GrNoClip(), grPaint, SkMatrix::I(), rrectToDraw, GrStyle::SimpleFill()); - - sk_sp<GrDrawContext> dc2(SkGpuBlurUtils::GaussianBlur(context, - dc->asTexture().release(), - nullptr, - SkIRect::MakeWH(size.fWidth, - size.fHeight), - nullptr, - sigma, sigma, SkBackingFit::kExact)); - if (!dc2) { - return nullptr; - } - - return dc2->asTexture(); -} - -sk_sp<GrFragmentProcessor> GrRRectBlurEffect::Make(GrContext* context, float sigma, - const SkRRect& rrect) { +sk_sp<GrFragmentProcessor> GrRRectBlurEffect::Make(GrTextureProvider* texProvider, float sigma, + const SkRRect& rrect) { if (rrect.isCircle()) { - return GrCircleBlurFragmentProcessor::Make(context->textureProvider(), - rrect.rect(), sigma); + return GrCircleBlurFragmentProcessor::Make(texProvider, rrect.rect(), sigma); } - // TODO: loosen this up if (!rrect.isSimpleCircular()) { return nullptr; } @@ -1065,17 +968,55 @@ sk_sp<GrFragmentProcessor> GrRRectBlurEffect::Make(GrContext* context, float sig builder[1] = cornerRadius; builder.finish(); - sk_sp<GrTexture> blurNinePatchTexture( - context->textureProvider()->findAndRefTextureByUniqueKey(key)); + SkAutoTUnref<GrTexture> blurNinePatchTexture(texProvider->findAndRefTextureByUniqueKey(key)); if (!blurNinePatchTexture) { - blurNinePatchTexture = make_rrect_blur_mask(context, rrect, sigma); + SkMask mask; + + unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1; + + 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, nullptr, nullptr, &mask, + SkMask::kJustRenderImage_CreateMode, SkStrokeRec::kFill_InitStyle); + + SkMask blurredMask; + if (!SkBlurMask::BoxBlur(&blurredMask, mask, sigma, kNormal_SkBlurStyle, + kHigh_SkBlurQuality, nullptr, true)) { + return nullptr; + } + + unsigned int texSide = smallRectSide + 2*blurRadius; + GrSurfaceDesc texDesc; + texDesc.fWidth = texSide; + texDesc.fHeight = texSide; + texDesc.fConfig = kAlpha_8_GrPixelConfig; + texDesc.fIsMipMapped = false; + + blurNinePatchTexture.reset( + texProvider->createTexture(texDesc, SkBudgeted::kYes , blurredMask.fImage, 0)); + SkMask::FreeImage(blurredMask.fImage); if (!blurNinePatchTexture) { return nullptr; } - context->textureProvider()->assignUniqueKeyToTexture(key, blurNinePatchTexture.get()); + texProvider->assignUniqueKeyToTexture(key, blurNinePatchTexture); } - return sk_sp<GrFragmentProcessor>(new GrRRectBlurEffect(sigma, rrect, blurNinePatchTexture.get())); + return sk_sp<GrFragmentProcessor>(new GrRRectBlurEffect(sigma, rrect, blurNinePatchTexture)); } void GrRRectBlurEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { @@ -1109,7 +1050,7 @@ sk_sp<GrFragmentProcessor> GrRRectBlurEffect::TestCreate(GrProcessorTestData* d) SkScalar sigma = d->fRandom->nextRangeF(1.f,10.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); - return GrRRectBlurEffect::Make(d->fContext, sigma, rrect); + return GrRRectBlurEffect::Make(d->fContext->textureProvider(), sigma, rrect); } ////////////////////////////////////////////////////////////////////////////// @@ -1212,7 +1153,7 @@ GrGLSLFragmentProcessor* GrRRectBlurEffect::onCreateGLSLInstance() const { return new GrGLRRectBlurEffect; } -bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, +bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvider, GrDrawContext* drawContext, GrPaint* grp, const GrClip& clip, @@ -1231,7 +1172,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); - sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma, rrect)); + sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(texProvider, xformedSigma, rrect)); if (!fp) { return false; } diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp index ebb480d3df..869cd76c5b 100644 --- a/src/effects/SkGpuBlurUtils.cpp +++ b/src/effects/SkGpuBlurUtils.cpp @@ -186,8 +186,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, const SkIRect& dstBounds, const SkIRect* srcBounds, float sigmaX, - float sigmaY, - SkBackingFit fit) { + float sigmaY) { SkASSERT(context); SkIRect clearRect; int scaleFactorX, radiusX; @@ -227,7 +226,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, const int height = dstBounds.height(); const GrPixelConfig config = srcTexture->config(); - sk_sp<GrDrawContext> dstDrawContext(context->makeDrawContext(fit, + sk_sp<GrDrawContext> dstDrawContext(context->makeDrawContext(SkBackingFit::kApprox, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); if (!dstDrawContext) { @@ -247,7 +246,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, return dstDrawContext; } - sk_sp<GrDrawContext> tmpDrawContext(context->makeDrawContext(fit, + sk_sp<GrDrawContext> tmpDrawContext(context->makeDrawContext(SkBackingFit::kApprox, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); if (!tmpDrawContext) { diff --git a/src/effects/SkGpuBlurUtils.h b/src/effects/SkGpuBlurUtils.h index a12a08873c..a5de6a242a 100644 --- a/src/effects/SkGpuBlurUtils.h +++ b/src/effects/SkGpuBlurUtils.h @@ -29,7 +29,6 @@ namespace SkGpuBlurUtils { * no pixels will be sampled outside of this rectangle. * @param sigmaX The blur's standard deviation in X. * @param sigmaY The blur's standard deviation in Y. - * @param fit backing fit for the returned draw context * @return The drawContext containing the blurred result. */ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, @@ -38,8 +37,7 @@ namespace SkGpuBlurUtils { const SkIRect& dstBounds, const SkIRect* srcBounds, float sigmaX, - float sigmaY, - SkBackingFit fit = SkBackingFit::kApprox); + float sigmaY); }; #endif diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index fb513f4483..cd34b1feba 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -436,7 +436,7 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, // clipped out return; } - if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext, + if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext->textureProvider(), fDrawContext.get(), &grPaint, fClip, diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp index e141cc2d62..2843c31996 100644 --- a/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/src/gpu/SkGpuDevice_drawTexture.cpp @@ -226,7 +226,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer, // First see if we can do the draw + mask filter direct to the dst. SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); - if (mf->directFilterRRectMaskGPU(fContext, + if (mf->directFilterRRectMaskGPU(fContext->textureProvider(), fDrawContext.get(), &grPaint, clip, diff --git a/tests/BlurTest.cpp b/tests/BlurTest.cpp index 32e2930171..6ccb0471aa 100644 --- a/tests/BlurTest.cpp +++ b/tests/BlurTest.cpp @@ -574,66 +574,4 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SmallBoxBlurBug, reporter, ctxInfo) { #endif - -DEF_TEST(BlurredRRectNinePatchComputation, reporter) { - const SkRect r = SkRect::MakeXYWH(10, 10, 100, 100); - - bool ninePatchable; - SkRRect rrectToDraw; - SkISize size; - SkScalar xs[4], ys[4]; - int numXs, numYs; - - // not nine-patchable - { - SkVector radii[4] = { { 100, 100 }, { 0, 0 }, { 100, 100 }, { 0, 0 } }; - - SkRRect rr; - rr.setRectRadii(r, radii); - - ninePatchable = SkBlurMaskFilter::ComputeBlurredRRectParams(rr, 3.0f, &rrectToDraw, &size, - xs, &numXs, ys, &numYs); - REPORTER_ASSERT(reporter, !ninePatchable); - } - - // simple circular - { - SkRRect rr; - rr.setRectXY(r, 10, 10); - - ninePatchable = SkBlurMaskFilter::ComputeBlurredRRectParams(rr, 3.0f, &rrectToDraw, &size, - xs, &numXs, ys, &numYs); - REPORTER_ASSERT(reporter, ninePatchable); - REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), 57.0f)); - REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), 57.0)); - REPORTER_ASSERT(reporter, 4 == numXs && 4 == numYs); - for (int i = 0; i < numXs; ++i) { - REPORTER_ASSERT(reporter, xs[i] >= 0.0f && xs[i] <= 1.0f); - } - for (int i = 0; i < numYs; ++i) { - REPORTER_ASSERT(reporter, ys[i] >= 0.0f && ys[i] <= 1.0f); - } - } - - // simple elliptical - { - SkRRect rr; - rr.setRectXY(r, 2, 10); - - ninePatchable = SkBlurMaskFilter::ComputeBlurredRRectParams(rr, 3.0f, &rrectToDraw, &size, - xs, &numXs, ys, &numYs); - REPORTER_ASSERT(reporter, ninePatchable); - REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fWidth), 41.0f)); - REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SkIntToScalar(size.fHeight), 57.0)); - REPORTER_ASSERT(reporter, 4 == numXs && 4 == numYs); - for (int i = 0; i < numXs; ++i) { - REPORTER_ASSERT(reporter, xs[i] >= 0.0f && xs[i] <= 1.0f); - } - for (int i = 0; i < numYs; ++i) { - REPORTER_ASSERT(reporter, ys[i] >= 0.0f && ys[i] <= 1.0f); - } - } - -} - /////////////////////////////////////////////////////////////////////////////////////////// |