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