blob: 5d6d014dfda5aec0c8191ce698e00fed30e0af99 [file] [log] [blame]
robertphillips@google.com736dd032013-07-15 15:06:54 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkGpuBlurUtils.h"
9
10#include "SkRect.h"
11
12#if SK_SUPPORT_GPU
13#include "effects/GrConvolutionEffect.h"
joshualitt5acfea72014-08-11 13:55:34 -070014#include "effects/GrMatrixConvolutionEffect.h"
robertphillips@google.com736dd032013-07-15 15:06:54 +000015#include "GrContext.h"
bsalomon76228632015-05-29 08:02:10 -070016#include "GrCaps.h"
robertphillipsea461502015-05-26 11:38:03 -070017#include "GrDrawContext.h"
robertphillips@google.com736dd032013-07-15 15:06:54 +000018#endif
19
20namespace SkGpuBlurUtils {
21
22#if SK_SUPPORT_GPU
23
24#define MAX_BLUR_SIGMA 4.0f
25
26static void scale_rect(SkRect* rect, float xScale, float yScale) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000027 rect->fLeft = SkScalarMul(rect->fLeft, xScale);
28 rect->fTop = SkScalarMul(rect->fTop, yScale);
29 rect->fRight = SkScalarMul(rect->fRight, xScale);
30 rect->fBottom = SkScalarMul(rect->fBottom, yScale);
robertphillips@google.com736dd032013-07-15 15:06:54 +000031}
32
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +000033static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) {
robertphillips@google.com736dd032013-07-15 15:06:54 +000034 *scaleFactor = 1;
35 while (sigma > MAX_BLUR_SIGMA) {
36 *scaleFactor *= 2;
37 sigma *= 0.5f;
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +000038 if (*scaleFactor > maxTextureSize) {
39 *scaleFactor = maxTextureSize;
40 sigma = MAX_BLUR_SIGMA;
41 }
robertphillips@google.com736dd032013-07-15 15:06:54 +000042 }
43 *radius = static_cast<int>(ceilf(sigma * 3.0f));
commit-bot@chromium.org96ae6882013-08-14 12:09:00 +000044 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
robertphillips@google.com736dd032013-07-15 15:06:54 +000045 return sigma;
46}
47
robertphillipsea461502015-05-26 11:38:03 -070048static void convolve_gaussian_1d(GrDrawContext* drawContext,
joshualitt570d2f82015-02-25 13:19:48 -080049 const GrClip& clip,
joshualitt5acfea72014-08-11 13:55:34 -070050 const SkRect& dstRect,
senorblanco48343ee2015-11-03 05:07:43 -080051 const SkPoint& srcOffset,
joshualitt5acfea72014-08-11 13:55:34 -070052 GrTexture* texture,
53 Gr1DKernelEffect::Direction direction,
54 int radius,
55 float sigma,
56 bool useBounds,
57 float bounds[2]) {
robertphillips@google.com736dd032013-07-15 15:06:54 +000058 GrPaint paint;
joshualittb0a8a372014-09-23 09:50:21 -070059 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
bsalomon4a339522015-10-06 08:40:50 -070060 texture, direction, radius, sigma, useBounds, bounds));
bsalomonac856c92015-08-27 06:30:17 -070061 paint.addColorFragmentProcessor(conv);
senorblanco48343ee2015-11-03 05:07:43 -080062 SkMatrix localMatrix = SkMatrix::MakeTrans(srcOffset.x(), srcOffset.y());
63 drawContext->drawNonAARectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
robertphillips@google.com736dd032013-07-15 15:06:54 +000064}
65
robertphillipsea461502015-05-26 11:38:03 -070066static void convolve_gaussian_2d(GrDrawContext* drawContext,
joshualitt570d2f82015-02-25 13:19:48 -080067 const GrClip& clip,
joshualitt5acfea72014-08-11 13:55:34 -070068 const SkRect& srcRect,
joshualitt5acfea72014-08-11 13:55:34 -070069 GrTexture* texture,
70 int radiusX,
71 int radiusY,
72 SkScalar sigmaX,
73 SkScalar sigmaY,
74 bool useBounds,
75 SkIRect bounds) {
senorblanco48343ee2015-11-03 05:07:43 -080076 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
77 SkMatrix localMatrix = SkMatrix::MakeTrans(srcRect.x(), srcRect.y());
joshualitt5acfea72014-08-11 13:55:34 -070078 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
79 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
80 GrPaint paint;
joshualittb0a8a372014-09-23 09:50:21 -070081 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaussian(
joshualitt5acfea72014-08-11 13:55:34 -070082 texture, bounds, size, 1.0, 0.0, kernelOffset,
83 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_Mode,
84 true, sigmaX, sigmaY));
bsalomonac856c92015-08-27 06:30:17 -070085 paint.addColorFragmentProcessor(conv);
senorblanco48343ee2015-11-03 05:07:43 -080086 drawContext->drawNonAARectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
joshualitt5acfea72014-08-11 13:55:34 -070087}
88
robertphillipsea461502015-05-26 11:38:03 -070089static void convolve_gaussian(GrDrawContext* drawContext,
joshualitt570d2f82015-02-25 13:19:48 -080090 const GrClip& clip,
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +000091 const SkRect& srcRect,
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +000092 GrTexture* texture,
93 Gr1DKernelEffect::Direction direction,
94 int radius,
95 float sigma,
96 bool cropToSrcRect) {
97 float bounds[2] = { 0.0f, 1.0f };
senorblanco48343ee2015-11-03 05:07:43 -080098 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
99 SkPoint srcOffset = SkPoint::Make(srcRect.x(), srcRect.y());
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000100 if (!cropToSrcRect) {
senorblanco48343ee2015-11-03 05:07:43 -0800101 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700102 direction, radius, sigma, false, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000103 return;
104 }
senorblanco48343ee2015-11-03 05:07:43 -0800105 SkRect lowerDstRect = dstRect;
106 SkRect middleDstRect = dstRect;
107 SkRect upperDstRect = dstRect;
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000108 SkScalar size;
109 SkScalar rad = SkIntToScalar(radius);
110 if (direction == Gr1DKernelEffect::kX_Direction) {
111 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
112 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
senorblanco48343ee2015-11-03 05:07:43 -0800113 size = dstRect.width();
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000114 lowerDstRect.fRight = dstRect.left() + rad;
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000115 upperDstRect.fLeft = dstRect.right() - rad;
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000116 middleDstRect.inset(rad, 0);
117 } else {
118 bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
119 bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
senorblanco48343ee2015-11-03 05:07:43 -0800120 size = dstRect.height();
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000121 lowerDstRect.fBottom = dstRect.top() + rad;
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000122 upperDstRect.fTop = dstRect.bottom() - rad;
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000123 middleDstRect.inset(0, rad);
124 }
125 if (radius >= size * SK_ScalarHalf) {
126 // Blur radius covers srcRect; use bounds over entire draw
senorblanco48343ee2015-11-03 05:07:43 -0800127 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700128 direction, radius, sigma, true, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000129 } else {
130 // Draw upper and lower margins with bounds; middle without.
senorblanco48343ee2015-11-03 05:07:43 -0800131 convolve_gaussian_1d(drawContext, clip, lowerDstRect, srcOffset, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700132 direction, radius, sigma, true, bounds);
senorblanco48343ee2015-11-03 05:07:43 -0800133 convolve_gaussian_1d(drawContext, clip, upperDstRect, srcOffset, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700134 direction, radius, sigma, true, bounds);
senorblanco48343ee2015-11-03 05:07:43 -0800135 convolve_gaussian_1d(drawContext, clip, middleDstRect, srcOffset, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700136 direction, radius, sigma, false, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000137 }
138}
139
robertphillips@google.com736dd032013-07-15 15:06:54 +0000140GrTexture* GaussianBlur(GrContext* context,
141 GrTexture* srcTexture,
142 bool canClobberSrc,
143 const SkRect& rect,
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000144 bool cropToRect,
skia.committer@gmail.com977409a2013-07-16 07:00:56 +0000145 float sigmaX,
reedc9b5f8b2015-10-22 13:20:20 -0700146 float sigmaY,
147 GrTextureProvider::SizeConstraint constraint) {
bsalomon49f085d2014-09-05 13:34:00 -0700148 SkASSERT(context);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000149
robertphillips@google.com736dd032013-07-15 15:06:54 +0000150 SkIRect clearRect;
151 int scaleFactorX, radiusX;
152 int scaleFactorY, radiusY;
bsalomon76228632015-05-29 08:02:10 -0700153 int maxTextureSize = context->caps()->maxTextureSize();
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000154 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
155 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000156
157 SkRect srcRect(rect);
158 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
reedd02cf262014-11-18 18:06:45 -0800159 srcRect.roundOut(&srcRect);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000160 scale_rect(&srcRect, static_cast<float>(scaleFactorX),
161 static_cast<float>(scaleFactorY));
162
joshualitt570d2f82015-02-25 13:19:48 -0800163 // setup new clip
164 GrClip clip(SkRect::MakeWH(srcRect.width(), srcRect.height()));
robertphillips@google.com736dd032013-07-15 15:06:54 +0000165
commit-bot@chromium.org96ae6882013-08-14 12:09:00 +0000166 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
robertphillips@google.com736dd032013-07-15 15:06:54 +0000167 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
168 kAlpha_8_GrPixelConfig == srcTexture->config());
169
bsalomonf2703d82014-10-28 14:33:06 -0700170 GrSurfaceDesc desc;
bsalomon6bc1b5f2015-02-23 09:06:38 -0800171 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000172 desc.fWidth = SkScalarFloorToInt(srcRect.width());
173 desc.fHeight = SkScalarFloorToInt(srcRect.height());
174 desc.fConfig = srcTexture->config();
175
bsalomone3059732014-10-14 11:47:22 -0700176 GrTexture* dstTexture;
177 GrTexture* tempTexture;
178 SkAutoTUnref<GrTexture> temp1, temp2;
179
reedc9b5f8b2015-10-22 13:20:20 -0700180 temp1.reset(context->textureProvider()->createTexture(desc, constraint));
bsalomone3059732014-10-14 11:47:22 -0700181 dstTexture = temp1.get();
182 if (canClobberSrc) {
183 tempTexture = srcTexture;
184 } else {
reedc9b5f8b2015-10-22 13:20:20 -0700185 temp2.reset(context->textureProvider()->createTexture(desc, constraint));
bsalomone3059732014-10-14 11:47:22 -0700186 tempTexture = temp2.get();
187 }
188
halcanary96fcdcc2015-08-27 07:41:13 -0700189 if (nullptr == dstTexture || nullptr == tempTexture) {
190 return nullptr;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000191 }
192
robertphillipsc9a37062015-09-01 08:34:28 -0700193 SkAutoTUnref<GrDrawContext> srcDrawContext;
robertphillipsea461502015-05-26 11:38:03 -0700194
robertphillips@google.com736dd032013-07-15 15:06:54 +0000195 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
196 GrPaint paint;
197 SkMatrix matrix;
198 matrix.setIDiv(srcTexture->width(), srcTexture->height());
robertphillips@google.com736dd032013-07-15 15:06:54 +0000199 SkRect dstRect(srcRect);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000200 if (cropToRect && i == 1) {
201 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
202 SkRect domain;
203 matrix.mapRect(&domain, rect);
204 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
205 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
bsalomon0ba8c242015-10-07 09:20:28 -0700206 SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create(
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000207 srcTexture,
208 matrix,
209 domain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000210 GrTextureDomain::kDecal_Mode,
humper@google.comb86add12013-07-25 18:49:07 +0000211 GrTextureParams::kBilerp_FilterMode));
bsalomonac856c92015-08-27 06:30:17 -0700212 paint.addColorFragmentProcessor(fp);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000213 } else {
humper@google.comb86add12013-07-25 18:49:07 +0000214 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
joshualittb0a8a372014-09-23 09:50:21 -0700215 paint.addColorTextureProcessor(srcTexture, matrix, params);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000216 }
robertphillips@google.com736dd032013-07-15 15:06:54 +0000217 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
218 i < scaleFactorY ? 0.5f : 1.0f);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700219
robertphillips2e1e51f2015-10-15 08:01:48 -0700220 SkAutoTUnref<GrDrawContext> dstDrawContext(
221 context->drawContext(dstTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700222 if (!dstDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700223 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700224 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700225 dstDrawContext->drawNonAARectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700226
bungeman77a53de2015-10-01 12:28:49 -0700227 srcDrawContext.swap(dstDrawContext);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000228 srcRect = dstRect;
229 srcTexture = dstTexture;
230 SkTSwap(dstTexture, tempTexture);
231 }
232
reedb07a94f2014-11-19 05:03:18 -0800233 const SkIRect srcIRect = srcRect.roundOut();
robertphillips@google.com736dd032013-07-15 15:06:54 +0000234
robertphillipsff0ca5e2015-07-22 11:54:44 -0700235 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
joshualitt5acfea72014-08-11 13:55:34 -0700236 // launch a single non separable kernel vs two launches
robertphillipsff0ca5e2015-07-22 11:54:44 -0700237 if (sigmaX > 0.0f && sigmaY > 0.0f &&
joshualitt5acfea72014-08-11 13:55:34 -0700238 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
239 // We shouldn't be scaling because this is a small size blur
robertphillipsff0ca5e2015-07-22 11:54:44 -0700240 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700241
robertphillips2e1e51f2015-10-15 08:01:48 -0700242 SkAutoTUnref<GrDrawContext> dstDrawContext(
243 context->drawContext(dstTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700244 if (!dstDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700245 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700246 }
senorblanco48343ee2015-11-03 05:07:43 -0800247 convolve_gaussian_2d(dstDrawContext, clip, srcRect,
joshualitt570d2f82015-02-25 13:19:48 -0800248 srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropToRect, srcIRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700249
bungeman77a53de2015-10-01 12:28:49 -0700250 srcDrawContext.swap(dstDrawContext);
senorblanco48343ee2015-11-03 05:07:43 -0800251 srcRect.offsetTo(0, 0);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700252 srcTexture = dstTexture;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000253 SkTSwap(dstTexture, tempTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000254
joshualitt5acfea72014-08-11 13:55:34 -0700255 } else {
256 if (sigmaX > 0.0f) {
257 if (scaleFactorX > 1) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700258 // TODO: if we pass in the source draw context we don't need this here
259 if (!srcDrawContext) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700260 srcDrawContext.reset(context->drawContext(srcTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700261 if (!srcDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700262 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700263 }
264 }
265
joshualitt5acfea72014-08-11 13:55:34 -0700266 // Clear out a radius to the right of the srcRect to prevent the
267 // X convolution from reading garbage.
268 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
269 radiusX, srcIRect.height());
robertphillips2e1e51f2015-10-15 08:01:48 -0700270 srcDrawContext->clear(&clearRect, 0x0, false);
joshualitt5acfea72014-08-11 13:55:34 -0700271 }
robertphillipsff0ca5e2015-07-22 11:54:44 -0700272
robertphillips2e1e51f2015-10-15 08:01:48 -0700273 SkAutoTUnref<GrDrawContext> dstDrawContext(
robertphillips77a2e522015-10-17 07:43:27 -0700274 context->drawContext(dstTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700275 if (!dstDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700276 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700277 }
senorblanco48343ee2015-11-03 05:07:43 -0800278 convolve_gaussian(dstDrawContext, clip, srcRect,
joshualitt570d2f82015-02-25 13:19:48 -0800279 srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
280 cropToRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700281
bungeman77a53de2015-10-01 12:28:49 -0700282 srcDrawContext.swap(dstDrawContext);
joshualitt5acfea72014-08-11 13:55:34 -0700283 srcTexture = dstTexture;
senorblanco48343ee2015-11-03 05:07:43 -0800284 srcRect.offsetTo(0, 0);
joshualitt5acfea72014-08-11 13:55:34 -0700285 SkTSwap(dstTexture, tempTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000286 }
287
joshualitt5acfea72014-08-11 13:55:34 -0700288 if (sigmaY > 0.0f) {
289 if (scaleFactorY > 1 || sigmaX > 0.0f) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700290 // TODO: if we pass in the source draw context we don't need this here
291 if (!srcDrawContext) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700292 srcDrawContext.reset(context->drawContext(srcTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700293 if (!srcDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700294 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700295 }
296 }
297
joshualitt5acfea72014-08-11 13:55:34 -0700298 // Clear out a radius below the srcRect to prevent the Y
299 // convolution from reading garbage.
300 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
301 srcIRect.width(), radiusY);
robertphillips2e1e51f2015-10-15 08:01:48 -0700302 srcDrawContext->clear(&clearRect, 0x0, false);
joshualitt5acfea72014-08-11 13:55:34 -0700303 }
304
robertphillips2e1e51f2015-10-15 08:01:48 -0700305 SkAutoTUnref<GrDrawContext> dstDrawContext(
robertphillips77a2e522015-10-17 07:43:27 -0700306 context->drawContext(dstTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700307 if (!dstDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700308 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700309 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700310 convolve_gaussian(dstDrawContext, clip, srcRect,
senorblanco48343ee2015-11-03 05:07:43 -0800311 srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
joshualitt570d2f82015-02-25 13:19:48 -0800312 cropToRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700313
bungeman77a53de2015-10-01 12:28:49 -0700314 srcDrawContext.swap(dstDrawContext);
joshualitt5acfea72014-08-11 13:55:34 -0700315 srcTexture = dstTexture;
senorblanco48343ee2015-11-03 05:07:43 -0800316 srcRect.offsetTo(0, 0);
joshualitt5acfea72014-08-11 13:55:34 -0700317 SkTSwap(dstTexture, tempTexture);
318 }
robertphillips@google.com736dd032013-07-15 15:06:54 +0000319 }
320
321 if (scaleFactorX > 1 || scaleFactorY > 1) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700322 SkASSERT(srcDrawContext);
323
robertphillips@google.com736dd032013-07-15 15:06:54 +0000324 // Clear one pixel to the right and below, to accommodate bilinear
325 // upsampling.
326 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
327 srcIRect.width() + 1, 1);
robertphillips2e1e51f2015-10-15 08:01:48 -0700328 srcDrawContext->clear(&clearRect, 0x0, false);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000329 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
330 1, srcIRect.height());
robertphillips2e1e51f2015-10-15 08:01:48 -0700331 srcDrawContext->clear(&clearRect, 0x0, false);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000332 SkMatrix matrix;
333 matrix.setIDiv(srcTexture->width(), srcTexture->height());
robertphillips@google.com736dd032013-07-15 15:06:54 +0000334
335 GrPaint paint;
336 // FIXME: this should be mitchell, not bilinear.
humper@google.comb86add12013-07-25 18:49:07 +0000337 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
joshualittb0a8a372014-09-23 09:50:21 -0700338 paint.addColorTextureProcessor(srcTexture, matrix, params);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000339
340 SkRect dstRect(srcRect);
341 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700342
robertphillips2e1e51f2015-10-15 08:01:48 -0700343 SkAutoTUnref<GrDrawContext> dstDrawContext(
robertphillips77a2e522015-10-17 07:43:27 -0700344 context->drawContext(dstTexture->asRenderTarget()));
robertphillipsff0ca5e2015-07-22 11:54:44 -0700345 if (!dstDrawContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700346 return nullptr;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700347 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700348 dstDrawContext->drawNonAARectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700349
bungeman77a53de2015-10-01 12:28:49 -0700350 srcDrawContext.swap(dstDrawContext);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000351 srcRect = dstRect;
352 srcTexture = dstTexture;
353 SkTSwap(dstTexture, tempTexture);
354 }
robertphillipsff0ca5e2015-07-22 11:54:44 -0700355
bsalomone3059732014-10-14 11:47:22 -0700356 return SkRef(srcTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000357}
358#endif
359
robertphillips@google.comcce41022013-07-15 15:47:10 +0000360}