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

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

Issue 418223009: 2D kernel initial wiring for Guassian (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 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 | « gyp/gmslides.gypi ('k') | src/gpu/effects/GrMatrixConvolutionEffect.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 2013 Google Inc. 2 * Copyright 2013 Google Inc.
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 "SkGpuBlurUtils.h" 8 #include "SkGpuBlurUtils.h"
9 9
10 #include "SkRect.h" 10 #include "SkRect.h"
11 11
12 #if SK_SUPPORT_GPU 12 #if SK_SUPPORT_GPU
13 #include "effects/GrConvolutionEffect.h" 13 #include "effects/GrConvolutionEffect.h"
14 #include "effects/GrTextureDomain.h" 14 #include "effects/GrMatrixConvolutionEffect.h"
15 #include "GrContext.h" 15 #include "GrContext.h"
16 #endif 16 #endif
17 17
18 namespace SkGpuBlurUtils { 18 namespace SkGpuBlurUtils {
19 19
20 #if SK_SUPPORT_GPU 20 #if SK_SUPPORT_GPU
21 21
22 #define MAX_BLUR_SIGMA 4.0f 22 #define MAX_BLUR_SIGMA 4.0f
23 23
24 static void scale_rect(SkRect* rect, float xScale, float yScale) { 24 static void scale_rect(SkRect* rect, float xScale, float yScale) {
(...skipping 11 matching lines...) Expand all
36 if (*scaleFactor > maxTextureSize) { 36 if (*scaleFactor > maxTextureSize) {
37 *scaleFactor = maxTextureSize; 37 *scaleFactor = maxTextureSize;
38 sigma = MAX_BLUR_SIGMA; 38 sigma = MAX_BLUR_SIGMA;
39 } 39 }
40 } 40 }
41 *radius = static_cast<int>(ceilf(sigma * 3.0f)); 41 *radius = static_cast<int>(ceilf(sigma * 3.0f));
42 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius); 42 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
43 return sigma; 43 return sigma;
44 } 44 }
45 45
46 static void convolve_gaussian_pass(GrContext* context, 46 static void convolve_gaussian_1d(GrContext* context,
47 const SkRect& srcRect, 47 const SkRect& srcRect,
48 const SkRect& dstRect, 48 const SkRect& dstRect,
49 GrTexture* texture, 49 GrTexture* texture,
50 Gr1DKernelEffect::Direction direction, 50 Gr1DKernelEffect::Direction direction,
51 int radius, 51 int radius,
52 float sigma, 52 float sigma,
53 bool useBounds, 53 bool useBounds,
54 float bounds[2]) { 54 float bounds[2]) {
55 GrPaint paint; 55 GrPaint paint;
56 paint.reset(); 56 paint.reset();
57 SkAutoTUnref<GrEffect> conv(GrConvolutionEffect::CreateGaussian( 57 SkAutoTUnref<GrEffect> conv(GrConvolutionEffect::CreateGaussian(
58 texture, direction, radius, sigma, useBounds, bounds)); 58 texture, direction, radius, sigma, useBounds, bounds));
59 paint.reset(); 59 paint.reset();
60 paint.addColorEffect(conv); 60 paint.addColorEffect(conv);
61 context->drawRectToRect(paint, dstRect, srcRect); 61 context->drawRectToRect(paint, dstRect, srcRect);
62 } 62 }
63 63
64 static void convolve_gaussian_2d(GrContext* context,
65 const SkRect& srcRect,
66 const SkRect& dstRect,
67 GrTexture* texture,
68 int radiusX,
69 int radiusY,
70 SkScalar sigmaX,
71 SkScalar sigmaY,
72 bool useBounds,
73 SkIRect bounds) {
74 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
75 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
76 GrPaint paint;
77 paint.reset();
78 SkAutoTUnref<GrEffect> conv(GrMatrixConvolutionEffect::CreateGaussian(
79 texture, bounds, size, 1.0, 0.0, kernelOffset,
80 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_ Mode,
81 true, sigmaX, sigmaY));
82 paint.reset();
83 paint.addColorEffect(conv);
84 context->drawRectToRect(paint, dstRect, srcRect);
85 }
86
64 static void convolve_gaussian(GrContext* context, 87 static void convolve_gaussian(GrContext* context,
65 const SkRect& srcRect, 88 const SkRect& srcRect,
66 const SkRect& dstRect, 89 const SkRect& dstRect,
67 GrTexture* texture, 90 GrTexture* texture,
68 Gr1DKernelEffect::Direction direction, 91 Gr1DKernelEffect::Direction direction,
69 int radius, 92 int radius,
70 float sigma, 93 float sigma,
71 bool cropToSrcRect) { 94 bool cropToSrcRect) {
72 float bounds[2] = { 0.0f, 1.0f }; 95 float bounds[2] = { 0.0f, 1.0f };
73 if (!cropToSrcRect) { 96 if (!cropToSrcRect) {
74 convolve_gaussian_pass(context, srcRect, dstRect, texture, 97 convolve_gaussian_1d(context, srcRect, dstRect, texture,
75 direction, radius, sigma, false, bounds); 98 direction, radius, sigma, false, bounds);
76 return; 99 return;
77 } 100 }
78 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect; 101 SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
79 SkRect middleSrcRect = srcRect, middleDstRect = dstRect; 102 SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
80 SkRect upperSrcRect = srcRect, upperDstRect = dstRect; 103 SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
81 SkScalar size; 104 SkScalar size;
82 SkScalar rad = SkIntToScalar(radius); 105 SkScalar rad = SkIntToScalar(radius);
83 if (direction == Gr1DKernelEffect::kX_Direction) { 106 if (direction == Gr1DKernelEffect::kX_Direction) {
84 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width(); 107 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
85 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width(); 108 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
(...skipping 10 matching lines...) Expand all
96 size = srcRect.height(); 119 size = srcRect.height();
97 lowerSrcRect.fBottom = srcRect.top() + rad; 120 lowerSrcRect.fBottom = srcRect.top() + rad;
98 lowerDstRect.fBottom = dstRect.top() + rad; 121 lowerDstRect.fBottom = dstRect.top() + rad;
99 upperSrcRect.fTop = srcRect.bottom() - rad; 122 upperSrcRect.fTop = srcRect.bottom() - rad;
100 upperDstRect.fTop = dstRect.bottom() - rad; 123 upperDstRect.fTop = dstRect.bottom() - rad;
101 middleSrcRect.inset(0, rad); 124 middleSrcRect.inset(0, rad);
102 middleDstRect.inset(0, rad); 125 middleDstRect.inset(0, rad);
103 } 126 }
104 if (radius >= size * SK_ScalarHalf) { 127 if (radius >= size * SK_ScalarHalf) {
105 // Blur radius covers srcRect; use bounds over entire draw 128 // Blur radius covers srcRect; use bounds over entire draw
106 convolve_gaussian_pass(context, srcRect, dstRect, texture, 129 convolve_gaussian_1d(context, srcRect, dstRect, texture,
107 direction, radius, sigma, true, bounds); 130 direction, radius, sigma, true, bounds);
108 } else { 131 } else {
109 // Draw upper and lower margins with bounds; middle without. 132 // Draw upper and lower margins with bounds; middle without.
110 convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture, 133 convolve_gaussian_1d(context, lowerSrcRect, lowerDstRect, texture,
111 direction, radius, sigma, true, bounds); 134 direction, radius, sigma, true, bounds);
112 convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture, 135 convolve_gaussian_1d(context, upperSrcRect, upperDstRect, texture,
113 direction, radius, sigma, true, bounds); 136 direction, radius, sigma, true, bounds);
114 convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture, 137 convolve_gaussian_1d(context, middleSrcRect, middleDstRect, texture,
115 direction, radius, sigma, false, bounds); 138 direction, radius, sigma, false, bounds);
116 } 139 }
117 } 140 }
118 141
119 GrTexture* GaussianBlur(GrContext* context, 142 GrTexture* GaussianBlur(GrContext* context,
120 GrTexture* srcTexture, 143 GrTexture* srcTexture,
121 bool canClobberSrc, 144 bool canClobberSrc,
122 const SkRect& rect, 145 const SkRect& rect,
123 bool cropToRect, 146 bool cropToRect,
124 float sigmaX, 147 float sigmaX,
125 float sigmaY) { 148 float sigmaY) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 i < scaleFactorY ? 0.5f : 1.0f); 212 i < scaleFactorY ? 0.5f : 1.0f);
190 context->drawRectToRect(paint, dstRect, srcRect); 213 context->drawRectToRect(paint, dstRect, srcRect);
191 srcRect = dstRect; 214 srcRect = dstRect;
192 srcTexture = dstTexture; 215 srcTexture = dstTexture;
193 SkTSwap(dstTexture, tempTexture); 216 SkTSwap(dstTexture, tempTexture);
194 } 217 }
195 218
196 SkIRect srcIRect; 219 SkIRect srcIRect;
197 srcRect.roundOut(&srcIRect); 220 srcRect.roundOut(&srcIRect);
198 221
199 if (sigmaX > 0.0f) { 222 // For really small blurs(Certainly no wider than 5x5 on desktop gpus) it is faster to just
200 if (scaleFactorX > 1) { 223 // launch a single non separable kernel vs two launches
201 // Clear out a radius to the right of the srcRect to prevent the 224 if (sigmaX > 0.0f && sigmaY > 0 &&
202 // X convolution from reading garbage. 225 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
203 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 226 // We shouldn't be scaling because this is a small size blur
204 radiusX, srcIRect.height()); 227 SkASSERT((scaleFactorX == scaleFactorY) == 1);
205 context->clear(&clearRect, 0x0, false);
206 }
207 context->setRenderTarget(dstTexture->asRenderTarget()); 228 context->setRenderTarget(dstTexture->asRenderTarget());
208 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 229 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
209 convolve_gaussian(context, srcRect, dstRect, srcTexture, 230 convolve_gaussian_2d(context, srcRect, dstRect, srcTexture,
210 Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropT oRect); 231 radiusX, radiusY, sigmaX, sigmaY, cropToRect, srcIRect);
211 srcTexture = dstTexture; 232 srcTexture = dstTexture;
212 srcRect = dstRect; 233 srcRect = dstRect;
213 SkTSwap(dstTexture, tempTexture); 234 SkTSwap(dstTexture, tempTexture);
214 }
215 235
216 if (sigmaY > 0.0f) { 236 } else {
217 if (scaleFactorY > 1 || sigmaX > 0.0f) { 237 if (sigmaX > 0.0f) {
218 // Clear out a radius below the srcRect to prevent the Y 238 if (scaleFactorX > 1) {
219 // convolution from reading garbage. 239 // Clear out a radius to the right of the srcRect to prevent the
220 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 240 // X convolution from reading garbage.
221 srcIRect.width(), radiusY); 241 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
222 context->clear(&clearRect, 0x0, false); 242 radiusX, srcIRect.height());
243 context->clear(&clearRect, 0x0, false);
244 }
245 context->setRenderTarget(dstTexture->asRenderTarget());
246 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
247 convolve_gaussian(context, srcRect, dstRect, srcTexture,
248 Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, c ropToRect);
249 srcTexture = dstTexture;
250 srcRect = dstRect;
251 SkTSwap(dstTexture, tempTexture);
223 } 252 }
224 253
225 context->setRenderTarget(dstTexture->asRenderTarget()); 254 if (sigmaY > 0.0f) {
226 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 255 if (scaleFactorY > 1 || sigmaX > 0.0f) {
227 convolve_gaussian(context, srcRect, dstRect, srcTexture, 256 // Clear out a radius below the srcRect to prevent the Y
228 Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropT oRect); 257 // convolution from reading garbage.
229 srcTexture = dstTexture; 258 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
230 srcRect = dstRect; 259 srcIRect.width(), radiusY);
231 SkTSwap(dstTexture, tempTexture); 260 context->clear(&clearRect, 0x0, false);
261 }
262
263 context->setRenderTarget(dstTexture->asRenderTarget());
264 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
265 convolve_gaussian(context, srcRect, dstRect, srcTexture,
266 Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, c ropToRect);
267 srcTexture = dstTexture;
268 srcRect = dstRect;
269 SkTSwap(dstTexture, tempTexture);
270 }
232 } 271 }
233 272
234 if (scaleFactorX > 1 || scaleFactorY > 1) { 273 if (scaleFactorX > 1 || scaleFactorY > 1) {
235 // Clear one pixel to the right and below, to accommodate bilinear 274 // Clear one pixel to the right and below, to accommodate bilinear
236 // upsampling. 275 // upsampling.
237 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 276 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
238 srcIRect.width() + 1, 1); 277 srcIRect.width() + 1, 1);
239 context->clear(&clearRect, 0x0, false); 278 context->clear(&clearRect, 0x0, false);
240 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 279 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
241 1, srcIRect.height()); 280 1, srcIRect.height());
(...skipping 19 matching lines...) Expand all
261 } else if (srcTexture == temp2.texture()) { 300 } else if (srcTexture == temp2.texture()) {
262 return temp2.detach(); 301 return temp2.detach();
263 } else { 302 } else {
264 srcTexture->ref(); 303 srcTexture->ref();
265 return srcTexture; 304 return srcTexture;
266 } 305 }
267 } 306 }
268 #endif 307 #endif
269 308
270 } 309 }
OLDNEW
« no previous file with comments | « gyp/gmslides.gypi ('k') | src/gpu/effects/GrMatrixConvolutionEffect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698