aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkGpuBlurUtils.cpp
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-04-25 09:13:28 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-25 15:01:07 +0000
commit213ce18fc4937c2c523f723f6890788e8f15ed9c (patch)
tree50727cdcf33b6bba8a0f3faeab813e79bcc105eb /src/core/SkGpuBlurUtils.cpp
parent7c09a31344b9ebafc9d19b47c755df7985cdfb73 (diff)
Refactor GaussianBlur
One of the bounding boxes in this method goes haywire in DDL mode. Hopefully, this refactoring will make it easier to determine which one it is. Note that in this CL I tried to not change the existing behavior at all. Bug: skia:7765 Change-Id: Ie71b4c338fd7ecf4f4b8b4cb5609ef3e686eaef5 Reviewed-on: https://skia-review.googlesource.com/122956 Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/core/SkGpuBlurUtils.cpp')
-rw-r--r--src/core/SkGpuBlurUtils.cpp480
1 files changed, 287 insertions, 193 deletions
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;