aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2017-11-20 14:04:15 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-21 22:43:50 +0000
commita0ec54829eb77ec51747d2c8fd1ecfb7c0587965 (patch)
tree140d25af068b7a7e025400589ed7273b39ad98a8 /src/core
parentd46e85ff6903ca4d0d5d97bdfdde364b8559c0f4 (diff)
Eliminate the use of a tmp buffer for image blur
Because the blur_one_direction routine, only reads the source buffer once for each result, it can be used to blur inplace. This allows the code to avoid using a temporary buffer for the intermediate result. This produces the same pixels according to skdiff, and has the same speed. Change-Id: I6485a71f0eb39936d69b8a98ab429a2cf592a7cd Reviewed-on: https://skia-review.googlesource.com/74520 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBlurImageFilter.cpp68
1 files changed, 29 insertions, 39 deletions
diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp
index 2f0759cfd5..088462b964 100644
--- a/src/core/SkBlurImageFilter.cpp
+++ b/src/core/SkBlurImageFilter.cpp
@@ -459,45 +459,35 @@ static sk_sp<SkSpecialImage> combined_pass_blur(
SkSTArenaAlloc<1024> alloc;
Sk4u* buffer = alloc.makeArrayDefault<Sk4u>(std::max(bufferSizeW, bufferSizeH));
- if (windowW > 1 && windowH > 1) {
- // Blur both directions.
-
- auto tmpW = srcH,
- tmpH = dstW;
-
- auto tmp = alloc.makeArrayDefault<uint32_t>(tmpW * tmpH);
-
- // Blur horizontally, and transpose.
- blur_one_direction(
- buffer, windowW,
- srcBounds.left(), srcBounds.right(), dstBounds.right(),
- static_cast<uint32_t*>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH,
- tmp, tmpW, 1);
-
- // Blur vertically (scan in memory order because of the transposition),
- // and transpose back to the original orientation.
- blur_one_direction(
- buffer, windowH,
- srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(),
- tmp, 1, tmpW, tmpH,
- static_cast<uint32_t*>(dst.getPixels()), dst.rowBytesAsPixels(), 1);
- } else if (windowW > 1) {
- // Blur only horizontally.
-
- blur_one_direction(
- buffer, windowW,
- srcBounds.left(), srcBounds.right(), dstBounds.right(),
- static_cast<uint32_t*>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH,
- static_cast<uint32_t*>(dst.getPixels()), 1, dst.rowBytesAsPixels());
- } else if (windowH > 1) {
- // Blur only vertically.
-
- blur_one_direction(
- buffer, windowH,
- srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(),
- static_cast<uint32_t*>(src.getPixels()), src.rowBytesAsPixels(), 1, srcW,
- static_cast<uint32_t*>(dst.getPixels()), dst.rowBytesAsPixels(), 1);
- } else {
+ if (windowW > 1 || windowH > 1) {
+ auto intermediateSrc = static_cast<uint32_t *>(src.getPixels());
+ auto intermediateRowBytesAsPixels = src.rowBytesAsPixels();
+ auto intermediateWidth = srcW;
+
+ if (windowW > 1) {
+ // For the horizontal blur, start part way down in anticipation of the vertical blur.
+ // If this is a horizontal only blur, then shift will be zero.
+ auto shift = (srcBounds.top() - dstBounds.top());
+ intermediateSrc = static_cast<uint32_t *>(dst.getPixels())
+ + (shift > 0 ? shift * dst.rowBytesAsPixels() : 0);
+ intermediateRowBytesAsPixels = dst.rowBytesAsPixels();
+ intermediateWidth = dstW;
+
+ blur_one_direction(
+ buffer, windowW,
+ srcBounds.left(), srcBounds.right(), dstBounds.right(),
+ static_cast<uint32_t *>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH,
+ intermediateSrc, 1, intermediateRowBytesAsPixels);
+ }
+
+ if (windowH > 1) {
+ blur_one_direction(
+ buffer, windowH,
+ srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(),
+ intermediateSrc, intermediateRowBytesAsPixels, 1, intermediateWidth,
+ static_cast<uint32_t *>(dst.getPixels()), dst.rowBytesAsPixels(), 1);
+ }
+ } else {
// There is no blurring to do, but we still need to copy the source while accounting for the
// dstBounds. Remember that the src was intersected with the dst.
int y = 0;