|
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2013 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkBlurUtils.h" | |
9 #include "SkRect.h" | |
tfarina
2013/07/13 22:19:30
can we have a blank line separating these?
robertphillips
2013/07/15 12:05:04
Done.
| |
10 | |
11 #if SK_SUPPORT_GPU | |
12 #include "effects\GrConvolutionEffect.h" | |
tfarina
2013/07/13 22:19:30
is effects necessary here? I think we don't use fu
robertphillips
2013/07/15 12:05:04
GrConvolutionEffect.h lives in src\gpu\effects. sr
| |
13 #include "GrContext.h" | |
14 #endif | |
15 | |
16 namespace SkBlurUtils { | |
17 | |
18 #if SK_SUPPORT_GPU | |
19 | |
20 #define MAX_BLUR_SIGMA 4.0f | |
21 | |
22 static void scale_rect(SkRect* rect, float xScale, float yScale) { | |
23 rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale)); | |
24 rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale)); | |
25 rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale)); | |
26 rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale)); | |
27 } | |
28 | |
29 static float adjust_sigma(float sigma, int *scaleFactor, int *radius) { | |
30 *scaleFactor = 1; | |
31 while (sigma > MAX_BLUR_SIGMA) { | |
32 *scaleFactor *= 2; | |
33 sigma *= 0.5f; | |
34 } | |
35 *radius = static_cast<int>(ceilf(sigma * 3.0f)); | |
36 GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius); | |
37 return sigma; | |
38 } | |
39 | |
40 static void convolve_gaussian(GrContext* context, | |
41 GrTexture* texture, | |
42 const SkRect& rect, | |
43 float sigma, | |
44 int radius, | |
45 Gr1DKernelEffect::Direction direction) { | |
46 GrPaint paint; | |
47 | |
48 SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture, | |
49 direction , | |
50 radius, | |
51 sigma)); | |
52 paint.addColorEffect(conv); | |
53 context->drawRect(paint, rect); | |
54 } | |
55 | |
56 GrTexture* GaussianBlur(GrContext* context, | |
57 GrTexture* srcTexture, | |
58 bool canClobberSrc, | |
59 const SkRect& rect, | |
60 float sigmaX, | |
61 float sigmaY) { | |
62 GrAssert(NULL != context); | |
63 | |
64 GrContext::AutoRenderTarget art(context); | |
65 | |
66 GrContext::AutoMatrix am; | |
67 am.setIdentity(context); | |
68 | |
69 SkIRect clearRect; | |
70 int scaleFactorX, radiusX; | |
71 int scaleFactorY, radiusY; | |
72 sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX); | |
73 sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY); | |
74 | |
75 SkRect srcRect(rect); | |
76 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | |
77 srcRect.roundOut(); | |
78 scale_rect(&srcRect, static_cast<float>(scaleFactorX), | |
79 static_cast<float>(scaleFactorY)); | |
80 | |
81 GrContext::AutoClip acs(context, srcRect); | |
82 | |
83 GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() || | |
84 kRGBA_8888_GrPixelConfig == srcTexture->config() || | |
85 kAlpha_8_GrPixelConfig == srcTexture->config()); | |
86 | |
87 GrTextureDesc desc; | |
88 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; | |
89 desc.fWidth = SkScalarFloorToInt(srcRect.width()); | |
90 desc.fHeight = SkScalarFloorToInt(srcRect.height()); | |
91 desc.fConfig = srcTexture->config(); | |
92 | |
93 GrAutoScratchTexture temp1, temp2; | |
94 GrTexture* dstTexture = temp1.set(context, desc); | |
95 GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, des c); | |
96 if (NULL == dstTexture || NULL == tempTexture) { | |
97 return NULL; | |
98 } | |
99 | |
100 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { | |
101 GrPaint paint; | |
102 SkMatrix matrix; | |
103 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | |
104 context->setRenderTarget(dstTexture->asRenderTarget()); | |
105 SkRect dstRect(srcRect); | |
106 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, | |
107 i < scaleFactorY ? 0.5f : 1.0f); | |
108 GrTextureParams params(SkShader::kClamp_TileMode, true); | |
109 paint.addColorTextureEffect(srcTexture, matrix, params); | |
110 context->drawRectToRect(paint, dstRect, srcRect); | |
111 srcRect = dstRect; | |
112 srcTexture = dstTexture; | |
113 SkTSwap(dstTexture, tempTexture); | |
114 } | |
115 | |
116 SkIRect srcIRect; | |
117 srcRect.roundOut(&srcIRect); | |
118 | |
119 if (sigmaX > 0.0f) { | |
120 if (scaleFactorX > 1) { | |
121 // Clear out a radius to the right of the srcRect to prevent the | |
122 // X convolution from reading garbage. | |
123 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | |
124 radiusX, srcIRect.height()); | |
125 context->clear(&clearRect, 0x0); | |
126 } | |
127 context->setRenderTarget(dstTexture->asRenderTarget()); | |
128 convolve_gaussian(context, srcTexture, srcRect, sigmaX, radiusX, | |
129 Gr1DKernelEffect::kX_Direction); | |
130 srcTexture = dstTexture; | |
131 SkTSwap(dstTexture, tempTexture); | |
132 } | |
133 | |
134 if (sigmaY > 0.0f) { | |
135 if (scaleFactorY > 1 || sigmaX > 0.0f) { | |
136 // Clear out a radius below the srcRect to prevent the Y | |
137 // convolution from reading garbage. | |
138 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | |
139 srcIRect.width(), radiusY); | |
140 context->clear(&clearRect, 0x0); | |
141 } | |
142 | |
143 context->setRenderTarget(dstTexture->asRenderTarget()); | |
144 convolve_gaussian(context, srcTexture, srcRect, sigmaY, radiusY, | |
145 Gr1DKernelEffect::kY_Direction); | |
146 srcTexture = dstTexture; | |
147 SkTSwap(dstTexture, tempTexture); | |
148 } | |
149 | |
150 if (scaleFactorX > 1 || scaleFactorY > 1) { | |
151 // Clear one pixel to the right and below, to accommodate bilinear | |
152 // upsampling. | |
153 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | |
154 srcIRect.width() + 1, 1); | |
155 context->clear(&clearRect, 0x0); | |
156 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | |
157 1, srcIRect.height()); | |
158 context->clear(&clearRect, 0x0); | |
159 SkMatrix matrix; | |
160 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | |
161 context->setRenderTarget(dstTexture->asRenderTarget()); | |
162 | |
163 GrPaint paint; | |
164 // FIXME: this should be mitchell, not bilinear. | |
165 GrTextureParams params(SkShader::kClamp_TileMode, true); | |
166 paint.addColorTextureEffect(srcTexture, matrix, params); | |
167 | |
168 SkRect dstRect(srcRect); | |
169 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); | |
170 context->drawRectToRect(paint, dstRect, srcRect); | |
171 srcRect = dstRect; | |
172 srcTexture = dstTexture; | |
173 SkTSwap(dstTexture, tempTexture); | |
174 } | |
175 if (srcTexture == temp1.texture()) { | |
176 return temp1.detach(); | |
177 } else if (srcTexture == temp2.texture()) { | |
178 return temp2.detach(); | |
179 } else { | |
180 srcTexture->ref(); | |
181 return srcTexture; | |
182 } | |
183 } | |
184 #endif | |
185 | |
186 }; | |
tfarina
2013/07/13 22:19:30
no need of ; here.
I'd just write:
} // namespa
robertphillips
2013/07/15 12:05:04
Done.
| |
OLD | NEW |