| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 The Android Open Source Project | 2 * Copyright 2011 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
| 9 #include "SkBlurImageFilter.h" | 9 #include "SkBlurImageFilter.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 75 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
| 76 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { | 76 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { |
| 77 return false; | 77 return false; |
| 78 } | 78 } |
| 79 | 79 |
| 80 if (src.colorType() != kN32_SkColorType) { | 80 if (src.colorType() != kN32_SkColorType) { |
| 81 return false; | 81 return false; |
| 82 } | 82 } |
| 83 | 83 |
| 84 SkIRect srcBounds, dstBounds; | 84 SkIRect srcBounds, dstBounds; |
| 85 if (!this->applyCropRect(ctx, src, srcOffset, &dstBounds, &srcBounds)) { | 85 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) { |
| 86 return false; | 86 return false; |
| 87 } | 87 } |
| 88 | 88 |
| 89 SkAutoLockPixels alp(src); | 89 SkAutoLockPixels alp(src); |
| 90 if (!src.getPixels()) { | 90 if (!src.getPixels()) { |
| 91 return false; | 91 return false; |
| 92 } | 92 } |
| 93 | 93 |
| 94 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dst
Bounds.height())); | 94 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(srcBounds.width(), src
Bounds.height())); |
| 95 if (!device) { | 95 if (!device) { |
| 96 return false; | 96 return false; |
| 97 } | 97 } |
| 98 *dst = device->accessBitmap(false); | 98 *dst = device->accessBitmap(false); |
| 99 SkAutoLockPixels alp_dst(*dst); | 99 SkAutoLockPixels alp_dst(*dst); |
| 100 dst->getBounds(&dstBounds); |
| 100 | 101 |
| 101 SkVector sigma = mapSigma(fSigma, ctx.ctm()); | 102 SkVector sigma = mapSigma(fSigma, ctx.ctm()); |
| 102 | 103 |
| 103 int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; | 104 int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; |
| 104 int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; | 105 int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; |
| 105 getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffs
etX); | 106 getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffs
etX); |
| 106 getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffs
etY); | 107 getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffs
etY); |
| 107 | 108 |
| 108 if (kernelSizeX < 0 || kernelSizeY < 0) { | 109 if (kernelSizeX < 0 || kernelSizeY < 0) { |
| 109 return false; | 110 return false; |
| 110 } | 111 } |
| 111 | 112 |
| 112 if (kernelSizeX == 0 && kernelSizeY == 0) { | 113 if (kernelSizeX == 0 && kernelSizeY == 0) { |
| 113 src.copyTo(dst, dst->colorType()); | 114 src.copyTo(dst, dst->colorType()); |
| 114 offset->fX = dstBounds.fLeft; | 115 offset->fX = srcBounds.fLeft; |
| 115 offset->fY = dstBounds.fTop; | 116 offset->fY = srcBounds.fTop; |
| 116 return true; | 117 return true; |
| 117 } | 118 } |
| 118 | 119 |
| 119 SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(), dst-
>height())); | 120 SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(), dst-
>height())); |
| 120 if (!tempDevice) { | 121 if (!tempDevice) { |
| 121 return false; | 122 return false; |
| 122 } | 123 } |
| 123 SkBitmap temp = tempDevice->accessBitmap(false); | 124 SkBitmap temp = tempDevice->accessBitmap(false); |
| 124 SkAutoLockPixels alpTemp(temp); | 125 SkAutoLockPixels alpTemp(temp); |
| 125 | 126 |
| 126 offset->fX = dstBounds.fLeft; | 127 offset->fX = srcBounds.fLeft; |
| 127 offset->fY = dstBounds.fTop; | 128 offset->fY = srcBounds.fTop; |
| 129 srcBounds.offset(-srcOffset); |
| 130 const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top()); |
| 128 SkPMColor* t = temp.getAddr32(0, 0); | 131 SkPMColor* t = temp.getAddr32(0, 0); |
| 129 SkPMColor* d = dst->getAddr32(0, 0); | 132 SkPMColor* d = dst->getAddr32(0, 0); |
| 130 int w = dstBounds.width(), h = dstBounds.height(); | 133 int w = dstBounds.width(), h = dstBounds.height(); |
| 131 const SkPMColor* s = src.getAddr32(srcBounds.x() - srcOffset.x(), srcBounds.
y() - srcOffset.y()); | |
| 132 srcBounds.offset(-dstBounds.x(), -dstBounds.y()); | |
| 133 dstBounds.offset(-dstBounds.x(), -dstBounds.y()); | |
| 134 SkIRect srcBoundsT = SkIRect::MakeLTRB(srcBounds.top(), srcBounds.left(), sr
cBounds.bottom(), srcBounds.right()); | |
| 135 SkIRect dstBoundsT = SkIRect::MakeWH(dstBounds.height(), dstBounds.width()); | |
| 136 int sw = src.rowBytesAsPixels(); | 134 int sw = src.rowBytesAsPixels(); |
| 137 | 135 |
| 138 /** | 136 /** |
| 139 * | 137 * |
| 140 * In order to make memory accesses cache-friendly, we reorder the passes to | 138 * In order to make memory accesses cache-friendly, we reorder the passes to |
| 141 * use contiguous memory reads wherever possible. | 139 * use contiguous memory reads wherever possible. |
| 142 * | 140 * |
| 143 * For example, the 6 passes of the X-and-Y blur case are rewritten as | 141 * For example, the 6 passes of the X-and-Y blur case are rewritten as |
| 144 * follows. Instead of 3 passes in X and 3 passes in Y, we perform | 142 * follows. Instead of 3 passes in X and 3 passes in Y, we perform |
| 145 * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X, | 143 * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X, |
| 146 * then 1 pass in X transposed to Y on write. | 144 * then 1 pass in X transposed to Y on write. |
| 147 * | 145 * |
| 148 * +----+ +----+ +----+ +---+ +---+ +---+
+----+ | 146 * +----+ +----+ +----+ +---+ +---+ +---+
+----+ |
| 149 * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | ---
--> | AB | | 147 * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | ---
--> | AB | |
| 150 * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blu
rXY +----+ | 148 * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blu
rXY +----+ |
| 151 * +---+ +---+ +---+ | 149 * +---+ +---+ +---+ |
| 152 * | 150 * |
| 153 * In this way, two of the y-blurs become x-blurs applied to transposed | 151 * In this way, two of the y-blurs become x-blurs applied to transposed |
| 154 * images, and all memory reads are contiguous. | 152 * images, and all memory reads are contiguous. |
| 155 */ | 153 */ |
| 156 if (kernelSizeX > 0 && kernelSizeY > 0) { | 154 if (kernelSizeX > 0 && kernelSizeY > 0) { |
| 157 SkOpts::box_blur_xx(s, sw, srcBounds, t, kernelSizeX, lowOffsetX, hi
ghOffsetX, w, h); | 155 SkOpts::box_blur_xx(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w
, h); |
| 158 SkOpts::box_blur_xx(t, w, dstBounds, d, kernelSizeX, highOffsetX, lo
wOffsetX, w, h); | 156 SkOpts::box_blur_xx(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w
, h); |
| 159 SkOpts::box_blur_xy(d, w, dstBounds, t, kernelSizeX3, highOffsetX, hi
ghOffsetX, w, h); | 157 SkOpts::box_blur_xy(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w
, h); |
| 160 SkOpts::box_blur_xx(t, h, dstBoundsT, d, kernelSizeY, lowOffsetY, hi
ghOffsetY, h, w); | 158 SkOpts::box_blur_xx(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h
, w); |
| 161 SkOpts::box_blur_xx(d, h, dstBoundsT, t, kernelSizeY, highOffsetY, lo
wOffsetY, h, w); | 159 SkOpts::box_blur_xx(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h
, w); |
| 162 SkOpts::box_blur_xy(t, h, dstBoundsT, d, kernelSizeY3, highOffsetY, hi
ghOffsetY, h, w); | 160 SkOpts::box_blur_xy(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h
, w); |
| 163 } else if (kernelSizeX > 0) { | 161 } else if (kernelSizeX > 0) { |
| 164 SkOpts::box_blur_xx(s, sw, srcBounds, d, kernelSizeX, lowOffsetX, hi
ghOffsetX, w, h); | 162 SkOpts::box_blur_xx(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w
, h); |
| 165 SkOpts::box_blur_xx(d, w, dstBounds, t, kernelSizeX, highOffsetX, lo
wOffsetX, w, h); | 163 SkOpts::box_blur_xx(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w
, h); |
| 166 SkOpts::box_blur_xx(t, w, dstBounds, d, kernelSizeX3, highOffsetX, hi
ghOffsetX, w, h); | 164 SkOpts::box_blur_xx(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w
, h); |
| 167 } else if (kernelSizeY > 0) { | 165 } else if (kernelSizeY > 0) { |
| 168 SkOpts::box_blur_yx(s, sw, srcBoundsT, d, kernelSizeY, lowOffsetY, hi
ghOffsetY, h, w); | 166 SkOpts::box_blur_yx(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h
, w); |
| 169 SkOpts::box_blur_xx(d, h, dstBoundsT, t, kernelSizeY, highOffsetY, lo
wOffsetY, h, w); | 167 SkOpts::box_blur_xx(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h
, w); |
| 170 SkOpts::box_blur_xy(t, h, dstBoundsT, d, kernelSizeY3, highOffsetY, hi
ghOffsetY, h, w); | 168 SkOpts::box_blur_xy(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h
, w); |
| 171 } | 169 } |
| 172 return true; | 170 return true; |
| 173 } | 171 } |
| 174 | 172 |
| 175 | 173 |
| 176 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const
{ | 174 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const
{ |
| 177 if (this->getInput(0)) { | 175 if (this->getInput(0)) { |
| 178 this->getInput(0)->computeFastBounds(src, dst); | 176 this->getInput(0)->computeFastBounds(src, dst); |
| 179 } else { | 177 } else { |
| 180 *dst = src; | 178 *dst = src; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 str->appendf("SkBlurImageFilter: ("); | 237 str->appendf("SkBlurImageFilter: ("); |
| 240 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight); | 238 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight); |
| 241 | 239 |
| 242 if (this->getInput(0)) { | 240 if (this->getInput(0)) { |
| 243 this->getInput(0)->toString(str); | 241 this->getInput(0)->toString(str); |
| 244 } | 242 } |
| 245 | 243 |
| 246 str->append("))"); | 244 str->append("))"); |
| 247 } | 245 } |
| 248 #endif | 246 #endif |
| OLD | NEW |