158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/*
258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Copyright 2013 Google Inc.
358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger *
458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * found in the LICENSE file.
658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkGpuBlurUtils.h"
958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkRect.h"
1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#if SK_SUPPORT_GPU
1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "effects/GrConvolutionEffect.h"
1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "effects/GrTextureDomainEffect.h"
1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "GrContext.h"
1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#endif
1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergernamespace SkGpuBlurUtils {
1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#if SK_SUPPORT_GPU
2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#define MAX_BLUR_SIGMA 4.0f
2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void scale_rect(SkRect* rect, float xScale, float yScale) {
2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    rect->fLeft   = SkScalarMul(rect->fLeft,   SkFloatToScalar(xScale));
2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    rect->fTop    = SkScalarMul(rect->fTop,    SkFloatToScalar(yScale));
2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    rect->fRight  = SkScalarMul(rect->fRight,  SkFloatToScalar(xScale));
2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    *scaleFactor = 1;
3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    while (sigma > MAX_BLUR_SIGMA) {
3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        *scaleFactor *= 2;
3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        sigma *= 0.5f;
3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    *radius = static_cast<int>(ceilf(sigma * 3.0f));
3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return sigma;
4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
42e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void convolve_gaussian_pass(GrContext* context,
43e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   const SkRect& srcRect,
44e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   const SkRect& dstRect,
45e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   GrTexture* texture,
46e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   Gr1DKernelEffect::Direction direction,
47e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   int radius,
48e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   float sigma,
49e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   bool useBounds,
50e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                   float bounds[2]) {
51e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    GrPaint paint;
52e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    paint.reset();
53e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(
54e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        texture, direction, radius, sigma, useBounds, bounds));
55e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    paint.reset();
56e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    paint.addColorEffect(conv);
57e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    context->drawRectToRect(paint, dstRect, srcRect);
58e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
59e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void convolve_gaussian(GrContext* context,
6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                              const SkRect& srcRect,
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                              const SkRect& dstRect,
63e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                              GrTexture* texture,
64e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                              Gr1DKernelEffect::Direction direction,
6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                              int radius,
66e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                              float sigma,
67e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                              bool cropToSrcRect) {
68e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    float bounds[2] = { 0.0f, 1.0f };
69e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (!cropToSrcRect) {
70e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian_pass(context, srcRect, dstRect, texture,
71e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          direction, radius, sigma, false, bounds);
72e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return;
73e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
74e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
75e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
76e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
77e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkScalar size;
78e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkScalar rad = SkIntToScalar(radius);
79e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (direction == Gr1DKernelEffect::kX_Direction) {
80e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
81e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
82e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        size = srcRect.width();
83e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        lowerSrcRect.fRight = srcRect.left() + rad;
84e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        lowerDstRect.fRight = dstRect.left() + rad;
85e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        upperSrcRect.fLeft = srcRect.right() - rad;
86e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        upperDstRect.fLeft = dstRect.right() - rad;
87e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        middleSrcRect.inset(rad, 0);
88e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        middleDstRect.inset(rad, 0);
89e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    } else {
90e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
91e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
92e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        size = srcRect.height();
93e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        lowerSrcRect.fBottom = srcRect.top() + rad;
94e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        lowerDstRect.fBottom = dstRect.top() + rad;
95e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        upperSrcRect.fTop = srcRect.bottom() - rad;
96e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        upperDstRect.fTop = dstRect.bottom() - rad;
97e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        middleSrcRect.inset(0, rad);
98e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        middleDstRect.inset(0, rad);
99e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
100e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (radius >= size * SK_ScalarHalf) {
101e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        // Blur radius covers srcRect; use bounds over entire draw
102e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian_pass(context, srcRect, dstRect, texture,
103e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          direction, radius, sigma, true, bounds);
104e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    } else {
105e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        // Draw upper and lower margins with bounds; middle without.
106e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture,
107e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          direction, radius, sigma, true, bounds);
108e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture,
109e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          direction, radius, sigma, true, bounds);
110e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture,
111e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          direction, radius, sigma, false, bounds);
11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerGrTexture* GaussianBlur(GrContext* context,
11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        GrTexture* srcTexture,
11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        bool canClobberSrc,
11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        const SkRect& rect,
11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        bool cropToRect,
12058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        float sigmaX,
12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                        float sigmaY) {
12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrAssert(NULL != context);
12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrContext::AutoRenderTarget art(context);
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrContext::AutoMatrix am;
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    am.setIdentity(context);
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkIRect clearRect;
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int scaleFactorX, radiusX;
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int scaleFactorY, radiusY;
13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkRect srcRect(rect);
13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    srcRect.roundOut();
13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                         static_cast<float>(scaleFactorY));
14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));
14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger             kAlpha_8_GrPixelConfig == srcTexture->config());
14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
14758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrTextureDesc desc;
14858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
14958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    desc.fWidth = SkScalarFloorToInt(srcRect.width());
15058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    desc.fHeight = SkScalarFloorToInt(srcRect.height());
15158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    desc.fConfig = srcTexture->config();
15258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
15358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrAutoScratchTexture temp1, temp2;
15458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrTexture* dstTexture = temp1.set(context, desc);
15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
15658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (NULL == dstTexture || NULL == tempTexture) {
15758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
15858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
15958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
16058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
16158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrPaint paint;
16258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkMatrix matrix;
16358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        matrix.setIDiv(srcTexture->width(), srcTexture->height());
16458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->setRenderTarget(dstTexture->asRenderTarget());
16558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkRect dstRect(srcRect);
16658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (cropToRect && i == 1) {
16758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
16858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkRect domain;
16958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            matrix.mapRect(&domain, rect);
17058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
17158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
17258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
17358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                srcTexture,
17458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                matrix,
17558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                domain,
17658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                GrTextureDomainEffect::kDecal_WrapMode,
17758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                GrTextureParams::kBilerp_FilterMode));
17858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            paint.addColorEffect(effect);
17958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        } else {
18058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
18158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            paint.addColorTextureEffect(srcTexture, matrix, params);
18258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
18358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
18458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                             i < scaleFactorY ? 0.5f : 1.0f);
18558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->drawRectToRect(paint, dstRect, srcRect);
18658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcRect = dstRect;
18758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcTexture = dstTexture;
18858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkTSwap(dstTexture, tempTexture);
18958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
19058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
19158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkIRect srcIRect;
19258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    srcRect.roundOut(&srcIRect);
19358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (sigmaX > 0.0f) {
19558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (scaleFactorX > 1) {
19658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            // Clear out a radius to the right of the srcRect to prevent the
19758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            // X convolution from reading garbage.
19858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
19958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                          radiusX, srcIRect.height());
20058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            context->clear(&clearRect, 0x0);
20158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
20258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->setRenderTarget(dstTexture->asRenderTarget());
20358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
204e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian(context, srcRect, dstRect, srcTexture,
205e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
20658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcTexture = dstTexture;
20758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcRect = dstRect;
20858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkTSwap(dstTexture, tempTexture);
20958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
21058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
21158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (sigmaY > 0.0f) {
21258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (scaleFactorY > 1 || sigmaX > 0.0f) {
21358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            // Clear out a radius below the srcRect to prevent the Y
21458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            // convolution from reading garbage.
21558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
21658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                          srcIRect.width(), radiusY);
21758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            context->clear(&clearRect, 0x0);
21858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
21958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->setRenderTarget(dstTexture->asRenderTarget());
22158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
222e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        convolve_gaussian(context, srcRect, dstRect, srcTexture,
223e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                          Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
22458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcTexture = dstTexture;
22558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcRect = dstRect;
22658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkTSwap(dstTexture, tempTexture);
22758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
22858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (scaleFactorX > 1 || scaleFactorY > 1) {
23058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Clear one pixel to the right and below, to accommodate bilinear
23158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // upsampling.
23258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
23358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                      srcIRect.width() + 1, 1);
23458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->clear(&clearRect, 0x0);
23558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
23658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                      1, srcIRect.height());
23758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->clear(&clearRect, 0x0);
23858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkMatrix matrix;
23958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        matrix.setIDiv(srcTexture->width(), srcTexture->height());
24058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->setRenderTarget(dstTexture->asRenderTarget());
24158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
24258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrPaint paint;
24358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // FIXME:  this should be mitchell, not bilinear.
24458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
24558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        paint.addColorTextureEffect(srcTexture, matrix, params);
24658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
24758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkRect dstRect(srcRect);
24858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
24958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        context->drawRectToRect(paint, dstRect, srcRect);
25058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcRect = dstRect;
25158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcTexture = dstTexture;
25258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkTSwap(dstTexture, tempTexture);
25358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
25458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (srcTexture == temp1.texture()) {
25558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return temp1.detach();
25658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    } else if (srcTexture == temp2.texture()) {
25758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return temp2.detach();
25858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    } else {
25958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcTexture->ref();
26058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return srcTexture;
26158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
26258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
26358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#endif
26458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
26558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
266