1736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com/*
2736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com * Copyright 2013 Google Inc.
3736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com *
4736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
5736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com * found in the LICENSE file.
6736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com */
7736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
8736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkGpuBlurUtils.h"
9736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
10736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkRect.h"
11736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
12736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#if SK_SUPPORT_GPU
13736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "effects/GrConvolutionEffect.h"
14907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org#include "effects/GrTextureDomain.h"
15736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "GrContext.h"
16736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#endif
17736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
18736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.comnamespace SkGpuBlurUtils {
19736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
20736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#if SK_SUPPORT_GPU
21736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
22736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#define MAX_BLUR_SIGMA 4.0f
23736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
24736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.comstatic void scale_rect(SkRect* rect, float xScale, float yScale) {
254b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rect->fLeft   = SkScalarMul(rect->fLeft,   xScale);
264b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rect->fTop    = SkScalarMul(rect->fTop,    yScale);
274b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rect->fRight  = SkScalarMul(rect->fRight,  xScale);
284b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rect->fBottom = SkScalarMul(rect->fBottom, yScale);
29736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com}
30736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
3109843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.orgstatic float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) {
32736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    *scaleFactor = 1;
33736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    while (sigma > MAX_BLUR_SIGMA) {
34736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        *scaleFactor *= 2;
35736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        sigma *= 0.5f;
3609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org        if (*scaleFactor > maxTextureSize) {
3709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org            *scaleFactor = maxTextureSize;
3809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org            sigma = MAX_BLUR_SIGMA;
3909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org        }
40736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
41736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    *radius = static_cast<int>(ceilf(sigma * 3.0f));
4296ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org    SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
43736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    return sigma;
44736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com}
45736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
46d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.orgstatic void convolve_gaussian_pass(GrContext* context,
47d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   const SkRect& srcRect,
48d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   const SkRect& dstRect,
49d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   GrTexture* texture,
50d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   Gr1DKernelEffect::Direction direction,
51d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   int radius,
52d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   float sigma,
53d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   bool useBounds,
54d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                                   float bounds[2]) {
55d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    GrPaint paint;
56d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    paint.reset();
57d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(
58d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        texture, direction, radius, sigma, useBounds, bounds));
59d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    paint.reset();
60d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    paint.addColorEffect(conv);
61d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    context->drawRectToRect(paint, dstRect, srcRect);
62d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org}
63d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org
64736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.comstatic void convolve_gaussian(GrContext* context,
65194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                              const SkRect& srcRect,
66194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                              const SkRect& dstRect,
67d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                              GrTexture* texture,
68d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                              Gr1DKernelEffect::Direction direction,
69736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                              int radius,
70d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                              float sigma,
71d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                              bool cropToSrcRect) {
72e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org    float bounds[2] = { 0.0f, 1.0f };
73d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    if (!cropToSrcRect) {
74d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian_pass(context, srcRect, dstRect, texture,
75d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          direction, radius, sigma, false, bounds);
76d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        return;
77d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    }
78d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
79d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
80d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
81d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkScalar size;
82d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    SkScalar rad = SkIntToScalar(radius);
83d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    if (direction == Gr1DKernelEffect::kX_Direction) {
84d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
85d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
86d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        size = srcRect.width();
87d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        lowerSrcRect.fRight = srcRect.left() + rad;
88d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        lowerDstRect.fRight = dstRect.left() + rad;
89d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        upperSrcRect.fLeft = srcRect.right() - rad;
90d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        upperDstRect.fLeft = dstRect.right() - rad;
91d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        middleSrcRect.inset(rad, 0);
92d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        middleDstRect.inset(rad, 0);
93d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    } else {
94d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
95d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
96d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        size = srcRect.height();
97d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        lowerSrcRect.fBottom = srcRect.top() + rad;
98d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        lowerDstRect.fBottom = dstRect.top() + rad;
99d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        upperSrcRect.fTop = srcRect.bottom() - rad;
100d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        upperDstRect.fTop = dstRect.bottom() - rad;
101d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        middleSrcRect.inset(0, rad);
102d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        middleDstRect.inset(0, rad);
103d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    }
104d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    if (radius >= size * SK_ScalarHalf) {
105d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        // Blur radius covers srcRect; use bounds over entire draw
106d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian_pass(context, srcRect, dstRect, texture,
107d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          direction, radius, sigma, true, bounds);
108d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org    } else {
109d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        // Draw upper and lower margins with bounds; middle without.
110d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture,
111d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          direction, radius, sigma, true, bounds);
112d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture,
113d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          direction, radius, sigma, true, bounds);
114d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture,
115d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          direction, radius, sigma, false, bounds);
116194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
117736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com}
118736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
119736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.comGrTexture* GaussianBlur(GrContext* context,
120736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                        GrTexture* srcTexture,
121736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                        bool canClobberSrc,
122736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                        const SkRect& rect,
123194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                        bool cropToRect,
124977409aceb949a9e834a9fb181a0581792d044cfskia.committer@gmail.com                        float sigmaX,
125736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                        float sigmaY) {
12696ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org    SkASSERT(NULL != context);
127736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
128736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrContext::AutoRenderTarget art(context);
129736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
130736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrContext::AutoMatrix am;
131736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    am.setIdentity(context);
132736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
133736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    SkIRect clearRect;
134736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    int scaleFactorX, radiusX;
135736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    int scaleFactorY, radiusY;
13609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    int maxTextureSize = context->getMaxTextureSize();
13709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
13809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
139736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
140736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    SkRect srcRect(rect);
141736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
142736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    srcRect.roundOut();
143736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
144736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                         static_cast<float>(scaleFactorY));
145736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
146194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));
147736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
14896ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org    SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
149736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
150736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com             kAlpha_8_GrPixelConfig == srcTexture->config());
151736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
152736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrTextureDesc desc;
153736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
154736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    desc.fWidth = SkScalarFloorToInt(srcRect.width());
155736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    desc.fHeight = SkScalarFloorToInt(srcRect.height());
156736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    desc.fConfig = srcTexture->config();
157736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
158736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrAutoScratchTexture temp1, temp2;
159736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrTexture* dstTexture = temp1.set(context, desc);
160736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
161736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    if (NULL == dstTexture || NULL == tempTexture) {
162736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        return NULL;
163736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
164736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
165736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
166736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        GrPaint paint;
167736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkMatrix matrix;
168736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        matrix.setIDiv(srcTexture->width(), srcTexture->height());
169736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->setRenderTarget(dstTexture->asRenderTarget());
170736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkRect dstRect(srcRect);
171194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        if (cropToRect && i == 1) {
172194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
173194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            SkRect domain;
174194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            matrix.mapRect(&domain, rect);
175194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
176194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
177194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
178194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                srcTexture,
179194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                matrix,
180194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                domain,
181907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org                GrTextureDomain::kDecal_Mode,
182b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                GrTextureParams::kBilerp_FilterMode));
183194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            paint.addColorEffect(effect);
184194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        } else {
185b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
186194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org            paint.addColorTextureEffect(srcTexture, matrix, params);
187194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        }
188736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
189736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                             i < scaleFactorY ? 0.5f : 1.0f);
190736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->drawRectToRect(paint, dstRect, srcRect);
191736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcRect = dstRect;
192736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcTexture = dstTexture;
193736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkTSwap(dstTexture, tempTexture);
194736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
195736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
196736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    SkIRect srcIRect;
197736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    srcRect.roundOut(&srcIRect);
198736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
199736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    if (sigmaX > 0.0f) {
200736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        if (scaleFactorX > 1) {
201736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            // Clear out a radius to the right of the srcRect to prevent the
202736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            // X convolution from reading garbage.
203736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
204736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                                          radiusX, srcIRect.height());
20556ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com            context->clear(&clearRect, 0x0, false);
206736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        }
207736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->setRenderTarget(dstTexture->asRenderTarget());
208194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
209d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian(context, srcRect, dstRect, srcTexture,
210d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
211736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcTexture = dstTexture;
212194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        srcRect = dstRect;
213736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkTSwap(dstTexture, tempTexture);
214736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
215736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
216736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    if (sigmaY > 0.0f) {
217736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        if (scaleFactorY > 1 || sigmaX > 0.0f) {
218736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            // Clear out a radius below the srcRect to prevent the Y
219736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            // convolution from reading garbage.
220736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
221736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                                          srcIRect.width(), radiusY);
22256ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com            context->clear(&clearRect, 0x0, false);
223736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        }
224736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
225736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->setRenderTarget(dstTexture->asRenderTarget());
226194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
227d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org        convolve_gaussian(context, srcRect, dstRect, srcTexture,
228d71732a5baf4a0a1d912b27ded5360c7e82656c3senorblanco@chromium.org                          Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
229736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcTexture = dstTexture;
230194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        srcRect = dstRect;
231736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkTSwap(dstTexture, tempTexture);
232736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
233736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
234736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    if (scaleFactorX > 1 || scaleFactorY > 1) {
235736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        // Clear one pixel to the right and below, to accommodate bilinear
236736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        // upsampling.
237736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
238736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                                      srcIRect.width() + 1, 1);
23956ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com        context->clear(&clearRect, 0x0, false);
240736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
241736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com                                      1, srcIRect.height());
24256ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com        context->clear(&clearRect, 0x0, false);
243736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkMatrix matrix;
244736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        matrix.setIDiv(srcTexture->width(), srcTexture->height());
245736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->setRenderTarget(dstTexture->asRenderTarget());
246736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
247736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        GrPaint paint;
248736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        // FIXME:  this should be mitchell, not bilinear.
249b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
250736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        paint.addColorTextureEffect(srcTexture, matrix, params);
251736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
252736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkRect dstRect(srcRect);
253736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
254736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        context->drawRectToRect(paint, dstRect, srcRect);
255736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcRect = dstRect;
256736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcTexture = dstTexture;
257736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        SkTSwap(dstTexture, tempTexture);
258736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
259736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    if (srcTexture == temp1.texture()) {
260736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        return temp1.detach();
261736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    } else if (srcTexture == temp2.texture()) {
262736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        return temp2.detach();
263736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    } else {
264736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        srcTexture->ref();
265736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com        return srcTexture;
266736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    }
267736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com}
268736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#endif
269736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com
270cce4102f3127cbabfb18f49ffa27e22d1207d96erobertphillips@google.com}
271