aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/effects/GrMatrixConvolutionEffect.cpp
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-06-20 07:46:19 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-20 12:09:00 +0000
commit4e962c6c248d60fa0b382050a566eed46f0fa10a (patch)
treef8d365c5bc94d2d22cc41e161fa31b324579abb6 /src/gpu/effects/GrMatrixConvolutionEffect.cpp
parente42cef510026c8e4d1eca49ee709610633d69ff9 (diff)
Fix degenerate case handling in fill_in_2D_gaussian_kernel
Bug: 849016 Change-Id: Icc46451acd83140cb86593195947efea7f83828d Reviewed-on: https://skia-review.googlesource.com/135142 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'src/gpu/effects/GrMatrixConvolutionEffect.cpp')
-rw-r--r--src/gpu/effects/GrMatrixConvolutionEffect.cpp47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index ec2126d520..c2c1f7c8ba 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -213,19 +213,58 @@ bool GrMatrixConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) cons
fDomain == s.domain();
}
+static void fill_in_1D_gaussian_kernel_with_stride(float* kernel, int size, int stride,
+ float twoSigmaSqrd) {
+ SkASSERT(!SkScalarNearlyZero(twoSigmaSqrd, SK_ScalarNearlyZero));
+
+ const float sigmaDenom = 1.0f / twoSigmaSqrd;
+ const int radius = size / 2;
+
+ float sum = 0.0f;
+ for (int i = 0; i < size; ++i) {
+ float term = static_cast<float>(i - radius);
+ // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
+ // is dropped here, since we renormalize the kernel below.
+ kernel[i * stride] = sk_float_exp(-term * term * sigmaDenom);
+ sum += kernel[i * stride];
+ }
+ // Normalize the kernel
+ float scale = 1.0f / sum;
+ for (int i = 0; i < size; ++i) {
+ kernel[i * stride] *= scale;
+ }
+}
+
static void fill_in_2D_gaussian_kernel(float* kernel, int width, int height,
SkScalar sigmaX, SkScalar sigmaY) {
SkASSERT(width * height <= MAX_KERNEL_SIZE);
const float twoSigmaSqrdX = 2.0f * SkScalarToFloat(SkScalarSquare(sigmaX));
const float twoSigmaSqrdY = 2.0f * SkScalarToFloat(SkScalarSquare(sigmaY));
+ // TODO: in all of these degenerate cases we're uploading (and using) a whole lot of zeros.
if (SkScalarNearlyZero(twoSigmaSqrdX, SK_ScalarNearlyZero) ||
SkScalarNearlyZero(twoSigmaSqrdY, SK_ScalarNearlyZero)) {
- SkASSERT(3 == width && 3 == height);
- for (int i = 0; i < width * height; ++i) {
- kernel[i] = 0.0f;
+ // In this case the 2D Gaussian degenerates to a 1D Gaussian (in X or Y) or a point
+ SkASSERT(3 == width || 3 == height);
+ memset(kernel, 0, width*height*sizeof(float));
+
+ if (SkScalarNearlyZero(twoSigmaSqrdX, SK_ScalarNearlyZero) &&
+ SkScalarNearlyZero(twoSigmaSqrdY, SK_ScalarNearlyZero)) {
+ // A point
+ SkASSERT(3 == width && 3 == height);
+ kernel[4] = 1.0f;
+ } else if (SkScalarNearlyZero(twoSigmaSqrdX, SK_ScalarNearlyZero)) {
+ // A 1D Gaussian in Y
+ SkASSERT(3 == width);
+ // Down the middle column of the kernel with a stride of width
+ fill_in_1D_gaussian_kernel_with_stride(&kernel[1], height, width, twoSigmaSqrdY);
+ } else {
+ // A 1D Gaussian in X
+ SkASSERT(SkScalarNearlyZero(twoSigmaSqrdY, SK_ScalarNearlyZero));
+ SkASSERT(3 == height);
+ // Down the middle row of the kernel with a stride of 1
+ fill_in_1D_gaussian_kernel_with_stride(&kernel[width], width, 1, twoSigmaSqrdX);
}
- kernel[4] = 1.0f;
return;
}