aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBlurImageFilter.cpp17
-rw-r--r--src/core/SkBlurMF.cpp3
-rw-r--r--src/core/SkGpuBlurUtils.cpp480
-rw-r--r--src/core/SkGpuBlurUtils.h1
-rw-r--r--src/gpu/SkGpuDevice.cpp6
-rw-r--r--src/gpu/effects/GrRRectBlurEffect.h1
6 files changed, 302 insertions, 206 deletions
diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp
index abdf8cdc48..aa566a49f6 100644
--- a/src/core/SkBlurImageFilter.cpp
+++ b/src/core/SkBlurImageFilter.cpp
@@ -650,14 +650,15 @@ sk_sp<SkSpecialImage> SkBlurImageFilterImpl::gpuFilter(
// Then, when we create the output image later, we tag it with the input's color space, so
// it will be tagged correctly, regardless of how we created the intermediate RTCs.
sk_sp<GrRenderTargetContext> renderTargetContext(SkGpuBlurUtils::GaussianBlur(
- context,
- std::move(inputTexture),
- outProps.colorSpace() ? sk_ref_sp(input->getColorSpace()) : nullptr,
- dstBounds,
- inputBounds,
- sigma.x(),
- sigma.y(),
- to_texture_domain_mode(fTileMode)));
+ context,
+ std::move(inputTexture),
+ outProps.colorSpace() ? sk_ref_sp(input->getColorSpace()) : nullptr,
+ dstBounds,
+ inputBounds,
+ sigma.x(),
+ sigma.y(),
+ to_texture_domain_mode(fTileMode),
+ input->alphaType()));
if (!renderTargetContext) {
return nullptr;
}
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index baa656597f..8bae1f05f1 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -954,7 +954,8 @@ sk_sp<GrTextureProxy> SkBlurMaskFilterImpl::filterMaskGPU(GrContext* context,
SkIRect::EmptyIRect(),
xformedSigma,
xformedSigma,
- GrTextureDomain::kIgnore_Mode));
+ GrTextureDomain::kIgnore_Mode,
+ kPremul_SkAlphaType));
if (!renderTargetContext) {
return nullptr;
}
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index fe614bd0df..04ca7d9b48 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -18,6 +18,8 @@
#include "effects/GrGaussianConvolutionFragmentProcessor.h"
#include "effects/GrMatrixConvolutionEffect.h"
+#include "SkGr.h"
+
#define MAX_BLUR_SIGMA 4.0f
using Direction = GrGaussianConvolutionFragmentProcessor::Direction;
@@ -91,17 +93,48 @@ static void convolve_gaussian_1d(GrRenderTargetContext* renderTargetContext,
SkRect::Make(dstRect), localMatrix);
}
-static void convolve_gaussian_2d(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
- const SkIRect& dstRect,
- const SkIPoint& srcOffset,
- sk_sp<GrTextureProxy> proxy,
- int radiusX,
- int radiusY,
- SkScalar sigmaX,
- SkScalar sigmaY,
- const SkIRect& srcBounds,
- GrTextureDomain::Mode mode) {
+static GrPixelConfig get_blur_config(GrTextureProxy* proxy, SkColorSpace* cs) {
+ GrPixelConfig config = proxy->config();
+
+ if (GrPixelConfigIsSRGB(config) && !cs) {
+ // If the context doesn't have sRGB write control, and we make an sRGB RTC, we won't be
+ // able to suppress the linear -> sRGB conversion out of the shader. Not all GL drivers
+ // have that feature, and Vulkan is missing it entirely. To keep things simple, switch to
+ // a non-sRGB destination, to ensure correct blurring behavior.
+ config = kRGBA_8888_GrPixelConfig;
+ }
+
+ SkASSERT(kBGRA_8888_GrPixelConfig == config || kRGBA_8888_GrPixelConfig == config ||
+ kRGB_888_GrPixelConfig == config || kRGBA_4444_GrPixelConfig == config ||
+ kRGB_565_GrPixelConfig == config || kSRGBA_8888_GrPixelConfig == config ||
+ kSBGRA_8888_GrPixelConfig == config || kRGBA_half_GrPixelConfig == config ||
+ kAlpha_8_GrPixelConfig == config || kRGBA_1010102_GrPixelConfig == config);
+
+ return config;
+}
+
+static sk_sp<GrRenderTargetContext> convolve_gaussian_2d(GrContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ const SkIRect& srcBounds,
+ const SkIPoint& srcOffset,
+ int radiusX,
+ int radiusY,
+ SkScalar sigmaX,
+ SkScalar sigmaY,
+ GrTextureDomain::Mode mode,
+ const SkImageInfo& dstII,
+ SkBackingFit dstFit) {
+
+ GrPixelConfig config = get_blur_config(proxy.get(), dstII.colorSpace());
+
+ sk_sp<GrRenderTargetContext> renderTargetContext;
+ renderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
+ dstFit, dstII.width(), dstII.height(),
+ config, dstII.refColorSpace());
+ if (!renderTargetContext) {
+ return nullptr;
+ }
+
SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
-SkIntToScalar(srcOffset.y()));
SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
@@ -113,28 +146,50 @@ static void convolve_gaussian_2d(GrRenderTargetContext* renderTargetContext,
kernelOffset, mode, true, sigmaX, sigmaY);
paint.addColorFragmentProcessor(std::move(conv));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+ GrFixedClip clip(dstII.bounds());
+
renderTargetContext->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::Make(dstRect), localMatrix);
+ SkRect::Make(dstII.bounds()), localMatrix);
+
+ return renderTargetContext;
}
-static void convolve_gaussian(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
- const SkIRect& srcRect,
- sk_sp<GrTextureProxy> proxy,
- Direction direction,
- int radius,
- float sigma,
- const SkIRect& srcBounds,
- const SkIPoint& srcOffset,
- GrTextureDomain::Mode mode) {
+static sk_sp<GrRenderTargetContext> convolve_gaussian(GrContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ const SkIRect& srcRect,
+ const SkIPoint& srcOffset,
+ Direction direction,
+ int radius,
+ float sigma,
+ const SkIRect& srcBounds,
+ GrTextureDomain::Mode mode,
+ const SkImageInfo& dstII,
+ SkBackingFit fit) {
+ SkASSERT(srcRect.width() <= dstII.width() && srcRect.height() <= dstII.height());
+
+ GrPixelConfig config = get_blur_config(proxy.get(), dstII.colorSpace());
+
+ sk_sp<GrRenderTargetContext> dstRenderTargetContext;
+ dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
+ fit, srcRect.width(),
+ srcRect.height(),
+ config,
+ dstII.refColorSpace());
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+
+ GrFixedClip clip(dstII.bounds());
+
int bounds[2] = { 0, 0 };
SkIRect dstRect = SkIRect::MakeWH(srcRect.width(), srcRect.height());
if (GrTextureDomain::kIgnore_Mode == mode) {
- convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset,
+ convolve_gaussian_1d(dstRenderTargetContext.get(), clip, dstRect, srcOffset,
std::move(proxy), direction, radius, sigma,
GrTextureDomain::kIgnore_Mode, bounds);
- return;
+ return dstRenderTargetContext;
}
+
SkIRect midRect = srcBounds, leftRect, rightRect;
midRect.offset(srcOffset);
SkIRect topRect, bottomRect;
@@ -162,31 +217,190 @@ static void convolve_gaussian(GrRenderTargetContext* renderTargetContext,
dstRect.fRight = midRect.right();
}
if (!topRect.isEmpty()) {
- renderTargetContext->clear(&topRect, 0, GrRenderTargetContext::CanClearFullscreen::kNo);
+ dstRenderTargetContext->clear(&topRect, 0, GrRenderTargetContext::CanClearFullscreen::kNo);
}
if (!bottomRect.isEmpty()) {
- renderTargetContext->clear(&bottomRect, 0, GrRenderTargetContext::CanClearFullscreen::kNo);
+ dstRenderTargetContext->clear(&bottomRect, 0,
+ GrRenderTargetContext::CanClearFullscreen::kNo);
}
if (midRect.isEmpty()) {
// Blur radius covers srcBounds; use bounds over entire draw
- convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset,
+ convolve_gaussian_1d(dstRenderTargetContext.get(), clip, dstRect, srcOffset,
std::move(proxy), direction, radius, sigma, mode, bounds);
} else {
// Draw right and left margins with bounds; middle without.
- convolve_gaussian_1d(renderTargetContext, clip, leftRect, srcOffset,
+ convolve_gaussian_1d(dstRenderTargetContext.get(), clip, leftRect, srcOffset,
proxy, direction, radius, sigma, mode, bounds);
- convolve_gaussian_1d(renderTargetContext, clip, rightRect, srcOffset,
+ convolve_gaussian_1d(dstRenderTargetContext.get(), clip, rightRect, srcOffset,
proxy, direction, radius, sigma, mode, bounds);
- convolve_gaussian_1d(renderTargetContext, clip, midRect, srcOffset,
+ convolve_gaussian_1d(dstRenderTargetContext.get(), clip, midRect, srcOffset,
std::move(proxy), direction, radius, sigma,
GrTextureDomain::kIgnore_Mode, bounds);
}
+
+ return dstRenderTargetContext;
+}
+
+static sk_sp<GrTextureProxy> decimate(GrContext* context,
+ sk_sp<GrTextureProxy> src,
+ SkIRect* srcRect, SkIPoint* srcOffset,
+ const SkIRect& localSrcBounds,
+ int scaleFactorX, int scaleFactorY,
+ bool willBeXFiltering, bool willBeYFiltering,
+ int radiusX, int radiusY,
+ GrTextureDomain::Mode mode,
+ const SkImageInfo& dstII,
+ SkBackingFit fit) {
+ SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY));
+ SkASSERT(scaleFactorX > 1 ||scaleFactorY > 1);
+
+ GrPixelConfig config = get_blur_config(src.get(), dstII.colorSpace());
+
+ // GrTextureDomainEffect does not support kRepeat_Mode with GrSamplerState::Filter.
+ GrTextureDomain::Mode modeForScaling = GrTextureDomain::kRepeat_Mode == mode
+ ? GrTextureDomain::kDecal_Mode
+ : mode;
+
+ sk_sp<GrRenderTargetContext> dstRenderTargetContext;
+
+ for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
+ SkIRect dstRect(*srcRect);
+ shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
+
+ dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
+ fit,
+ SkTMin(dstRect.fRight, dstII.width()),
+ SkTMin(dstRect.fBottom, dstII.height()),
+ config, dstII.refColorSpace());
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+
+ GrPaint paint;
+ paint.setGammaCorrect(dstRenderTargetContext->colorSpaceInfo().isGammaCorrect());
+
+ if (GrTextureDomain::kIgnore_Mode != mode && i == 1) {
+ SkRect domain = SkRect::Make(localSrcBounds);
+ domain.inset((i < scaleFactorX) ? SK_ScalarHalf : 0.0f,
+ (i < scaleFactorY) ? SK_ScalarHalf : 0.0f);
+ auto fp = GrTextureDomainEffect::Make(std::move(src),
+ SkMatrix::I(),
+ domain,
+ modeForScaling,
+ GrSamplerState::Filter::kBilerp);
+ paint.addColorFragmentProcessor(std::move(fp));
+ srcRect->offset(-(*srcOffset));
+ srcOffset->set(0, 0);
+ } else {
+ paint.addColorTextureProcessor(std::move(src), SkMatrix::I(),
+ GrSamplerState::ClampBilerp());
+ }
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+
+ dstRenderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo,
+ SkMatrix::I(), SkRect::Make(dstRect),
+ SkRect::Make(*srcRect));
+
+ src = dstRenderTargetContext->asTextureProxyRef();
+ if (!src) {
+ return nullptr;
+ }
+ *srcRect = dstRect;
+ }
+
+ SkASSERT(dstRenderTargetContext);
+
+ if (willBeXFiltering) {
+ if (scaleFactorX > 1) {
+ // Clear out a radius to the right of the srcRect to prevent the
+ // X convolution from reading garbage.
+ SkIRect clearRect = SkIRect::MakeXYWH(srcRect->fRight, srcRect->fTop,
+ radiusX, srcRect->height());
+ dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
+ }
+ } else {
+ if (scaleFactorY > 1) {
+ // Clear out a radius below the srcRect to prevent the Y
+ // convolution from reading garbage.
+ SkIRect clearRect = SkIRect::MakeXYWH(srcRect->fLeft, srcRect->fBottom,
+ srcRect->width(), radiusY);
+ dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
+ }
+ }
+
+ return dstRenderTargetContext->asTextureProxyRef();
+}
+
+static sk_sp<GrRenderTargetContext> reexpand(GrContext* context,
+ sk_sp<GrRenderTargetContext> dstRenderTargetContext,
+ const SkIRect& srcRect,
+ const SkIRect& localSrcBounds,
+ int scaleFactorX, int scaleFactorY,
+ GrTextureDomain::Mode mode,
+ const SkImageInfo& dstII,
+ SkBackingFit fit) {
+ sk_sp<GrTextureProxy> srcProxy = dstRenderTargetContext->asTextureProxyRef();
+ if (!srcProxy) {
+ return nullptr;
+ }
+
+ GrPixelConfig config = get_blur_config(srcProxy.get(), dstII.colorSpace());
+
+ // GrTextureDomainEffect does not support kRepeat_Mode with GrSamplerState::Filter.
+ GrTextureDomain::Mode modeForScaling = GrTextureDomain::kRepeat_Mode == mode
+ ? GrTextureDomain::kDecal_Mode
+ : mode;
+
+ // Clear one pixel to the right and below, to accommodate bilinear upsampling.
+ // TODO: it seems like we should actually be clamping here rather than darkening
+ // the bottom right edges.
+ SkIRect clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1);
+ dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
+ clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.height());
+ dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
+
+ SkIRect dstRect(srcRect);
+ scale_irect(&dstRect, scaleFactorX, scaleFactorY);
+
+ dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
+ fit,
+ SkTMin(dstRect.width(), dstII.width()),
+ SkTMin(dstRect.height(), dstII.height()),
+ config, dstII.refColorSpace());
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+
+ GrPaint paint;
+ paint.setGammaCorrect(dstRenderTargetContext->colorSpaceInfo().isGammaCorrect());
+
+ if (GrTextureDomain::kIgnore_Mode != mode) {
+ SkRect domain = SkRect::Make(localSrcBounds);
+ auto fp = GrTextureDomainEffect::Make(std::move(srcProxy),
+ SkMatrix::I(),
+ domain,
+ modeForScaling,
+ GrSamplerState::Filter::kBilerp);
+ paint.addColorFragmentProcessor(std::move(fp));
+ } else {
+ // FIXME: this should be mitchell, not bilinear.
+ paint.addColorTextureProcessor(std::move(srcProxy), SkMatrix::I(),
+ GrSamplerState::ClampBilerp());
+ }
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+ GrFixedClip clip(dstII.bounds());
+
+ dstRenderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(dstRect), SkRect::Make(srcRect));
+
+ return dstRenderTargetContext;
}
namespace SkGpuBlurUtils {
+// TODO: the 'fit' field actually only needs to apply to the final, returned GrRenderTargetContext
sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
sk_sp<GrTextureProxy> srcProxy,
sk_sp<SkColorSpace> colorSpace,
@@ -195,9 +409,19 @@ sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
float sigmaX,
float sigmaY,
GrTextureDomain::Mode mode,
+ SkAlphaType at,
SkBackingFit fit) {
SkASSERT(context);
- SkIRect clearRect;
+
+ const GrPixelConfig config = get_blur_config(srcProxy.get(), colorSpace.get());
+ SkColorType ct;
+ if (!GrPixelConfigToColorType(config, &ct)) {
+ return nullptr;
+ }
+
+ const SkImageInfo finalDestII = SkImageInfo::Make(dstBounds.width(), dstBounds.height(),
+ ct, at, std::move(colorSpace));
+
int scaleFactorX, radiusX;
int scaleFactorY, radiusY;
int maxTextureSize = context->caps()->maxTextureSize();
@@ -206,11 +430,10 @@ sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
SkASSERT(sigmaX || sigmaY);
SkIPoint srcOffset = SkIPoint::Make(-dstBounds.x(), -dstBounds.y());
- SkIRect localDstBounds = SkIRect::MakeWH(dstBounds.width(), dstBounds.height());
SkIRect localSrcBounds;
SkIRect srcRect;
if (GrTextureDomain::kIgnore_Mode == mode) {
- srcRect = localDstBounds;
+ srcRect = finalDestII.bounds();
} else {
srcRect = localSrcBounds = srcBounds;
srcRect.offset(srcOffset);
@@ -219,30 +442,6 @@ sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
scale_irect(&srcRect, scaleFactorX, scaleFactorY);
- // setup new clip
- GrFixedClip clip(localDstBounds);
-
- GrPixelConfig config = srcProxy->config();
-
- if (GrPixelConfigIsSRGB(config) && !colorSpace) {
- // If the context doesn't have sRGB write control, and we make an sRGB RTC, we won't be
- // able to suppress the linear -> sRGB conversion out of the shader. Not all GL drivers
- // have that feature, and Vulkan is missing it entirely. To keep things simple, switch to
- // a non-sRGB destination, to ensure correct blurring behavior.
- config = kRGBA_8888_GrPixelConfig;
- }
-
- SkASSERT(kBGRA_8888_GrPixelConfig == config || kRGBA_8888_GrPixelConfig == config ||
- kRGB_888_GrPixelConfig == config || kRGBA_4444_GrPixelConfig == config ||
- kRGB_565_GrPixelConfig == config || kSRGBA_8888_GrPixelConfig == config ||
- kSBGRA_8888_GrPixelConfig == config || kRGBA_half_GrPixelConfig == config ||
- kAlpha_8_GrPixelConfig == config || kRGBA_1010102_GrPixelConfig == config);
-
- const int width = dstBounds.width();
- const int height = dstBounds.height();
-
- sk_sp<GrRenderTargetContext> dstRenderTargetContext;
-
// For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
// launch a single non separable kernel vs two launches
if (sigmaX > 0.0f && sigmaY > 0.0f &&
@@ -250,98 +449,48 @@ sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
// We shouldn't be scaling because this is a small size blur
SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
- dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
- fit, width, height, config, colorSpace);
- if (!dstRenderTargetContext) {
- return nullptr;
- }
-
- convolve_gaussian_2d(dstRenderTargetContext.get(),
- clip, localDstBounds, srcOffset, std::move(srcProxy),
- radiusX, radiusY, sigmaX, sigmaY, srcBounds, mode);
-
- return dstRenderTargetContext;
+ return convolve_gaussian_2d(context, std::move(srcProxy), srcBounds, srcOffset,
+ radiusX, radiusY, sigmaX, sigmaY,
+ mode, finalDestII, fit);
}
- SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY));
-
- // GrTextureDomainEffect does not support kRepeat_Mode with GrSamplerState::Filter.
- GrTextureDomain::Mode modeForScaling =
- GrTextureDomain::kRepeat_Mode == mode ? GrTextureDomain::kDecal_Mode : mode;
- for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
- SkIRect dstRect(srcRect);
- shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
-
- dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
- fit,
- SkTMin(dstRect.fRight, width),
- SkTMin(dstRect.fBottom, height),
- config, colorSpace);
- if (!dstRenderTargetContext) {
- return nullptr;
- }
-
- GrPaint paint;
- paint.setGammaCorrect(dstRenderTargetContext->colorSpaceInfo().isGammaCorrect());
-
- if (GrTextureDomain::kIgnore_Mode != mode && i == 1) {
- SkRect domain = SkRect::Make(localSrcBounds);
- domain.inset((i < scaleFactorX) ? SK_ScalarHalf : 0.0f,
- (i < scaleFactorY) ? SK_ScalarHalf : 0.0f);
- auto fp = GrTextureDomainEffect::Make(std::move(srcProxy),
- SkMatrix::I(),
- domain,
- modeForScaling,
- GrSamplerState::Filter::kBilerp);
- paint.addColorFragmentProcessor(std::move(fp));
- srcRect.offset(-srcOffset);
- srcOffset.set(0, 0);
- } else {
- paint.addColorTextureProcessor(std::move(srcProxy), SkMatrix::I(),
- GrSamplerState::ClampBilerp());
- }
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- dstRenderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::Make(dstRect), SkRect::Make(srcRect));
-
- srcProxy = dstRenderTargetContext->asTextureProxyRef();
+ if (scaleFactorX > 1 || scaleFactorY > 1) {
+ srcProxy = decimate(context, std::move(srcProxy), &srcRect, &srcOffset, localSrcBounds,
+ scaleFactorX, scaleFactorY,
+ sigmaX > 0.0f, sigmaY > 0.0f, radiusX, radiusY,
+ mode, finalDestII, fit);
if (!srcProxy) {
return nullptr;
}
- srcRect = dstRect;
+
localSrcBounds = srcRect;
}
- srcRect = localDstBounds;
+ sk_sp<GrRenderTargetContext> dstRenderTargetContext;
+
+ srcRect = finalDestII.bounds();
scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
if (sigmaX > 0.0f) {
- if (scaleFactorX > 1) {
- SkASSERT(dstRenderTargetContext);
-
- // Clear out a radius to the right of the srcRect to prevent the
- // X convolution from reading garbage.
- clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop,
- radiusX, srcRect.height());
- dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
- }
-
- SkASSERT(srcRect.width() <= width && srcRect.height() <= height);
- dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
- fit, srcRect.width(),
- srcRect.height(),
- config, colorSpace);
+ dstRenderTargetContext = convolve_gaussian(context, std::move(srcProxy), srcRect, srcOffset,
+ Direction::kX, radiusX, sigmaX, localSrcBounds,
+ mode, finalDestII, fit);
if (!dstRenderTargetContext) {
return nullptr;
}
- convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, std::move(srcProxy),
- Direction::kX, radiusX, sigmaX, localSrcBounds, srcOffset, mode);
+ if (sigmaY > 0.0f) {
+ // Clear out a radius below the srcRect to prevent the Y
+ // convolution from reading garbage.
+ SkIRect clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom,
+ srcRect.width(), radiusY);
+ dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
+ }
srcProxy = dstRenderTargetContext->asTextureProxyRef();
if (!srcProxy) {
return nullptr;
}
+
srcRect.offsetTo(0, 0);
localSrcBounds = srcRect;
if (GrTextureDomain::kClamp_Mode == mode) {
@@ -352,84 +501,29 @@ sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
}
if (sigmaY > 0.0f) {
- if (scaleFactorY > 1 || sigmaX > 0.0f) {
- SkASSERT(dstRenderTargetContext);
-
- // Clear out a radius below the srcRect to prevent the Y
- // convolution from reading garbage.
- clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom,
- srcRect.width(), radiusY);
- dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
- }
-
- SkASSERT(srcRect.width() <= width && srcRect.height() <= height);
- dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
- fit, srcRect.width(),
- srcRect.height(),
- config, colorSpace);
+ dstRenderTargetContext = convolve_gaussian(context, std::move(srcProxy), srcRect, srcOffset,
+ Direction::kY, radiusY, sigmaY, localSrcBounds,
+ mode, finalDestII, fit);
if (!dstRenderTargetContext) {
return nullptr;
}
- convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, std::move(srcProxy),
- Direction::kY, radiusY, sigmaY, localSrcBounds, srcOffset, mode);
-
srcProxy = dstRenderTargetContext->asTextureProxyRef();
if (!srcProxy) {
return nullptr;
}
+
srcRect.offsetTo(0, 0);
+ srcOffset.set(0, 0);
}
SkASSERT(dstRenderTargetContext);
SkASSERT(srcProxy.get() == dstRenderTargetContext->asTextureProxy());
if (scaleFactorX > 1 || scaleFactorY > 1) {
- // Clear one pixel to the right and below, to accommodate bilinear upsampling.
- // TODO: it seems like we should actually be clamping here rather than darkening
- // the bottom right edges.
- clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1);
- dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
- clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.height());
- dstRenderTargetContext->priv().absClear(&clearRect, 0x0);
-
- SkIRect dstRect(srcRect);
- scale_irect(&dstRect, scaleFactorX, scaleFactorY);
-
- dstRenderTargetContext = context->contextPriv().makeDeferredRenderTargetContext(
- fit, SkTMin(dstRect.width(), width),
- SkTMin(dstRect.height(), height),
- config, colorSpace);
- if (!dstRenderTargetContext) {
- return nullptr;
- }
-
- GrPaint paint;
- paint.setGammaCorrect(dstRenderTargetContext->colorSpaceInfo().isGammaCorrect());
-
- if (GrTextureDomain::kIgnore_Mode != mode) {
- SkRect domain = SkRect::Make(localSrcBounds);
- auto fp = GrTextureDomainEffect::Make(std::move(srcProxy),
- SkMatrix::I(),
- domain,
- modeForScaling,
- GrSamplerState::Filter::kBilerp);
- paint.addColorFragmentProcessor(std::move(fp));
- } else {
- // FIXME: this should be mitchell, not bilinear.
- paint.addColorTextureProcessor(std::move(srcProxy), SkMatrix::I(),
- GrSamplerState::ClampBilerp());
- }
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- dstRenderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::Make(dstRect), SkRect::Make(srcRect));
-
- srcProxy = dstRenderTargetContext->asTextureProxyRef();
- if (!srcProxy) {
- return nullptr;
- }
- srcRect = dstRect;
+ dstRenderTargetContext = reexpand(context, std::move(dstRenderTargetContext), srcRect,
+ localSrcBounds, scaleFactorX, scaleFactorY,
+ mode, finalDestII, fit);
}
return dstRenderTargetContext;
diff --git a/src/core/SkGpuBlurUtils.h b/src/core/SkGpuBlurUtils.h
index 8a6f7b1922..e06dc8ba2d 100644
--- a/src/core/SkGpuBlurUtils.h
+++ b/src/core/SkGpuBlurUtils.h
@@ -44,6 +44,7 @@ namespace SkGpuBlurUtils {
float sigmaX,
float sigmaY,
GrTextureDomain::Mode mode,
+ SkAlphaType at,
SkBackingFit fit = SkBackingFit::kApprox);
};
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 138d41f26a..7600a8f1c6 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1052,7 +1052,7 @@ void SkGpuDevice::drawSprite(const SkBitmap& bitmap,
void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const SkPaint& paint,
- SkImage* clipImage,const SkMatrix& clipMatrix) {
+ SkImage* clipImage, const SkMatrix& clipMatrix) {
ASSERT_SINGLE_OWNER
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpecial", fContext.get());
@@ -1062,9 +1062,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const
sk_sp<SkSpecialImage> result;
if (paint.getImageFilter()) {
- result = this->filterTexture(special1, left, top,
- &offset,
- paint.getImageFilter());
+ result = this->filterTexture(special1, left, top, &offset, paint.getImageFilter());
if (!result) {
return;
}
diff --git a/src/gpu/effects/GrRRectBlurEffect.h b/src/gpu/effects/GrRRectBlurEffect.h
index d1316e8a5b..04af1273f7 100644
--- a/src/gpu/effects/GrRRectBlurEffect.h
+++ b/src/gpu/effects/GrRRectBlurEffect.h
@@ -79,6 +79,7 @@ public:
xformedSigma,
xformedSigma,
GrTextureDomain::kIgnore_Mode,
+ kPremul_SkAlphaType,
SkBackingFit::kExact));
if (!rtc2) {
return nullptr;