From f054b1766b96d270b98efd9afc87835d299d4a4e Mon Sep 17 00:00:00 2001 From: robertphillips Date: Fri, 13 May 2016 05:06:19 -0700 Subject: Swap SkGpuBlurUtils over to using SkIRects We don't have to land this, but I found it more comforting for the blurring code to explicitly deal with SkIRects rather than SkRects with integer values. Split out of: https://codereview.chromium.org/1959493002/ (Retract GrRenderTarget from SkGpuBlurUtils) GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1968603003 Review-Url: https://codereview.chromium.org/1968603003 --- include/core/SkMaskFilter.h | 2 +- include/core/SkScalar.h | 1 + src/core/SkMaskFilter.cpp | 2 +- src/effects/SkBlurImageFilter.cpp | 5 +- src/effects/SkBlurMaskFilter.cpp | 9 +- src/effects/SkGpuBlurUtils.cpp | 175 +++++++++++++++++++++----------------- src/effects/SkGpuBlurUtils.h | 5 +- src/gpu/GrBlurUtils.cpp | 35 ++++---- 8 files changed, 124 insertions(+), 110 deletions(-) diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index a07cb6c49f..fbd749e837 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -140,7 +140,7 @@ public: */ virtual bool filterMaskGPU(GrTexture* src, const SkMatrix& ctm, - const SkRect& maskRect, + const SkIRect& maskRect, GrTexture** result, bool canOverwriteSrc) const; #endif diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h index b2d966cb3b..922840fd1a 100644 --- a/include/core/SkScalar.h +++ b/include/core/SkScalar.h @@ -101,6 +101,7 @@ typedef double SkScalar; ////////////////////////////////////////////////////////////////////////////////////////////////// #define SkIntToScalar(x) static_cast(x) +#define SkIntToFloat(x) static_cast(x) #define SkScalarTruncToInt(x) static_cast(x) #define SkScalarToFloat(x) static_cast(x) diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index 8f8e70901f..86fc40ebac 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -336,7 +336,7 @@ bool SkMaskFilter::directFilterRRectMaskGPU(GrTextureProvider* texProvider, bool SkMaskFilter::filterMaskGPU(GrTexture* src, const SkMatrix& ctm, - const SkRect& maskRect, + const SkIRect& maskRect, GrTexture** result, bool canOverwriteSrc) const { return false; diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index 0625d37a42..39b58b856e 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -120,13 +120,12 @@ sk_sp SkBlurImageFilter::onFilterImage(SkSpecialImage* source, offset->fY = dstBounds.fTop; inputBounds.offset(-inputOffset); dstBounds.offset(-inputOffset); - SkRect inputBoundsF(SkRect::Make(inputBounds)); sk_sp drawContext(SkGpuBlurUtils::GaussianBlur( context, inputTexture.get(), source->props().isGammaCorrect(), - SkRect::Make(dstBounds), - &inputBoundsF, + dstBounds, + &inputBounds, sigma.x(), sigma.y())); if (!drawContext) { diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index a2d67d74af..7f076d6ca5 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -66,7 +66,7 @@ public: const SkRRect& rrect) const override; bool filterMaskGPU(GrTexture* src, const SkMatrix& ctm, - const SkRect& maskRect, + const SkIRect& maskRect, GrTexture** result, bool canOverwriteSrc) const override; #endif @@ -1235,10 +1235,11 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, const SkMatrix& ctm, - const SkRect& maskRect, + const SkIRect& maskRect, GrTexture** result, bool canOverwriteSrc) const { - SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); + // 'maskRect' isn't snapped to the UL corner but the mask in 'src' is. + const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height()); GrContext* context = src->getContext(); @@ -1277,7 +1278,7 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); } - drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), clipRect); + drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), SkRect::Make(clipRect)); } *result = drawContext->asTexture().release(); diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp index c157a6e2e6..de19d4372c 100644 --- a/src/effects/SkGpuBlurUtils.cpp +++ b/src/effects/SkGpuBlurUtils.cpp @@ -15,19 +15,38 @@ #include "GrContext.h" #include "GrCaps.h" #include "GrDrawContext.h" -#endif -namespace SkGpuBlurUtils { +#define MAX_BLUR_SIGMA 4.0f -#if SK_SUPPORT_GPU +static void scale_irect_roundout(SkIRect* rect, float xScale, float yScale) { + rect->fLeft = SkScalarFloorToInt(SkScalarMul(rect->fLeft, xScale)); + rect->fTop = SkScalarFloorToInt(SkScalarMul(rect->fTop, yScale)); + rect->fRight = SkScalarCeilToInt(SkScalarMul(rect->fRight, xScale)); + rect->fBottom = SkScalarCeilToInt(SkScalarMul(rect->fBottom, yScale)); +} -#define MAX_BLUR_SIGMA 4.0f +static void scale_irect(SkIRect* rect, int xScale, int yScale) { + rect->fLeft *= xScale; + rect->fTop *= yScale; + rect->fRight *= xScale; + rect->fBottom *= yScale; +} + +#ifdef SK_DEBUG +static inline int is_even(int x) { return !(x & 1); } +#endif -static void scale_rect(SkRect* rect, float xScale, float yScale) { - rect->fLeft = SkScalarMul(rect->fLeft, xScale); - rect->fTop = SkScalarMul(rect->fTop, yScale); - rect->fRight = SkScalarMul(rect->fRight, xScale); - rect->fBottom = SkScalarMul(rect->fBottom, yScale); +static void shrink_irect_by_2(SkIRect* rect, bool xAxis, bool yAxis) { + if (xAxis) { + SkASSERT(is_even(rect->fLeft) && is_even(rect->fRight)); + rect->fLeft /= 2; + rect->fRight /= 2; + } + if (yAxis) { + SkASSERT(is_even(rect->fTop) && is_even(rect->fBottom)); + rect->fTop /= 2; + rect->fBottom /= 2; + } } static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) { @@ -47,8 +66,8 @@ static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int static void convolve_gaussian_1d(GrDrawContext* drawContext, const GrClip& clip, - const SkRect& dstRect, - const SkPoint& srcOffset, + const SkIRect& dstRect, + const SkIPoint& srcOffset, GrTexture* texture, Gr1DKernelEffect::Direction direction, int radius, @@ -61,31 +80,29 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext, texture, direction, radius, sigma, useBounds, bounds)); paint.addColorFragmentProcessor(conv); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); - drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix); + SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), + -SkIntToScalar(srcOffset.y())); + drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), + SkRect::Make(dstRect), localMatrix); } static void convolve_gaussian_2d(GrDrawContext* drawContext, const GrClip& clip, - const SkRect& dstRect, - const SkPoint& srcOffset, + const SkIRect& dstRect, + const SkIPoint& srcOffset, GrTexture* texture, int radiusX, int radiusY, SkScalar sigmaX, SkScalar sigmaY, - const SkRect* srcBounds) { - SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); + const SkIRect* srcBounds) { + SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), + -SkIntToScalar(srcOffset.y())); SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); GrPaint paint; paint.setGammaCorrect(drawContext->isGammaCorrect()); - SkIRect bounds; - if (srcBounds) { - srcBounds->roundOut(&bounds); - } else { - bounds.setEmpty(); - } + SkIRect bounds = srcBounds ? *srcBounds : SkIRect::EmptyIRect(); SkAutoTUnref conv(GrMatrixConvolutionEffect::CreateGaussian( texture, bounds, size, 1.0, 0.0, kernelOffset, @@ -93,51 +110,49 @@ static void convolve_gaussian_2d(GrDrawContext* drawContext, true, sigmaX, sigmaY)); paint.addColorFragmentProcessor(conv); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix); + drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), + SkRect::Make(dstRect), localMatrix); } static void convolve_gaussian(GrDrawContext* drawContext, const GrClip& clip, - const SkRect& srcRect, + const SkIRect& srcRect, GrTexture* texture, Gr1DKernelEffect::Direction direction, int radius, float sigma, - const SkRect* srcBounds, - const SkPoint& srcOffset) { + const SkIRect* srcBounds, + const SkIPoint& srcOffset) { float bounds[2] = { 0.0f, 1.0f }; - SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); + SkIRect dstRect = SkIRect::MakeWH(srcRect.width(), srcRect.height()); if (!srcBounds) { convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, direction, radius, sigma, false, bounds); return; } - SkRect midRect = *srcBounds, leftRect, rightRect; + SkIRect midRect = *srcBounds, leftRect, rightRect; midRect.offset(srcOffset); SkIRect topRect, bottomRect; - SkScalar rad = SkIntToScalar(radius); if (direction == Gr1DKernelEffect::kX_Direction) { - bounds[0] = SkScalarToFloat(srcBounds->left()) / texture->width(); - bounds[1] = SkScalarToFloat(srcBounds->right()) / texture->width(); - SkRect::MakeLTRB(0, 0, dstRect.right(), midRect.top()).roundOut(&topRect); - SkRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dstRect.bottom()) - .roundOut(&bottomRect); - midRect.inset(rad, 0); - leftRect = SkRect::MakeLTRB(0, midRect.top(), midRect.left(), midRect.bottom()); + bounds[0] = SkIntToFloat(srcBounds->left()) / texture->width(); + bounds[1] = SkIntToFloat(srcBounds->right()) / texture->width(); + topRect = SkIRect::MakeLTRB(0, 0, dstRect.right(), midRect.top()); + bottomRect = SkIRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dstRect.bottom()); + midRect.inset(radius, 0); + leftRect = SkIRect::MakeLTRB(0, midRect.top(), midRect.left(), midRect.bottom()); rightRect = - SkRect::MakeLTRB(midRect.right(), midRect.top(), dstRect.width(), midRect.bottom()); + SkIRect::MakeLTRB(midRect.right(), midRect.top(), dstRect.width(), midRect.bottom()); dstRect.fTop = midRect.top(); dstRect.fBottom = midRect.bottom(); } else { - bounds[0] = SkScalarToFloat(srcBounds->top()) / texture->height(); - bounds[1] = SkScalarToFloat(srcBounds->bottom()) / texture->height(); - SkRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom()).roundOut(&topRect); - SkRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstRect.bottom()) - .roundOut(&bottomRect);; - midRect.inset(0, rad); - leftRect = SkRect::MakeLTRB(midRect.left(), 0, midRect.right(), midRect.top()); + bounds[0] = SkIntToFloat(srcBounds->top()) / texture->height(); + bounds[1] = SkIntToFloat(srcBounds->bottom()) / texture->height(); + topRect = SkIRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom()); + bottomRect = SkIRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstRect.bottom()); + midRect.inset(0, radius); + leftRect = SkIRect::MakeLTRB(midRect.left(), 0, midRect.right(), midRect.top()); rightRect = - SkRect::MakeLTRB(midRect.left(), midRect.bottom(), midRect.right(), dstRect.height()); + SkIRect::MakeLTRB(midRect.left(), midRect.bottom(), midRect.right(), dstRect.height()); dstRect.fLeft = midRect.left(); dstRect.fRight = midRect.right(); } @@ -151,7 +166,7 @@ static void convolve_gaussian(GrDrawContext* drawContext, if (midRect.isEmpty()) { // Blur radius covers srcBounds; use bounds over entire draw convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, - direction, radius, sigma, true, bounds); + direction, radius, sigma, true, bounds); } else { // Draw right and left margins with bounds; middle without. convolve_gaussian_1d(drawContext, clip, leftRect, srcOffset, texture, @@ -163,11 +178,13 @@ static void convolve_gaussian(GrDrawContext* drawContext, } } +namespace SkGpuBlurUtils { + sk_sp GaussianBlur(GrContext* context, GrTexture* origSrc, bool gammaCorrect, - const SkRect& dstBounds, - const SkRect* srcBounds, + const SkIRect& dstBounds, + const SkIRect* srcBounds, float sigmaX, float sigmaY) { SkASSERT(context); @@ -177,11 +194,12 @@ sk_sp GaussianBlur(GrContext* context, int maxTextureSize = context->caps()->maxTextureSize(); sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); + SkASSERT(sigmaX || sigmaY); - SkPoint srcOffset = SkPoint::Make(-dstBounds.x(), -dstBounds.y()); - SkRect localDstBounds = SkRect::MakeWH(dstBounds.width(), dstBounds.height()); - SkRect localSrcBounds; - SkRect srcRect; + SkIPoint srcOffset = SkIPoint::Make(-dstBounds.x(), -dstBounds.y()); + SkIRect localDstBounds = SkIRect::MakeWH(dstBounds.width(), dstBounds.height()); + SkIRect localSrcBounds; + SkIRect srcRect; if (srcBounds) { srcRect = localSrcBounds = *srcBounds; srcRect.offset(srcOffset); @@ -190,10 +208,8 @@ sk_sp GaussianBlur(GrContext* context, srcRect = localDstBounds; } - scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); - srcRect.roundOut(&srcRect); - scale_rect(&srcRect, static_cast(scaleFactorX), - static_cast(scaleFactorY)); + scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); + scale_irect(&srcRect, scaleFactorX, scaleFactorY); // setup new clip GrClip clip(localDstBounds); @@ -206,8 +222,8 @@ sk_sp GaussianBlur(GrContext* context, kSBGRA_8888_GrPixelConfig == srcTexture->config() || kAlpha_8_GrPixelConfig == srcTexture->config()); - const int width = SkScalarFloorToInt(dstBounds.width()); - const int height = SkScalarFloorToInt(dstBounds.height()); + const int width = dstBounds.width(); + const int height = dstBounds.height(); const GrPixelConfig config = srcTexture->config(); const SkSurfaceProps props(gammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag : 0, @@ -244,15 +260,17 @@ sk_sp GaussianBlur(GrContext* context, sk_sp srcDrawContext; + SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY)); + for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { GrPaint paint; paint.setGammaCorrect(gammaCorrect); SkMatrix matrix; matrix.setIDiv(srcTexture->width(), srcTexture->height()); - SkRect dstRect(srcRect); + SkIRect dstRect(srcRect); if (srcBounds && i == 1) { SkRect domain; - matrix.mapRect(&domain, *srcBounds); + matrix.mapRect(&domain, SkRect::Make(*srcBounds)); domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width() : 0.0f, (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height() : 0.0f); sk_sp fp(GrTextureDomainEffect::Create( @@ -269,10 +287,10 @@ sk_sp GaussianBlur(GrContext* context, paint.addColorTextureProcessor(srcTexture.get(), matrix, params); } paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, - i < scaleFactorY ? 0.5f : 1.0f); + shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); - dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); + dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), + SkRect::Make(dstRect), SkRect::Make(srcRect)); srcDrawContext = dstDrawContext; srcRect = dstRect; @@ -282,18 +300,15 @@ sk_sp GaussianBlur(GrContext* context, } srcRect = localDstBounds; - - scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); - srcRect.roundOut(&srcRect); - SkIRect srcIRect = srcRect.roundOut(); + scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); if (sigmaX > 0.0f) { if (scaleFactorX > 1) { SkASSERT(srcDrawContext); // Clear out a radius to the right of the srcRect to prevent the // X convolution from reading garbage. - clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, - radiusX, srcIRect.height()); + clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, + radiusX, srcRect.height()); srcDrawContext->clear(&clearRect, 0x0, false); } @@ -314,8 +329,8 @@ sk_sp GaussianBlur(GrContext* context, // Clear out a radius below the srcRect to prevent the Y // convolution from reading garbage. - clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, - srcIRect.width(), radiusY); + clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, + srcRect.width(), radiusY); srcDrawContext->clear(&clearRect, 0x0, false); } @@ -330,13 +345,12 @@ sk_sp GaussianBlur(GrContext* context, SkASSERT(srcDrawContext); srcTexture = nullptr; // we don't use this from here on out - srcIRect = srcRect.roundOut(); if (scaleFactorX > 1 || scaleFactorY > 1) { // Clear one pixel to the right and below, to accommodate bilinear upsampling. - clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, srcIRect.width() + 1, 1); + clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1); srcDrawContext->clear(&clearRect, 0x0, false); - clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 1, srcIRect.height()); + clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.height()); srcDrawContext->clear(&clearRect, 0x0, false); SkMatrix matrix; @@ -350,10 +364,11 @@ sk_sp GaussianBlur(GrContext* context, paint.addColorTextureProcessor(tex.get(), matrix, params); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); - SkRect dstRect(srcRect); - scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); + SkIRect dstRect(srcRect); + scale_irect(&dstRect, scaleFactorX, scaleFactorY); - dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); + dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), + SkRect::Make(dstRect), SkRect::Make(srcRect)); srcDrawContext = dstDrawContext; srcRect = dstRect; @@ -362,6 +377,8 @@ sk_sp GaussianBlur(GrContext* context, return srcDrawContext; } -#endif } + +#endif + diff --git a/src/effects/SkGpuBlurUtils.h b/src/effects/SkGpuBlurUtils.h index 0d37f158be..4f80fc3114 100644 --- a/src/effects/SkGpuBlurUtils.h +++ b/src/effects/SkGpuBlurUtils.h @@ -34,11 +34,10 @@ namespace SkGpuBlurUtils { sk_sp GaussianBlur(GrContext* context, GrTexture* srcTexture, bool gammaCorrect, - const SkRect& dstBounds, - const SkRect* srcBounds, + const SkIRect& dstBounds, + const SkIRect* srcBounds, float sigmaX, float sigmaY); - }; #endif diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp index 0a8351fd07..40bd6f973b 100644 --- a/src/gpu/GrBlurUtils.cpp +++ b/src/gpu/GrBlurUtils.cpp @@ -28,11 +28,11 @@ static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r static bool draw_mask(GrDrawContext* drawContext, const GrClip& clip, const SkMatrix& viewMatrix, - const SkRect& maskRect, + const SkIRect& maskRect, GrPaint* grp, GrTexture* mask) { SkMatrix matrix; - matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop); + matrix.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop)); matrix.postIDiv(mask->width(), mask->height()); grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(mask, matrix, @@ -42,7 +42,8 @@ static bool draw_mask(GrDrawContext* drawContext, if (!viewMatrix.invert(&inverse)) { return false; } - drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), maskRect, inverse); + drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), + SkRect::Make(maskRect), inverse); return true; } @@ -86,23 +87,16 @@ static bool sw_draw_with_mask_filter(GrDrawContext* drawContext, texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, dstM.fImage, dstM.fRowBytes); - SkRect maskRect = SkRect::Make(dstM.fBounds); - - return draw_mask(drawContext, clipData, viewMatrix, maskRect, grp, texture); + return draw_mask(drawContext, clipData, viewMatrix, dstM.fBounds, grp, texture); } // Create a mask of 'devPath' and place the result in 'mask'. static sk_sp create_mask_GPU(GrContext* context, - SkRect* maskRect, + const SkIRect& maskRect, const SkPath& devPath, SkStrokeRec::InitStyle fillOrHairline, bool doAA, int sampleCnt) { - // This mask will ultimately be drawn as a non-AA rect (see draw_mask). - // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here - // so the mask draws in a reproducible manner. - *maskRect = SkRect::Make(maskRect->roundOut()); - if (!doAA) { // Don't need MSAA if mask isn't AA sampleCnt = 0; @@ -116,8 +110,8 @@ static sk_sp create_mask_GPU(GrContext* context, } sk_sp drawContext(context->newDrawContext(SkBackingFit::kApprox, - SkScalarCeilToInt(maskRect->width()), - SkScalarCeilToInt(maskRect->height()), + maskRect.width(), + maskRect.height(), config, sampleCnt)); if (!drawContext) { @@ -131,13 +125,13 @@ static sk_sp create_mask_GPU(GrContext* context, tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); // setup new clip - const SkRect clipRect = SkRect::MakeWH(maskRect->width(), maskRect->height()); + const SkRect clipRect = SkRect::MakeIWH(maskRect.width(), maskRect.height()); GrClip clip(clipRect); // Draw the mask into maskTexture with the path's integerized top-left at // the origin using tempPaint. SkMatrix translate; - translate.setTranslate(-maskRect->fLeft, -maskRect->fTop); + translate.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop)); drawContext->drawPath(clip, tempPaint, translate, devPath, GrStyle(fillOrHairline)); return drawContext->asTexture();; } @@ -195,6 +189,9 @@ static void draw_path_with_mask_filter(GrContext* context, clipBounds, viewMatrix, &maskRect)) { + // This mask will ultimately be drawn as a non-AA rect (see draw_mask). + // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here + // so the mask draws in a reproducible manner. SkIRect finalIRect; maskRect.roundOut(&finalIRect); if (clip_bounds_quick_reject(clipBounds, finalIRect)) { @@ -215,7 +212,7 @@ static void draw_path_with_mask_filter(GrContext* context, } sk_sp mask(create_mask_GPU(context, - &maskRect, + finalIRect, *path, fillOrHairline, paint->isAntiAlias(), @@ -223,10 +220,10 @@ static void draw_path_with_mask_filter(GrContext* context, if (mask) { GrTexture* filtered; - if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, maskRect, &filtered, true)) { + if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, finalIRect, &filtered, true)) { // filterMaskGPU gives us ownership of a ref to the result SkAutoTUnref atu(filtered); - if (draw_mask(drawContext, clip, viewMatrix, maskRect, paint, filtered)) { + if (draw_mask(drawContext, clip, viewMatrix, finalIRect, paint, filtered)) { // This path is completely drawn return; } -- cgit v1.2.3