diff options
Diffstat (limited to 'src/opts/SkBlurImageFilter_opts.h')
-rw-r--r-- | src/opts/SkBlurImageFilter_opts.h | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/src/opts/SkBlurImageFilter_opts.h b/src/opts/SkBlurImageFilter_opts.h index 720130b1ec..8d22391b5f 100644 --- a/src/opts/SkBlurImageFilter_opts.h +++ b/src/opts/SkBlurImageFilter_opts.h @@ -84,8 +84,8 @@ static inline __m128i mullo_epi32(__m128i a, __m128i b) { // Fast path for kernel sizes between 2 and 127, working on two rows at a time. template<BlurDirection srcDirection, BlurDirection dstDirection> -void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int kernelSize, - int leftOffset, int rightOffset, int width, int* height) { +int box_blur_double(const SkPMColor** src, int srcStride, const SkIRect& srcBounds, SkPMColor** dst, int kernelSize, + int leftOffset, int rightOffset, int width, int height) { // Load 2 pixels from adjacent rows. auto load_2_pixels = [&](const SkPMColor* s) { if (srcDirection == BlurDirection::kX) { @@ -99,16 +99,21 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int return vld1_u8((uint8_t*)s); } }; - int incrementStart = SkMax32(-rightOffset - 1, -width); - int incrementEnd = SkMax32(width - rightOffset - 1, 0); - int decrementStart = SkMin32(leftOffset, width); + int left = srcBounds.left(); + int right = srcBounds.right(); + int top = srcBounds.top(); + int bottom = srcBounds.bottom(); + int incrementStart = SkMax32(left - rightOffset - 1, left - right); + int incrementEnd = SkMax32(right - rightOffset - 1, 0); + int decrementStart = SkMin32(left + leftOffset, width); + int decrementEnd = SkMin32(right + leftOffset, width); const int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; - const int dstStrideX = dstDirection == BlurDirection::kX ? 1 : *height; + const int dstStrideX = dstDirection == BlurDirection::kX ? 1 : height; const int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; const int dstStrideY = dstDirection == BlurDirection::kX ? width : 1; const uint16x8_t scale = vdupq_n_u16((1 << 15) / kernelSize); - for (; *height >= 2; *height -= 2) { + for (; bottom - top >= 2; top += 2) { uint16x8_t sum = vdupq_n_u16(0); const SkPMColor* lptr = *src; const SkPMColor* rptr = *src; @@ -118,6 +123,12 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int INCREMENT_SUMS_DOUBLE(rptr); rptr += srcStrideX; } + // Clear to zero when sampling to the left our domain. "sum" is zero here because we + // initialized it above, and the preceeding loop has no effect in this case. + for (x = 0; x < incrementStart; ++x) { + STORE_SUMS_DOUBLE + dptr += dstStrideX; + } for (; x < decrementStart && x < incrementEnd; ++x) { STORE_SUMS_DOUBLE dptr += dstStrideX; @@ -136,15 +147,22 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int STORE_SUMS_DOUBLE dptr += dstStrideX; } - for (; x < width; ++x) { + for (; x < decrementEnd; ++x) { STORE_SUMS_DOUBLE dptr += dstStrideX; DECREMENT_SUMS_DOUBLE(lptr); lptr += srcStrideX; } + // Clear to zero when sampling to the right of our domain. "sum" is zero here because we + // added on then subtracted off all of the pixels, leaving zero. + for (; x < width; ++x) { + STORE_SUMS_DOUBLE + dptr += dstStrideX; + } *src += srcStrideY * 2; *dst += dstStrideY * 2; } + return top; } // ARGB -> 0A0R 0G0B @@ -166,8 +184,9 @@ static inline uint16x4_t expand(SkPMColor p) { #define DOUBLE_ROW_OPTIMIZATION \ if (1 < kernelSize && kernelSize < 128) { \ - box_blur_double<srcDirection, dstDirection>(&src, srcStride, &dst, kernelSize, \ - leftOffset, rightOffset, width, &height); \ + top = box_blur_double<srcDirection, dstDirection>(&src, srcStride, srcBounds, &dst, \ + kernelSize, leftOffset, rightOffset, \ + width, height); \ } #else // Neither NEON nor >=SSE2. @@ -200,11 +219,16 @@ static inline uint16x4_t expand(SkPMColor p) { } template<BlurDirection srcDirection, BlurDirection dstDirection> -static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSize, - int leftOffset, int rightOffset, int width, int height) { - int incrementStart = SkMax32(-rightOffset - 1, -width); - int incrementEnd = SkMax32(width - rightOffset - 1, 0); - int decrementStart = SkMin32(leftOffset, width); +static void box_blur(const SkPMColor* src, int srcStride, const SkIRect& srcBounds, SkPMColor* dst, + int kernelSize, int leftOffset, int rightOffset, int width, int height) { + int left = srcBounds.left(); + int right = srcBounds.right(); + int top = srcBounds.top(); + int bottom = srcBounds.bottom(); + int incrementStart = SkMax32(left - rightOffset - 1, left - right); + int incrementEnd = SkMax32(right - rightOffset - 1, 0); + int decrementStart = SkMin32(left + leftOffset, width); + int decrementEnd = SkMin32(right + leftOffset, width); int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; int dstStrideX = dstDirection == BlurDirection::kX ? 1 : height; int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; @@ -212,9 +236,19 @@ static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ke INIT_SCALE INIT_HALF + // Clear to zero when sampling above our domain. + for (int y = 0; y < top; y++) { + SkColor* dptr = dst; + for (int x = 0; x < width; ++x) { + *dptr = 0; + dptr += dstStrideX; + } + dst += dstStrideY; + } + DOUBLE_ROW_OPTIMIZATION - for (int y = 0; y < height; ++y) { + for (int y = top; y < bottom; ++y) { INIT_SUMS const SkPMColor* lptr = src; const SkPMColor* rptr = src; @@ -225,6 +259,11 @@ static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ke rptr += srcStrideX; PREFETCH_RPTR } + // Clear to zero when sampling to the left of our domain. + for (x = 0; x < incrementStart; ++x) { + *dptr = 0; + dptr += dstStrideX; + } for (; x < decrementStart && x < incrementEnd; ++x) { STORE_SUMS dptr += dstStrideX; @@ -245,15 +284,29 @@ static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ke STORE_SUMS dptr += dstStrideX; } - for (; x < width; ++x) { + for (; x < decrementEnd; ++x) { STORE_SUMS dptr += dstStrideX; DECREMENT_SUMS(*lptr); lptr += srcStrideX; } + // Clear to zero when sampling to the right of our domain. + for (; x < width; ++x) { + *dptr = 0; + dptr += dstStrideX; + } src += srcStrideY; dst += dstStrideY; } + // Clear to zero when sampling below our domain. + for (int y = bottom; y < height; ++y) { + SkColor* dptr = dst; + for (int x = 0; x < width; ++x) { + *dptr = 0; + dptr += dstStrideX; + } + dst += dstStrideY; + } } static auto box_blur_xx = &box_blur<BlurDirection::kX, BlurDirection::kX>, |