diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp index 1a0515bd00..6f7a2e39a1 100644 --- a/src/core/SkBlurImageFilter.cpp +++ b/src/core/SkBlurImageFilter.cpp @@ -141,7 +141,7 @@ sk_sp SkBlurImageFilterImpl::onFilterImage(SkSpecialImage* sourc // xform during the filter itself. input = ImageToColorSpace(input.get(), ctx.outputProperties()); - sk_sp inputTexture(input->asTextureProxy(context)); + sk_sp inputTexture(input->asTextureRef(context)); if (!inputTexture) { return nullptr; } @@ -163,7 +163,7 @@ sk_sp SkBlurImageFilterImpl::onFilterImage(SkSpecialImage* sourc // have the same gamut, so in this case, we do everything in the input's color space. sk_sp renderTargetContext(SkGpuBlurUtils::GaussianBlur( context, - std::move(inputTexture), + inputTexture.get(), sk_ref_sp(input->getColorSpace()), dstBounds, &inputBounds, diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp index d58582da46..d7522ca726 100644 --- a/src/core/SkGpuBlurUtils.cpp +++ b/src/core/SkGpuBlurUtils.cpp @@ -66,21 +66,20 @@ static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int return sigma; } -static void convolve_gaussian_1d(GrContext* context, - GrRenderTargetContext* renderTargetContext, +static void convolve_gaussian_1d(GrRenderTargetContext* renderTargetContext, const GrClip& clip, const SkIRect& dstRect, const SkIPoint& srcOffset, - sk_sp proxy, + GrTexture* texture, Gr1DKernelEffect::Direction direction, int radius, float sigma, bool useBounds, - int bounds[2]) { + float bounds[2]) { GrPaint paint; paint.setGammaCorrect(renderTargetContext->isGammaCorrect()); sk_sp conv(GrGaussianConvolutionFragmentProcessor::Make( - context, std::move(proxy), direction, radius, sigma, useBounds, bounds)); + texture, direction, radius, sigma, useBounds, bounds)); paint.addColorFragmentProcessor(std::move(conv)); paint.setPorterDuffXPFactory(SkBlendMode::kSrc); SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), @@ -89,12 +88,11 @@ static void convolve_gaussian_1d(GrContext* context, SkRect::Make(dstRect), localMatrix); } -static void convolve_gaussian_2d(GrContext* context, - GrRenderTargetContext* renderTargetContext, +static void convolve_gaussian_2d(GrRenderTargetContext* renderTargetContext, const GrClip& clip, const SkIRect& dstRect, const SkIPoint& srcOffset, - sk_sp proxy, + GrTexture* texture, int radiusX, int radiusY, SkScalar sigmaX, @@ -109,7 +107,7 @@ static void convolve_gaussian_2d(GrContext* context, SkIRect bounds = srcBounds ? *srcBounds : SkIRect::EmptyIRect(); sk_sp conv(GrMatrixConvolutionEffect::MakeGaussian( - context, std::move(proxy), bounds, size, 1.0, 0.0, kernelOffset, + texture, bounds, size, 1.0, 0.0, kernelOffset, srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode, true, sigmaX, sigmaY)); paint.addColorFragmentProcessor(std::move(conv)); @@ -118,29 +116,28 @@ static void convolve_gaussian_2d(GrContext* context, SkRect::Make(dstRect), localMatrix); } -static void convolve_gaussian(GrContext* context, - GrRenderTargetContext* renderTargetContext, +static void convolve_gaussian(GrRenderTargetContext* renderTargetContext, const GrClip& clip, const SkIRect& srcRect, - sk_sp proxy, + GrTexture* texture, Gr1DKernelEffect::Direction direction, int radius, float sigma, const SkIRect* srcBounds, const SkIPoint& srcOffset) { - int bounds[2] = { 0, 0 }; + float bounds[2] = { 0.0f, 1.0f }; SkIRect dstRect = SkIRect::MakeWH(srcRect.width(), srcRect.height()); if (!srcBounds) { - convolve_gaussian_1d(context, renderTargetContext, clip, dstRect, srcOffset, - std::move(proxy), direction, radius, sigma, false, bounds); + convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset, texture, + direction, radius, sigma, false, bounds); return; } SkIRect midRect = *srcBounds, leftRect, rightRect; midRect.offset(srcOffset); SkIRect topRect, bottomRect; if (direction == Gr1DKernelEffect::kX_Direction) { - bounds[0] = srcBounds->left(); - bounds[1] = srcBounds->right(); + 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); @@ -150,8 +147,8 @@ static void convolve_gaussian(GrContext* context, dstRect.fTop = midRect.top(); dstRect.fBottom = midRect.bottom(); } else { - bounds[0] = srcBounds->top(); - bounds[1] = srcBounds->bottom(); + 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); @@ -170,23 +167,23 @@ static void convolve_gaussian(GrContext* context, } if (midRect.isEmpty()) { // Blur radius covers srcBounds; use bounds over entire draw - convolve_gaussian_1d(context, renderTargetContext, clip, dstRect, srcOffset, - std::move(proxy), direction, radius, sigma, true, bounds); + convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset, texture, + direction, radius, sigma, true, bounds); } else { // Draw right and left margins with bounds; middle without. - convolve_gaussian_1d(context, renderTargetContext, clip, leftRect, srcOffset, - proxy, direction, radius, sigma, true, bounds); - convolve_gaussian_1d(context, renderTargetContext, clip, rightRect, srcOffset, - proxy, direction, radius, sigma, true, bounds); - convolve_gaussian_1d(context, renderTargetContext, clip, midRect, srcOffset, - std::move(proxy), direction, radius, sigma, false, bounds); + convolve_gaussian_1d(renderTargetContext, clip, leftRect, srcOffset, texture, + direction, radius, sigma, true, bounds); + convolve_gaussian_1d(renderTargetContext, clip, rightRect, srcOffset, texture, + direction, radius, sigma, true, bounds); + convolve_gaussian_1d(renderTargetContext, clip, midRect, srcOffset, texture, + direction, radius, sigma, false, bounds); } } namespace SkGpuBlurUtils { sk_sp GaussianBlur(GrContext* context, - sk_sp srcProxy, + GrTexture* origSrc, sk_sp colorSpace, const SkIRect& dstBounds, const SkIRect* srcBounds, @@ -220,14 +217,18 @@ sk_sp GaussianBlur(GrContext* context, // setup new clip GrFixedClip clip(localDstBounds); - const GrPixelConfig config = srcProxy->config(); + sk_sp srcTexture(sk_ref_sp(origSrc)); - SkASSERT(kBGRA_8888_GrPixelConfig == config || kRGBA_8888_GrPixelConfig == config || - kSRGBA_8888_GrPixelConfig == config || kSBGRA_8888_GrPixelConfig == config || - kRGBA_half_GrPixelConfig == config || kAlpha_8_GrPixelConfig == config); + SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || + kRGBA_8888_GrPixelConfig == srcTexture->config() || + kSRGBA_8888_GrPixelConfig == srcTexture->config() || + kSBGRA_8888_GrPixelConfig == srcTexture->config() || + kRGBA_half_GrPixelConfig == srcTexture->config() || + kAlpha_8_GrPixelConfig == srcTexture->config()); const int width = dstBounds.width(); const int height = dstBounds.height(); + const GrPixelConfig config = srcTexture->config(); sk_sp dstRenderTargetContext(context->makeDeferredRenderTargetContext( fit, width, height, config, colorSpace, 0, kBottomLeft_GrSurfaceOrigin)); @@ -242,8 +243,8 @@ sk_sp GaussianBlur(GrContext* context, // We shouldn't be scaling because this is a small size blur SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); - convolve_gaussian_2d(context, dstRenderTargetContext.get(), clip, localDstBounds, srcOffset, - std::move(srcProxy), radiusX, radiusY, sigmaX, sigmaY, srcBounds); + convolve_gaussian_2d(dstRenderTargetContext.get(), clip, localDstBounds, srcOffset, + srcTexture.get(), radiusX, radiusY, sigmaX, sigmaY, srcBounds); return dstRenderTargetContext; } @@ -267,8 +268,7 @@ sk_sp GaussianBlur(GrContext* context, domain.inset((i < scaleFactorX) ? SK_ScalarHalf : 0.0f, (i < scaleFactorY) ? SK_ScalarHalf : 0.0f); sk_sp fp(GrTextureDomainEffect::Make( - context, - std::move(srcProxy), + srcTexture.get(), nullptr, SkMatrix::I(), domain, @@ -279,8 +279,7 @@ sk_sp GaussianBlur(GrContext* context, srcOffset.set(0, 0); } else { GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode); - paint.addColorTextureProcessor(context, std::move(srcProxy), nullptr, - SkMatrix::I(), params); + paint.addColorTextureProcessor(srcTexture.get(), nullptr, SkMatrix::I(), params); } paint.setPorterDuffXPFactory(SkBlendMode::kSrc); shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); @@ -290,8 +289,8 @@ sk_sp GaussianBlur(GrContext* context, srcRenderTargetContext = dstRenderTargetContext; srcRect = dstRect; - srcProxy = sk_ref_sp(srcRenderTargetContext->asDeferredTexture()); - if (!srcProxy) { + srcTexture = srcRenderTargetContext->asTexture(); + if (!srcTexture) { return nullptr; } dstRenderTargetContext.swap(tmpRenderTargetContext); @@ -311,12 +310,12 @@ sk_sp GaussianBlur(GrContext* context, srcRenderTargetContext->priv().absClear(&clearRect, 0x0); } - convolve_gaussian(context, dstRenderTargetContext.get(), clip, srcRect, - std::move(srcProxy), Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, + convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, + srcTexture.get(), Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, srcBounds, srcOffset); srcRenderTargetContext = dstRenderTargetContext; - srcProxy = sk_ref_sp(srcRenderTargetContext->asDeferredTexture()); - if (!srcProxy) { + srcTexture = srcRenderTargetContext->asTexture(); + if (!srcTexture) { return nullptr; } srcRect.offsetTo(0, 0); @@ -336,8 +335,8 @@ sk_sp GaussianBlur(GrContext* context, srcRenderTargetContext->priv().absClear(&clearRect, 0x0); } - convolve_gaussian(context, dstRenderTargetContext.get(), clip, srcRect, - std::move(srcProxy), Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, + convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, + srcTexture.get(), Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, srcBounds, srcOffset); srcRenderTargetContext = dstRenderTargetContext; @@ -346,7 +345,7 @@ sk_sp GaussianBlur(GrContext* context, } SkASSERT(srcRenderTargetContext); - srcProxy.reset(nullptr); // we don't use this from here on out + srcTexture = nullptr; // we don't use this from here on out if (scaleFactorX > 1 || scaleFactorY > 1) { // Clear one pixel to the right and below, to accommodate bilinear upsampling. diff --git a/src/core/SkGpuBlurUtils.h b/src/core/SkGpuBlurUtils.h index c6c56b61f7..7849e8c651 100644 --- a/src/core/SkGpuBlurUtils.h +++ b/src/core/SkGpuBlurUtils.h @@ -22,7 +22,7 @@ namespace SkGpuBlurUtils { * as a renderTargetContext in case the caller wishes to future draw into the result. * Note: one of sigmaX and sigmaY should be non-zero! * @param context The GPU context - * @param src The source to be blurred. + * @param srcTexture The source texture to be blurred. * @param colorSpace Color space of the source (used for the renderTargetContext result, * too). * @param dstBounds The destination bounds, relative to the source texture. @@ -34,7 +34,7 @@ namespace SkGpuBlurUtils { * @return The renderTargetContext containing the blurred result. */ sk_sp GaussianBlur(GrContext* context, - sk_sp src, + GrTexture* srcTexture, sk_sp colorSpace, const SkIRect& dstBounds, const SkIRect* srcBounds, diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 594a94e300..bf544077df 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -1135,12 +1135,12 @@ static sk_sp find_or_create_rrect_blur_mask(GrContext* context, rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw, GrStyle::SimpleFill()); - sk_sp srcProxy(sk_ref_sp(rtc->asDeferredTexture())); - if (!srcProxy) { + sk_sp srcTexture(rtc->asTexture()); + if (!srcTexture) { return nullptr; } sk_sp rtc2(SkGpuBlurUtils::GaussianBlur(context, - std::move(srcProxy), + srcTexture.get(), nullptr, SkIRect::MakeWH( size.fWidth, @@ -1498,11 +1498,16 @@ sk_sp SkBlurMaskFilterImpl::filterMaskGPU(GrContext* context, SkScalar xformedSigma = this->computeXformedSigma(ctm); SkASSERT(xformedSigma > 0); + // TODO: defer this further (i.e., push the proxy into GaussianBlur) + GrTexture* src = srcProxy->instantiate(context->textureProvider()); + if (!src) { + return nullptr; + } + // If we're doing a normal blur, we can clobber the pathTexture in the // gaussianBlur. Otherwise, we need to save it for later compositing. bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle); - sk_sp renderTargetContext(SkGpuBlurUtils::GaussianBlur(context, - srcProxy, + sk_sp renderTargetContext(SkGpuBlurUtils::GaussianBlur(context, src, nullptr, clipRect, nullptr, xformedSigma, @@ -1515,7 +1520,7 @@ sk_sp SkBlurMaskFilterImpl::filterMaskGPU(GrContext* context, GrPaint paint; // Blend pathTexture over blurTexture. paint.addCoverageFragmentProcessor( - GrSimpleTextureEffect::Make(context, std::move(srcProxy), nullptr, SkMatrix::I())); + GrSimpleTextureEffect::Make(src, nullptr, SkMatrix::I())); if (kInner_SkBlurStyle == fBlurStyle) { // inner: dst = dst * src paint.setCoverageSetOpXPFactory(SkRegion::kIntersect_Op); diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp index 66aba13438..c5f554fc69 100644 --- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp +++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp @@ -115,17 +115,12 @@ void GrGLConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdman, } pdman.set2fv(fImageIncrementUni, 1, imageIncrement); if (conv.useBounds()) { - const int* bounds = conv.bounds(); - if (Gr1DKernelEffect::kX_Direction == conv.direction()) { - SkScalar inv = SkScalarInvert(SkIntToScalar(texture.width())); - pdman.set2f(fBoundsUni, inv * bounds[0], inv * bounds[1]); + const float* bounds = conv.bounds(); + if (Gr1DKernelEffect::kY_Direction == conv.direction() && + texture.origin() != kTopLeft_GrSurfaceOrigin) { + pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]); } else { - SkScalar inv = SkScalarInvert(SkIntToScalar(texture.height())); - if (texture.origin() != kTopLeft_GrSurfaceOrigin) { - pdman.set2f(fBoundsUni, 1.0f - (inv * bounds[1]), 1.0f - (inv * bounds[0])); - } else { - pdman.set2f(fBoundsUni, inv * bounds[1], inv * bounds[0]); - } + pdman.set2f(fBoundsUni, bounds[0], bounds[1]); } } int width = Gr1DKernelEffect::WidthFromRadius(conv.radius()); @@ -149,6 +144,8 @@ void GrGLConvolutionEffect::GenKey(const GrProcessor& processor, const GrShaderC } /////////////////////////////////////////////////////////////////////////////// + + static void fill_in_1D_guassian_kernel(float* kernel, int width, float gaussianSigma, int radius) { const float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); @@ -172,7 +169,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor(G int radius, float gaussianSigma, bool useBounds, - int bounds[2]) + float bounds[2]) : INHERITED(texture, direction, radius, ModulationFlags(texture->config())) , fUseBounds(useBounds) { this->initClassID(); @@ -190,7 +187,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor( int radius, float gaussianSigma, bool useBounds, - int bounds[2]) + float bounds[2]) : INHERITED{context, ModulationFlags(proxy->config()), GR_PROXY_MOVE(proxy), @@ -233,25 +230,16 @@ sk_sp GrGaussianConvolutionFragmentProcessor::TestCreate( GrProcessorTestData* d) { int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : GrProcessorUnitTest::kAlphaTextureIdx; - sk_sp proxy = d->textureProxy(texIdx); + Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction; + int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius); bool useBounds = d->fRandom->nextBool(); - int bounds[2]; - - Direction dir; - if (d->fRandom->nextBool()) { - dir = kX_Direction; - bounds[0] = d->fRandom->nextRangeU(0, proxy->width()-1); - bounds[1] = d->fRandom->nextRangeU(bounds[0], proxy->width()-1); - } else { - dir = kY_Direction; - bounds[0] = d->fRandom->nextRangeU(0, proxy->height()-1); - bounds[1] = d->fRandom->nextRangeU(bounds[0], proxy->height()-1); + float bounds[2]; + for (size_t i = 0; i < SK_ARRAY_COUNT(bounds); ++i) { + bounds[i] = d->fRandom->nextF(); } - int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius); float sigma = radius / 3.f; - return GrGaussianConvolutionFragmentProcessor::Make( d->context(), d->textureProxy(texIdx), dir, radius, sigma, useBounds, bounds); } diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h index 0bb9c5e1df..b4f5cb7921 100644 --- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h +++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h @@ -24,7 +24,7 @@ public: int halfWidth, float gaussianSigma, bool useBounds, - int* bounds) { + float* bounds) { return sk_sp(new GrGaussianConvolutionFragmentProcessor( tex, dir, halfWidth, gaussianSigma, useBounds, bounds)); } @@ -35,7 +35,7 @@ public: int halfWidth, float gaussianSigma, bool useBounds, - int* bounds) { + float* bounds) { return sk_sp(new GrGaussianConvolutionFragmentProcessor( context, std::move(proxy), dir, halfWidth, gaussianSigma, useBounds, bounds)); } @@ -44,7 +44,7 @@ public: const float* kernel() const { return fKernel; } - const int* bounds() const { return fBounds; } + const float* bounds() const { return fBounds; } bool useBounds() const { return fUseBounds; } const char* name() const override { return "GaussianConvolution"; } @@ -61,11 +61,11 @@ public: private: /// Convolve with a Gaussian kernel GrGaussianConvolutionFragmentProcessor(GrTexture*, Direction, int halfWidth, - float gaussianSigma, bool useBounds, int bounds[2]); + float gaussianSigma, bool useBounds, float bounds[2]); GrGaussianConvolutionFragmentProcessor(GrContext*, sk_sp, Direction, int halfWidth, float gaussianSigma, bool useBounds, - int bounds[2]); + float bounds[2]); GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; @@ -85,7 +85,7 @@ private: // some of the logic from SkGpuBlurUtils into this class related to radius/sigma calculations. float fKernel[kMaxKernelWidth]; bool fUseBounds; - int fBounds[2]; + float fBounds[2]; typedef Gr1DKernelEffect INHERITED; }; diff --git a/src/gpu/effects/GrProxyMove.h b/src/gpu/effects/GrProxyMove.h index 87612f7e0f..643e01bc81 100644 --- a/src/gpu/effects/GrProxyMove.h +++ b/src/gpu/effects/GrProxyMove.h @@ -3,8 +3,8 @@ * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - */ - + */ + #ifndef GrProxyMove_DEFINED #define GrProxyMove_DEFINED