blob: 2b6b310819eb0110eb9c230f66c0d19a298f006e [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,
joshualitt25d9c152015-02-18 12:29:52 -080049 GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -080050 const GrClip& clip,
joshualitt5acfea72014-08-11 13:55:34 -070051 const SkRect& srcRect,
52 const SkRect& dstRect,
53 GrTexture* texture,
54 Gr1DKernelEffect::Direction direction,
55 int radius,
56 float sigma,
57 bool useBounds,
58 float bounds[2]) {
robertphillips@google.com736dd032013-07-15 15:06:54 +000059 GrPaint paint;
joshualittb0a8a372014-09-23 09:50:21 -070060 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
joshualitt5f10b5c2015-07-09 10:24:35 -070061 paint.getProcessorDataManager(), texture, direction, radius, sigma, useBounds, bounds));
bsalomonac856c92015-08-27 06:30:17 -070062 paint.addColorFragmentProcessor(conv);
robertphillipsea461502015-05-26 11:38:03 -070063 drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
robertphillips@google.com736dd032013-07-15 15:06:54 +000064}
65
robertphillipsea461502015-05-26 11:38:03 -070066static void convolve_gaussian_2d(GrDrawContext* drawContext,
joshualitt25d9c152015-02-18 12:29:52 -080067 GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -080068 const GrClip& clip,
joshualitt5acfea72014-08-11 13:55:34 -070069 const SkRect& srcRect,
70 const SkRect& dstRect,
71 GrTexture* texture,
72 int radiusX,
73 int radiusY,
74 SkScalar sigmaX,
75 SkScalar sigmaY,
76 bool useBounds,
77 SkIRect bounds) {
78 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(
joshualitt5f10b5c2015-07-09 10:24:35 -070082 paint.getProcessorDataManager(),
joshualitt5acfea72014-08-11 13:55:34 -070083 texture, bounds, size, 1.0, 0.0, kernelOffset,
84 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_Mode,
85 true, sigmaX, sigmaY));
bsalomonac856c92015-08-27 06:30:17 -070086 paint.addColorFragmentProcessor(conv);
robertphillipsea461502015-05-26 11:38:03 -070087 drawContext->drawNonAARectToRect(rt, clip, paint, SkMatrix::I(), dstRect, srcRect);
joshualitt5acfea72014-08-11 13:55:34 -070088}
89
robertphillipsea461502015-05-26 11:38:03 -070090static void convolve_gaussian(GrDrawContext* drawContext,
joshualitt25d9c152015-02-18 12:29:52 -080091 GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -080092 const GrClip& clip,
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +000093 const SkRect& srcRect,
94 const SkRect& dstRect,
95 GrTexture* texture,
96 Gr1DKernelEffect::Direction direction,
97 int radius,
98 float sigma,
99 bool cropToSrcRect) {
100 float bounds[2] = { 0.0f, 1.0f };
101 if (!cropToSrcRect) {
robertphillipsea461502015-05-26 11:38:03 -0700102 convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700103 direction, radius, sigma, false, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000104 return;
105 }
106 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
107 SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
108 SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
109 SkScalar size;
110 SkScalar rad = SkIntToScalar(radius);
111 if (direction == Gr1DKernelEffect::kX_Direction) {
112 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
113 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
114 size = srcRect.width();
115 lowerSrcRect.fRight = srcRect.left() + rad;
116 lowerDstRect.fRight = dstRect.left() + rad;
117 upperSrcRect.fLeft = srcRect.right() - rad;
118 upperDstRect.fLeft = dstRect.right() - rad;
119 middleSrcRect.inset(rad, 0);
120 middleDstRect.inset(rad, 0);
121 } else {
122 bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
123 bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
124 size = srcRect.height();
125 lowerSrcRect.fBottom = srcRect.top() + rad;
126 lowerDstRect.fBottom = dstRect.top() + rad;
127 upperSrcRect.fTop = srcRect.bottom() - rad;
128 upperDstRect.fTop = dstRect.bottom() - rad;
129 middleSrcRect.inset(0, rad);
130 middleDstRect.inset(0, rad);
131 }
132 if (radius >= size * SK_ScalarHalf) {
133 // Blur radius covers srcRect; use bounds over entire draw
robertphillipsea461502015-05-26 11:38:03 -0700134 convolve_gaussian_1d(drawContext, rt, clip, srcRect, dstRect, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700135 direction, radius, sigma, true, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000136 } else {
137 // Draw upper and lower margins with bounds; middle without.
robertphillipsea461502015-05-26 11:38:03 -0700138 convolve_gaussian_1d(drawContext, rt, clip, lowerSrcRect, lowerDstRect, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700139 direction, radius, sigma, true, bounds);
robertphillipsea461502015-05-26 11:38:03 -0700140 convolve_gaussian_1d(drawContext, rt, clip, upperSrcRect, upperDstRect, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700141 direction, radius, sigma, true, bounds);
robertphillipsea461502015-05-26 11:38:03 -0700142 convolve_gaussian_1d(drawContext, rt, clip, middleSrcRect, middleDstRect, texture,
joshualitt5acfea72014-08-11 13:55:34 -0700143 direction, radius, sigma, false, bounds);
senorblanco@chromium.orgd71732a2013-07-30 21:11:05 +0000144 }
145}
146
robertphillips@google.com736dd032013-07-15 15:06:54 +0000147GrTexture* GaussianBlur(GrContext* context,
148 GrTexture* srcTexture,
149 bool canClobberSrc,
150 const SkRect& rect,
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000151 bool cropToRect,
skia.committer@gmail.com977409a2013-07-16 07:00:56 +0000152 float sigmaX,
robertphillips@google.com736dd032013-07-15 15:06:54 +0000153 float sigmaY) {
bsalomon49f085d2014-09-05 13:34:00 -0700154 SkASSERT(context);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000155
robertphillips@google.com736dd032013-07-15 15:06:54 +0000156 SkIRect clearRect;
157 int scaleFactorX, radiusX;
158 int scaleFactorY, radiusY;
bsalomon76228632015-05-29 08:02:10 -0700159 int maxTextureSize = context->caps()->maxTextureSize();
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000160 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
161 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000162
163 SkRect srcRect(rect);
164 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
reedd02cf262014-11-18 18:06:45 -0800165 srcRect.roundOut(&srcRect);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000166 scale_rect(&srcRect, static_cast<float>(scaleFactorX),
167 static_cast<float>(scaleFactorY));
168
joshualitt570d2f82015-02-25 13:19:48 -0800169 // setup new clip
170 GrClip clip(SkRect::MakeWH(srcRect.width(), srcRect.height()));
robertphillips@google.com736dd032013-07-15 15:06:54 +0000171
commit-bot@chromium.org96ae6882013-08-14 12:09:00 +0000172 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
robertphillips@google.com736dd032013-07-15 15:06:54 +0000173 kRGBA_8888_GrPixelConfig == srcTexture->config() ||
174 kAlpha_8_GrPixelConfig == srcTexture->config());
175
bsalomonf2703d82014-10-28 14:33:06 -0700176 GrSurfaceDesc desc;
bsalomon6bc1b5f2015-02-23 09:06:38 -0800177 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000178 desc.fWidth = SkScalarFloorToInt(srcRect.width());
179 desc.fHeight = SkScalarFloorToInt(srcRect.height());
180 desc.fConfig = srcTexture->config();
181
bsalomone3059732014-10-14 11:47:22 -0700182 GrTexture* dstTexture;
183 GrTexture* tempTexture;
184 SkAutoTUnref<GrTexture> temp1, temp2;
185
bsalomoneae62002015-07-31 13:59:30 -0700186 temp1.reset(context->textureProvider()->createApproxTexture(desc));
bsalomone3059732014-10-14 11:47:22 -0700187 dstTexture = temp1.get();
188 if (canClobberSrc) {
189 tempTexture = srcTexture;
190 } else {
bsalomoneae62002015-07-31 13:59:30 -0700191 temp2.reset(context->textureProvider()->createApproxTexture(desc));
bsalomone3059732014-10-14 11:47:22 -0700192 tempTexture = temp2.get();
193 }
194
robertphillips@google.com736dd032013-07-15 15:06:54 +0000195 if (NULL == dstTexture || NULL == tempTexture) {
196 return NULL;
197 }
198
robertphillipsff0ca5e2015-07-22 11:54:44 -0700199 GrDrawContext* srcDrawContext = NULL;
robertphillipsea461502015-05-26 11:38:03 -0700200
robertphillips@google.com736dd032013-07-15 15:06:54 +0000201 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
202 GrPaint paint;
203 SkMatrix matrix;
204 matrix.setIDiv(srcTexture->width(), srcTexture->height());
robertphillips@google.com736dd032013-07-15 15:06:54 +0000205 SkRect dstRect(srcRect);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000206 if (cropToRect && i == 1) {
207 dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
208 SkRect domain;
209 matrix.mapRect(&domain, rect);
210 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
211 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
bsalomon9f876a32014-12-09 10:51:07 -0800212 SkAutoTUnref<GrFragmentProcessor> fp( GrTextureDomainEffect::Create(
joshualitt5f10b5c2015-07-09 10:24:35 -0700213 paint.getProcessorDataManager(),
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000214 srcTexture,
215 matrix,
216 domain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000217 GrTextureDomain::kDecal_Mode,
humper@google.comb86add12013-07-25 18:49:07 +0000218 GrTextureParams::kBilerp_FilterMode));
bsalomonac856c92015-08-27 06:30:17 -0700219 paint.addColorFragmentProcessor(fp);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000220 } else {
humper@google.comb86add12013-07-25 18:49:07 +0000221 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
joshualittb0a8a372014-09-23 09:50:21 -0700222 paint.addColorTextureProcessor(srcTexture, matrix, params);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000223 }
robertphillips@google.com736dd032013-07-15 15:06:54 +0000224 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
225 i < scaleFactorY ? 0.5f : 1.0f);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700226
227 GrDrawContext* dstDrawContext = context->drawContext();
228 if (!dstDrawContext) {
229 return NULL;
230 }
231 dstDrawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint,
232 SkMatrix::I(), dstRect, srcRect);
233
234 srcDrawContext = dstDrawContext;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000235 srcRect = dstRect;
236 srcTexture = dstTexture;
237 SkTSwap(dstTexture, tempTexture);
238 }
239
reedb07a94f2014-11-19 05:03:18 -0800240 const SkIRect srcIRect = srcRect.roundOut();
robertphillips@google.com736dd032013-07-15 15:06:54 +0000241
robertphillipsff0ca5e2015-07-22 11:54:44 -0700242 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
joshualitt5acfea72014-08-11 13:55:34 -0700243 // launch a single non separable kernel vs two launches
robertphillipsff0ca5e2015-07-22 11:54:44 -0700244 if (sigmaX > 0.0f && sigmaY > 0.0f &&
joshualitt5acfea72014-08-11 13:55:34 -0700245 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
246 // We shouldn't be scaling because this is a small size blur
robertphillipsff0ca5e2015-07-22 11:54:44 -0700247 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000248 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
robertphillipsff0ca5e2015-07-22 11:54:44 -0700249
250 GrDrawContext* dstDrawContext = context->drawContext();
251 if (!dstDrawContext) {
252 return NULL;
253 }
254 convolve_gaussian_2d(dstDrawContext, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
joshualitt570d2f82015-02-25 13:19:48 -0800255 srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropToRect, srcIRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700256
257 srcDrawContext = dstDrawContext;
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000258 srcRect = dstRect;
robertphillipsff0ca5e2015-07-22 11:54:44 -0700259 srcTexture = dstTexture;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000260 SkTSwap(dstTexture, tempTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000261
joshualitt5acfea72014-08-11 13:55:34 -0700262 } else {
263 if (sigmaX > 0.0f) {
264 if (scaleFactorX > 1) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700265 // TODO: if we pass in the source draw context we don't need this here
266 if (!srcDrawContext) {
267 srcDrawContext = context->drawContext();
268 if (!srcDrawContext) {
269 return NULL;
270 }
271 }
272
joshualitt5acfea72014-08-11 13:55:34 -0700273 // Clear out a radius to the right of the srcRect to prevent the
274 // X convolution from reading garbage.
275 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
276 radiusX, srcIRect.height());
robertphillipsff0ca5e2015-07-22 11:54:44 -0700277 srcDrawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
joshualitt5acfea72014-08-11 13:55:34 -0700278 }
joshualitt5acfea72014-08-11 13:55:34 -0700279 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
robertphillipsff0ca5e2015-07-22 11:54:44 -0700280
281 GrDrawContext* dstDrawContext = context->drawContext();
282 if (!dstDrawContext) {
283 return NULL;
284 }
285 convolve_gaussian(dstDrawContext, dstTexture->asRenderTarget(), clip, srcRect, dstRect,
joshualitt570d2f82015-02-25 13:19:48 -0800286 srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
287 cropToRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700288
289 srcDrawContext = dstDrawContext;
joshualitt5acfea72014-08-11 13:55:34 -0700290 srcTexture = dstTexture;
291 srcRect = dstRect;
292 SkTSwap(dstTexture, tempTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000293 }
294
joshualitt5acfea72014-08-11 13:55:34 -0700295 if (sigmaY > 0.0f) {
296 if (scaleFactorY > 1 || sigmaX > 0.0f) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700297 // TODO: if we pass in the source draw context we don't need this here
298 if (!srcDrawContext) {
299 srcDrawContext = context->drawContext();
300 if (!srcDrawContext) {
301 return NULL;
302 }
303 }
304
joshualitt5acfea72014-08-11 13:55:34 -0700305 // Clear out a radius below the srcRect to prevent the Y
306 // convolution from reading garbage.
307 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
308 srcIRect.width(), radiusY);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700309 srcDrawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
joshualitt5acfea72014-08-11 13:55:34 -0700310 }
311
joshualitt5acfea72014-08-11 13:55:34 -0700312 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
robertphillipsff0ca5e2015-07-22 11:54:44 -0700313
314 GrDrawContext* dstDrawContext = context->drawContext();
315 if (!dstDrawContext) {
316 return NULL;
317 }
318 convolve_gaussian(dstDrawContext, dstTexture->asRenderTarget(), clip, srcRect,
joshualitt570d2f82015-02-25 13:19:48 -0800319 dstRect, srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
320 cropToRect);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700321
322 srcDrawContext = dstDrawContext;
joshualitt5acfea72014-08-11 13:55:34 -0700323 srcTexture = dstTexture;
324 srcRect = dstRect;
325 SkTSwap(dstTexture, tempTexture);
326 }
robertphillips@google.com736dd032013-07-15 15:06:54 +0000327 }
328
329 if (scaleFactorX > 1 || scaleFactorY > 1) {
robertphillipsff0ca5e2015-07-22 11:54:44 -0700330 SkASSERT(srcDrawContext);
331
robertphillips@google.com736dd032013-07-15 15:06:54 +0000332 // Clear one pixel to the right and below, to accommodate bilinear
333 // upsampling.
334 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
335 srcIRect.width() + 1, 1);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700336 srcDrawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000337 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
338 1, srcIRect.height());
robertphillipsff0ca5e2015-07-22 11:54:44 -0700339 srcDrawContext->clear(srcTexture->asRenderTarget(), &clearRect, 0x0, false);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000340 SkMatrix matrix;
341 matrix.setIDiv(srcTexture->width(), srcTexture->height());
robertphillips@google.com736dd032013-07-15 15:06:54 +0000342
343 GrPaint paint;
344 // FIXME: this should be mitchell, not bilinear.
humper@google.comb86add12013-07-25 18:49:07 +0000345 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
joshualittb0a8a372014-09-23 09:50:21 -0700346 paint.addColorTextureProcessor(srcTexture, matrix, params);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000347
348 SkRect dstRect(srcRect);
349 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
robertphillipsff0ca5e2015-07-22 11:54:44 -0700350
351 GrDrawContext* dstDrawContext = context->drawContext();
352 if (!dstDrawContext) {
353 return NULL;
354 }
355 dstDrawContext->drawNonAARectToRect(dstTexture->asRenderTarget(), clip, paint,
356 SkMatrix::I(), dstRect, srcRect);
357
358 srcDrawContext = dstDrawContext;
robertphillips@google.com736dd032013-07-15 15:06:54 +0000359 srcRect = dstRect;
360 srcTexture = dstTexture;
361 SkTSwap(dstTexture, tempTexture);
362 }
robertphillipsff0ca5e2015-07-22 11:54:44 -0700363
bsalomone3059732014-10-14 11:47:22 -0700364 return SkRef(srcTexture);
robertphillips@google.com736dd032013-07-15 15:06:54 +0000365}
366#endif
367
robertphillips@google.comcce41022013-07-15 15:47:10 +0000368}