| Index: src/opts/SkBlurImageFilter_opts.h
|
| diff --git a/src/opts/SkBlurImageFilter_opts.h b/src/opts/SkBlurImageFilter_opts.h
|
| index 720130b1ecf032f303ee50bc67f3ed7ef365aa4a..8d22391b5fe1cbdd69b7082876657f2565c7bd8b 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>,
|
|
|