Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/effects/SkBlurImageFilter.cpp

Issue 1264103004: Port SkBlurImage opts to SkOpts. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rename to match src/effects Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkOpts.cpp ('k') | src/opts/SkBlurImageFilter_opts.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "SkGpuBlurUtils.h"
12 #include "SkOpts.h"
11 #include "SkReadBuffer.h" 13 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h" 14 #include "SkWriteBuffer.h"
13 #include "SkGpuBlurUtils.h"
14 #include "SkBlurImage_opts.h"
15 #if SK_SUPPORT_GPU 15 #if SK_SUPPORT_GPU
16 #include "GrContext.h" 16 #include "GrContext.h"
17 #endif 17 #endif
18 18
19 // This rather arbitrary-looking value results in a maximum box blur kernel size 19 // This rather arbitrary-looking value results in a maximum box blur kernel size
20 // of 1000 pixels on the raster path, which matches the WebKit and Firefox 20 // of 1000 pixels on the raster path, which matches the WebKit and Firefox
21 // implementations. Since the GPU path does not compute a box blur, putting 21 // implementations. Since the GPU path does not compute a box blur, putting
22 // the limit on sigma ensures consistent behaviour between the GPU and 22 // the limit on sigma ensures consistent behaviour between the GPU and
23 // raster paths. 23 // raster paths.
24 #define MAX_SIGMA SkIntToScalar(532) 24 #define MAX_SIGMA SkIntToScalar(532)
(...skipping 19 matching lines...) Expand all
44 SkScalar sigmaY = buffer.readScalar(); 44 SkScalar sigmaY = buffer.readScalar();
45 return Create(sigmaX, sigmaY, common.getInput(0), &common.cropRect()); 45 return Create(sigmaX, sigmaY, common.getInput(0), &common.cropRect());
46 } 46 }
47 47
48 void SkBlurImageFilter::flatten(SkWriteBuffer& buffer) const { 48 void SkBlurImageFilter::flatten(SkWriteBuffer& buffer) const {
49 this->INHERITED::flatten(buffer); 49 this->INHERITED::flatten(buffer);
50 buffer.writeScalar(fSigma.fWidth); 50 buffer.writeScalar(fSigma.fWidth);
51 buffer.writeScalar(fSigma.fHeight); 51 buffer.writeScalar(fSigma.fHeight);
52 } 52 }
53 53
54 enum BlurDirection {
55 kX, kY
56 };
57
58 /**
59 *
60 * In order to make memory accesses cache-friendly, we reorder the passes to
61 * use contiguous memory reads wherever possible.
62 *
63 * For example, the 6 passes of the X-and-Y blur case are rewritten as
64 * follows. Instead of 3 passes in X and 3 passes in Y, we perform
65 * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X,
66 * then 1 pass in X transposed to Y on write.
67 *
68 * +----+ +----+ +----+ +---+ +---+ +---+ +----+
69 * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | -----> | AB |
70 * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blurXY +----+
71 * +---+ +---+ +---+
72 *
73 * In this way, two of the y-blurs become x-blurs applied to transposed
74 * images, and all memory reads are contiguous.
75 */
76
77 template<BlurDirection srcDirection, BlurDirection dstDirection>
78 static void boxBlur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ker nelSize,
79 int leftOffset, int rightOffset, int width, int height)
80 {
81 int rightBorder = SkMin32(rightOffset + 1, width);
82 int srcStrideX = srcDirection == kX ? 1 : srcStride;
83 int dstStrideX = dstDirection == kX ? 1 : height;
84 int srcStrideY = srcDirection == kX ? srcStride : 1;
85 int dstStrideY = dstDirection == kX ? width : 1;
86 uint32_t scale = (1 << 24) / kernelSize;
87 uint32_t half = 1 << 23;
88 for (int y = 0; y < height; ++y) {
89 int sumA = 0, sumR = 0, sumG = 0, sumB = 0;
90 const SkPMColor* p = src;
91 for (int i = 0; i < rightBorder; ++i) {
92 sumA += SkGetPackedA32(*p);
93 sumR += SkGetPackedR32(*p);
94 sumG += SkGetPackedG32(*p);
95 sumB += SkGetPackedB32(*p);
96 p += srcStrideX;
97 }
98
99 const SkPMColor* sptr = src;
100 SkColor* dptr = dst;
101 for (int x = 0; x < width; ++x) {
102 *dptr = SkPackARGB32((sumA * scale + half) >> 24,
103 (sumR * scale + half) >> 24,
104 (sumG * scale + half) >> 24,
105 (sumB * scale + half) >> 24);
106 if (x >= leftOffset) {
107 SkColor l = *(sptr - leftOffset * srcStrideX);
108 sumA -= SkGetPackedA32(l);
109 sumR -= SkGetPackedR32(l);
110 sumG -= SkGetPackedG32(l);
111 sumB -= SkGetPackedB32(l);
112 }
113 if (x + rightOffset + 1 < width) {
114 SkColor r = *(sptr + (rightOffset + 1) * srcStrideX);
115 sumA += SkGetPackedA32(r);
116 sumR += SkGetPackedR32(r);
117 sumG += SkGetPackedG32(r);
118 sumB += SkGetPackedB32(r);
119 }
120 sptr += srcStrideX;
121 if (srcDirection == kY) {
122 SK_PREFETCH(sptr + (rightOffset + 1) * srcStrideX);
123 }
124 dptr += dstStrideX;
125 }
126 src += srcStrideY;
127 dst += dstStrideY;
128 }
129 }
130
131 static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lo wOffset, 54 static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lo wOffset,
132 int *highOffset) 55 int *highOffset)
133 { 56 {
134 float pi = SkScalarToFloat(SK_ScalarPI); 57 float pi = SkScalarToFloat(SK_ScalarPI);
135 int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f)); 58 int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f));
136 *kernelSize = d; 59 *kernelSize = d;
137 if (d % 2 == 1) { 60 if (d % 2 == 1) {
138 *lowOffset = *highOffset = (d - 1) / 2; 61 *lowOffset = *highOffset = (d - 1) / 2;
139 *kernelSize3 = d; 62 *kernelSize3 = d;
140 } else { 63 } else {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 120 }
198 121
199 offset->fX = srcBounds.fLeft; 122 offset->fX = srcBounds.fLeft;
200 offset->fY = srcBounds.fTop; 123 offset->fY = srcBounds.fTop;
201 srcBounds.offset(-srcOffset); 124 srcBounds.offset(-srcOffset);
202 const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top()); 125 const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top());
203 SkPMColor* t = temp.getAddr32(0, 0); 126 SkPMColor* t = temp.getAddr32(0, 0);
204 SkPMColor* d = dst->getAddr32(0, 0); 127 SkPMColor* d = dst->getAddr32(0, 0);
205 int w = dstBounds.width(), h = dstBounds.height(); 128 int w = dstBounds.width(), h = dstBounds.height();
206 int sw = src.rowBytesAsPixels(); 129 int sw = src.rowBytesAsPixels();
207 SkBoxBlurProc boxBlurX, boxBlurXY, boxBlurYX;
208 if (!SkBoxBlurGetPlatformProcs(&boxBlurX, &boxBlurXY, &boxBlurYX)) {
209 boxBlurX = boxBlur<kX, kX>;
210 boxBlurXY = boxBlur<kX, kY>;
211 boxBlurYX = boxBlur<kY, kX>;
212 }
213 130
131 /**
132 *
133 * In order to make memory accesses cache-friendly, we reorder the passes to
134 * use contiguous memory reads wherever possible.
135 *
136 * For example, the 6 passes of the X-and-Y blur case are rewritten as
137 * follows. Instead of 3 passes in X and 3 passes in Y, we perform
138 * 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X,
139 * then 1 pass in X transposed to Y on write.
140 *
141 * +----+ +----+ +----+ +---+ +---+ +---+ +----+
142 * + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | --- --> | AB |
143 * +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blu rXY +----+
144 * +---+ +---+ +---+
145 *
146 * In this way, two of the y-blurs become x-blurs applied to transposed
147 * images, and all memory reads are contiguous.
148 */
214 if (kernelSizeX > 0 && kernelSizeY > 0) { 149 if (kernelSizeX > 0 && kernelSizeY > 0) {
215 boxBlurX(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w, h); 150 SkOpts::box_blur_xx(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w , h);
216 boxBlurX(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w, h); 151 SkOpts::box_blur_xx(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w , h);
217 boxBlurXY(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w, h); 152 SkOpts::box_blur_xy(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w , h);
218 boxBlurX(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); 153 SkOpts::box_blur_xx(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h , w);
219 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); 154 SkOpts::box_blur_xx(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h , w);
220 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); 155 SkOpts::box_blur_xy(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h , w);
221 } else if (kernelSizeX > 0) { 156 } else if (kernelSizeX > 0) {
222 boxBlurX(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w, h); 157 SkOpts::box_blur_xx(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w , h);
223 boxBlurX(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w, h); 158 SkOpts::box_blur_xx(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w , h);
224 boxBlurX(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w, h); 159 SkOpts::box_blur_xx(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w , h);
225 } else if (kernelSizeY > 0) { 160 } else if (kernelSizeY > 0) {
226 boxBlurYX(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); 161 SkOpts::box_blur_yx(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h , w);
227 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); 162 SkOpts::box_blur_xx(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h , w);
228 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); 163 SkOpts::box_blur_xy(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h , w);
229 } 164 }
230 return true; 165 return true;
231 } 166 }
232 167
233 168
234 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 169 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
235 if (this->getInput(0)) { 170 if (this->getInput(0)) {
236 this->getInput(0)->computeFastBounds(src, dst); 171 this->getInput(0)->computeFastBounds(src, dst);
237 } else { 172 } else {
238 *dst = src; 173 *dst = src;
(...skipping 14 matching lines...) Expand all
253 } 188 }
254 *dst = bounds; 189 *dst = bounds;
255 return true; 190 return true;
256 } 191 }
257 192
258 bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, 193 bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
259 SkBitmap* result, SkIPoint* offset) const { 194 SkBitmap* result, SkIPoint* offset) const {
260 #if SK_SUPPORT_GPU 195 #if SK_SUPPORT_GPU
261 SkBitmap input = src; 196 SkBitmap input = src;
262 SkIPoint srcOffset = SkIPoint::Make(0, 0); 197 SkIPoint srcOffset = SkIPoint::Make(0, 0);
263 if (this->getInput(0) && 198 if (this->getInput(0) &&
264 !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffse t)) { 199 !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffse t)) {
265 return false; 200 return false;
266 } 201 }
267 SkIRect rect; 202 SkIRect rect;
268 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) { 203 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) {
269 return false; 204 return false;
270 } 205 }
271 GrTexture* source = input.getTexture(); 206 GrTexture* source = input.getTexture();
272 SkVector sigma = mapSigma(fSigma, ctx.ctm()); 207 SkVector sigma = mapSigma(fSigma, ctx.ctm());
273 offset->fX = rect.fLeft; 208 offset->fX = rect.fLeft;
(...skipping 22 matching lines...) Expand all
296 str->appendf("SkBlurImageFilter: ("); 231 str->appendf("SkBlurImageFilter: (");
297 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight); 232 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight);
298 233
299 if (this->getInput(0)) { 234 if (this->getInput(0)) {
300 this->getInput(0)->toString(str); 235 this->getInput(0)->toString(str);
301 } 236 }
302 237
303 str->append("))"); 238 str->append("))");
304 } 239 }
305 #endif 240 #endif
OLDNEW
« no previous file with comments | « src/core/SkOpts.cpp ('k') | src/opts/SkBlurImageFilter_opts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698