Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 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 "SkBlurUtils.h" | |
| 9 #include "SkRect.h" | |
|
tfarina
2013/07/13 22:19:30
can we have a blank line separating these?
robertphillips
2013/07/15 12:05:04
Done.
| |
| 10 | |
| 11 #if SK_SUPPORT_GPU | |
| 12 #include "effects\GrConvolutionEffect.h" | |
|
tfarina
2013/07/13 22:19:30
is effects necessary here? I think we don't use fu
robertphillips
2013/07/15 12:05:04
GrConvolutionEffect.h lives in src\gpu\effects. sr
| |
| 13 #include "GrContext.h" | |
| 14 #endif | |
| 15 | |
| 16 namespace SkBlurUtils { | |
| 17 | |
| 18 #if SK_SUPPORT_GPU | |
| 19 | |
| 20 #define MAX_BLUR_SIGMA 4.0f | |
| 21 | |
| 22 static void scale_rect(SkRect* rect, float xScale, float yScale) { | |
| 23 rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale)); | |
| 24 rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale)); | |
| 25 rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale)); | |
| 26 rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale)); | |
| 27 } | |
| 28 | |
| 29 static float adjust_sigma(float sigma, int *scaleFactor, int *radius) { | |
| 30 *scaleFactor = 1; | |
| 31 while (sigma > MAX_BLUR_SIGMA) { | |
| 32 *scaleFactor *= 2; | |
| 33 sigma *= 0.5f; | |
| 34 } | |
| 35 *radius = static_cast<int>(ceilf(sigma * 3.0f)); | |
| 36 GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius); | |
| 37 return sigma; | |
| 38 } | |
| 39 | |
| 40 static void convolve_gaussian(GrContext* context, | |
| 41 GrTexture* texture, | |
| 42 const SkRect& rect, | |
| 43 float sigma, | |
| 44 int radius, | |
| 45 Gr1DKernelEffect::Direction direction) { | |
| 46 GrPaint paint; | |
| 47 | |
| 48 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture, | |
| 49 direction , | |
| 50 radius, | |
| 51 sigma)); | |
| 52 paint.addColorEffect(conv); | |
| 53 context->drawRect(paint, rect); | |
| 54 } | |
| 55 | |
| 56 GrTexture* GaussianBlur(GrContext* context, | |
| 57 GrTexture* srcTexture, | |
| 58 bool canClobberSrc, | |
| 59 const SkRect& rect, | |
| 60 float sigmaX, | |
| 61 float sigmaY) { | |
| 62 GrAssert(NULL != context); | |
| 63 | |
| 64 GrContext::AutoRenderTarget art(context); | |
| 65 | |
| 66 GrContext::AutoMatrix am; | |
| 67 am.setIdentity(context); | |
| 68 | |
| 69 SkIRect clearRect; | |
| 70 int scaleFactorX, radiusX; | |
| 71 int scaleFactorY, radiusY; | |
| 72 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX); | |
| 73 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY); | |
| 74 | |
| 75 SkRect srcRect(rect); | |
| 76 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | |
| 77 srcRect.roundOut(); | |
| 78 scale_rect(&srcRect, static_cast<float>(scaleFactorX), | |
| 79 static_cast<float>(scaleFactorY)); | |
| 80 | |
| 81 GrContext::AutoClip acs(context, srcRect); | |
| 82 | |
| 83 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() || | |
| 84 kRGBA_8888_GrPixelConfig == srcTexture->config() || | |
| 85 kAlpha_8_GrPixelConfig == srcTexture->config()); | |
| 86 | |
| 87 GrTextureDesc desc; | |
| 88 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; | |
| 89 desc.fWidth = SkScalarFloorToInt(srcRect.width()); | |
| 90 desc.fHeight = SkScalarFloorToInt(srcRect.height()); | |
| 91 desc.fConfig = srcTexture->config(); | |
| 92 | |
| 93 GrAutoScratchTexture temp1, temp2; | |
| 94 GrTexture* dstTexture = temp1.set(context, desc); | |
| 95 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c); | |
| 96 if (NULL == dstTexture || NULL == tempTexture) { | |
| 97 return NULL; | |
| 98 } | |
| 99 | |
| 100 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { | |
| 101 GrPaint paint; | |
| 102 SkMatrix matrix; | |
| 103 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | |
| 104 context->setRenderTarget(dstTexture->asRenderTarget()); | |
| 105 SkRect dstRect(srcRect); | |
| 106 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, | |
| 107 i < scaleFactorY ? 0.5f : 1.0f); | |
| 108 GrTextureParams params(SkShader::kClamp_TileMode, true); | |
| 109 paint.addColorTextureEffect(srcTexture, matrix, params); | |
| 110 context->drawRectToRect(paint, dstRect, srcRect); | |
| 111 srcRect = dstRect; | |
| 112 srcTexture = dstTexture; | |
| 113 SkTSwap(dstTexture, tempTexture); | |
| 114 } | |
| 115 | |
| 116 SkIRect srcIRect; | |
| 117 srcRect.roundOut(&srcIRect); | |
| 118 | |
| 119 if (sigmaX > 0.0f) { | |
| 120 if (scaleFactorX > 1) { | |
| 121 // Clear out a radius to the right of the srcRect to prevent the | |
| 122 // X convolution from reading garbage. | |
| 123 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | |
| 124 radiusX, srcIRect.height()); | |
| 125 context->clear(&clearRect, 0x0); | |
| 126 } | |
| 127 context->setRenderTarget(dstTexture->asRenderTarget()); | |
| 128 convolve_gaussian(context, srcTexture, srcRect, sigmaX, radiusX, | |
| 129 Gr1DKernelEffect::kX_Direction); | |
| 130 srcTexture = dstTexture; | |
| 131 SkTSwap(dstTexture, tempTexture); | |
| 132 } | |
| 133 | |
| 134 if (sigmaY > 0.0f) { | |
| 135 if (scaleFactorY > 1 || sigmaX > 0.0f) { | |
| 136 // Clear out a radius below the srcRect to prevent the Y | |
| 137 // convolution from reading garbage. | |
| 138 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | |
| 139 srcIRect.width(), radiusY); | |
| 140 context->clear(&clearRect, 0x0); | |
| 141 } | |
| 142 | |
| 143 context->setRenderTarget(dstTexture->asRenderTarget()); | |
| 144 convolve_gaussian(context, srcTexture, srcRect, sigmaY, radiusY, | |
| 145 Gr1DKernelEffect::kY_Direction); | |
| 146 srcTexture = dstTexture; | |
| 147 SkTSwap(dstTexture, tempTexture); | |
| 148 } | |
| 149 | |
| 150 if (scaleFactorX > 1 || scaleFactorY > 1) { | |
| 151 // Clear one pixel to the right and below, to accommodate bilinear | |
| 152 // upsampling. | |
| 153 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | |
| 154 srcIRect.width() + 1, 1); | |
| 155 context->clear(&clearRect, 0x0); | |
| 156 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | |
| 157 1, srcIRect.height()); | |
| 158 context->clear(&clearRect, 0x0); | |
| 159 SkMatrix matrix; | |
| 160 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | |
| 161 context->setRenderTarget(dstTexture->asRenderTarget()); | |
| 162 | |
| 163 GrPaint paint; | |
| 164 // FIXME: this should be mitchell, not bilinear. | |
| 165 GrTextureParams params(SkShader::kClamp_TileMode, true); | |
| 166 paint.addColorTextureEffect(srcTexture, matrix, params); | |
| 167 | |
| 168 SkRect dstRect(srcRect); | |
| 169 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); | |
| 170 context->drawRectToRect(paint, dstRect, srcRect); | |
| 171 srcRect = dstRect; | |
| 172 srcTexture = dstTexture; | |
| 173 SkTSwap(dstTexture, tempTexture); | |
| 174 } | |
| 175 if (srcTexture == temp1.texture()) { | |
| 176 return temp1.detach(); | |
| 177 } else if (srcTexture == temp2.texture()) { | |
| 178 return temp2.detach(); | |
| 179 } else { | |
| 180 srcTexture->ref(); | |
| 181 return srcTexture; | |
| 182 } | |
| 183 } | |
| 184 #endif | |
| 185 | |
| 186 }; | |
|
tfarina
2013/07/13 22:19:30
no need of ; here.
I'd just write:
} // namespa
robertphillips
2013/07/15 12:05:04
Done.
| |
| OLD | NEW |