OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 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 "SkMatrixConvolutionImageFilter.h" | 8 #include "SkMatrixConvolutionImageFilter.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 #include "SkFlattenableBuffers.h" | 11 #include "SkFlattenableBuffers.h" |
12 #include "SkRect.h" | 12 #include "SkRect.h" |
13 #include "SkUnPreMultiply.h" | 13 #include "SkUnPreMultiply.h" |
14 | 14 |
15 #if SK_SUPPORT_GPU | 15 #if SK_SUPPORT_GPU |
16 #include "gl/GrGLEffect.h" | 16 #include "gl/GrGLEffect.h" |
17 #include "effects/GrSingleTextureEffect.h" | 17 #include "effects/GrSingleTextureEffect.h" |
18 #include "GrTBackendEffectFactory.h" | 18 #include "GrTBackendEffectFactory.h" |
19 #include "GrTexture.h" | 19 #include "GrTexture.h" |
20 #include "SkMatrix.h" | 20 #include "SkMatrix.h" |
21 | |
22 #endif | 21 #endif |
23 | 22 |
24 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(const SkISize& ke
rnelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint&
target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input) | 23 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter( |
25 : INHERITED(input), | 24 const SkISize& kernelSize, |
| 25 const SkScalar* kernel, |
| 26 SkScalar gain, |
| 27 SkScalar bias, |
| 28 const SkIPoint& target, |
| 29 TileMode tileMode, |
| 30 bool convolveAlpha, |
| 31 SkImageFilter* input, |
| 32 const CropRect* cropRect) |
| 33 : INHERITED(input, cropRect), |
26 fKernelSize(kernelSize), | 34 fKernelSize(kernelSize), |
27 fGain(gain), | 35 fGain(gain), |
28 fBias(bias), | 36 fBias(bias), |
29 fTarget(target), | 37 fTarget(target), |
30 fTileMode(tileMode), | 38 fTileMode(tileMode), |
31 fConvolveAlpha(convolveAlpha) { | 39 fConvolveAlpha(convolveAlpha) { |
32 uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight; | 40 uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight; |
33 fKernel = SkNEW_ARRAY(SkScalar, size); | 41 fKernel = SkNEW_ARRAY(SkScalar, size); |
34 memcpy(fKernel, kernel, size * sizeof(SkScalar)); | 42 memcpy(fKernel, kernel, size * sizeof(SkScalar)); |
35 SkASSERT(kernelSize.fWidth >= 1 && kernelSize.fHeight >= 1); | 43 SkASSERT(kernelSize.fWidth >= 1 && kernelSize.fHeight >= 1); |
36 SkASSERT(target.fX >= 0 && target.fX < kernelSize.fWidth); | 44 SkASSERT(target.fX >= 0 && target.fX < kernelSize.fWidth); |
37 SkASSERT(target.fY >= 0 && target.fY < kernelSize.fHeight); | 45 SkASSERT(target.fY >= 0 && target.fY < kernelSize.fHeight); |
38 } | 46 } |
39 | 47 |
40 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableRead
Buffer& buffer) : INHERITED(buffer) { | 48 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableRead
Buffer& buffer) |
| 49 : INHERITED(buffer) { |
41 fKernelSize.fWidth = buffer.readInt(); | 50 fKernelSize.fWidth = buffer.readInt(); |
42 fKernelSize.fHeight = buffer.readInt(); | 51 fKernelSize.fHeight = buffer.readInt(); |
43 uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight; | 52 uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight; |
44 fKernel = SkNEW_ARRAY(SkScalar, size); | 53 fKernel = SkNEW_ARRAY(SkScalar, size); |
45 SkDEBUGCODE(uint32_t readSize = )buffer.readScalarArray(fKernel); | 54 SkDEBUGCODE(uint32_t readSize = )buffer.readScalarArray(fKernel); |
46 SkASSERT(readSize == size); | 55 SkASSERT(readSize == size); |
47 fGain = buffer.readScalar(); | 56 fGain = buffer.readScalar(); |
48 fBias = buffer.readScalar(); | 57 fBias = buffer.readScalar(); |
49 fTarget.fX = buffer.readInt(); | 58 fTarget.fX = buffer.readInt(); |
50 fTarget.fY = buffer.readInt(); | 59 fTarget.fY = buffer.readInt(); |
(...skipping 13 matching lines...) Expand all Loading... |
64 buffer.writeInt((int) fTileMode); | 73 buffer.writeInt((int) fTileMode); |
65 buffer.writeBool(fConvolveAlpha); | 74 buffer.writeBool(fConvolveAlpha); |
66 } | 75 } |
67 | 76 |
68 SkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() { | 77 SkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() { |
69 delete[] fKernel; | 78 delete[] fKernel; |
70 } | 79 } |
71 | 80 |
72 class UncheckedPixelFetcher { | 81 class UncheckedPixelFetcher { |
73 public: | 82 public: |
74 static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { | 83 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe
ct& bounds) { |
75 return *src.getAddr32(x, y); | 84 return *src.getAddr32(x, y); |
76 } | 85 } |
77 }; | 86 }; |
78 | 87 |
79 class ClampPixelFetcher { | 88 class ClampPixelFetcher { |
80 public: | 89 public: |
81 static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { | 90 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe
ct& bounds) { |
82 x = SkClampMax(x, src.width() - 1); | 91 x = SkPin32(x, bounds.fLeft, bounds.fRight - 1); |
83 y = SkClampMax(y, src.height() - 1); | 92 y = SkPin32(y, bounds.fTop, bounds.fBottom - 1); |
84 return *src.getAddr32(x, y); | 93 return *src.getAddr32(x, y); |
85 } | 94 } |
86 }; | 95 }; |
87 | 96 |
88 class RepeatPixelFetcher { | 97 class RepeatPixelFetcher { |
89 public: | 98 public: |
90 static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { | 99 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe
ct& bounds) { |
91 x %= src.width(); | 100 x = (x - bounds.left()) % bounds.width() + bounds.left(); |
92 y %= src.height(); | 101 y = (y - bounds.top()) % bounds.height() + bounds.top(); |
93 if (x < 0) { | 102 if (x < bounds.left()) { |
94 x += src.width(); | 103 x += bounds.width(); |
95 } | 104 } |
96 if (y < 0) { | 105 if (y < bounds.top()) { |
97 y += src.height(); | 106 y += bounds.height(); |
98 } | 107 } |
99 return *src.getAddr32(x, y); | 108 return *src.getAddr32(x, y); |
100 } | 109 } |
101 }; | 110 }; |
102 | 111 |
103 class ClampToBlackPixelFetcher { | 112 class ClampToBlackPixelFetcher { |
104 public: | 113 public: |
105 static inline SkPMColor fetch(const SkBitmap& src, int x, int y) { | 114 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe
ct& bounds) { |
106 if (x < 0 || x >= src.width() || y < 0 || y >= src.height()) { | 115 if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bo
unds.fBottom) { |
107 return 0; | 116 return 0; |
108 } else { | 117 } else { |
109 return *src.getAddr32(x, y); | 118 return *src.getAddr32(x, y); |
110 } | 119 } |
111 } | 120 } |
112 }; | 121 }; |
113 | 122 |
114 template<class PixelFetcher, bool convolveAlpha> | 123 template<class PixelFetcher, bool convolveAlpha> |
115 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap*
result, const SkIRect& rect) { | 124 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, |
| 125 SkBitmap* result, |
| 126 const SkIRect& rect, |
| 127 const SkIRect& bounds) { |
116 for (int y = rect.fTop; y < rect.fBottom; ++y) { | 128 for (int y = rect.fTop; y < rect.fBottom; ++y) { |
117 SkPMColor* dptr = result->getAddr32(rect.fLeft, y); | 129 SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bound
s.fTop); |
118 for (int x = rect.fLeft; x < rect.fRight; ++x) { | 130 for (int x = rect.fLeft; x < rect.fRight; ++x) { |
119 SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0; | 131 SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0; |
120 for (int cy = 0; cy < fKernelSize.fHeight; cy++) { | 132 for (int cy = 0; cy < fKernelSize.fHeight; cy++) { |
121 for (int cx = 0; cx < fKernelSize.fWidth; cx++) { | 133 for (int cx = 0; cx < fKernelSize.fWidth; cx++) { |
122 SkPMColor s = PixelFetcher::fetch(src, x + cx - fTarget.fX,
y + cy - fTarget.fY); | 134 SkPMColor s = PixelFetcher::fetch(src, |
| 135 x + cx - fTarget.fX, |
| 136 y + cy - fTarget.fY, |
| 137 bounds); |
123 SkScalar k = fKernel[cy * fKernelSize.fWidth + cx]; | 138 SkScalar k = fKernel[cy * fKernelSize.fWidth + cx]; |
124 if (convolveAlpha) { | 139 if (convolveAlpha) { |
125 sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k)
; | 140 sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k)
; |
126 } | 141 } |
127 sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k); | 142 sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k); |
128 sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k); | 143 sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k); |
129 sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k); | 144 sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k); |
130 } | 145 } |
131 } | 146 } |
132 int a = convolveAlpha | 147 int a = convolveAlpha |
133 ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBi
as), 255) | 148 ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBi
as), 255) |
134 : 255; | 149 : 255; |
135 int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBi
as), a); | 150 int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBi
as), a); |
136 int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBi
as), a); | 151 int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBi
as), a); |
137 int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBi
as), a); | 152 int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBi
as), a); |
138 if (!convolveAlpha) { | 153 if (!convolveAlpha) { |
139 a = SkGetPackedA32(PixelFetcher::fetch(src, x, y)); | 154 a = SkGetPackedA32(PixelFetcher::fetch(src, x, y, bounds)); |
140 *dptr++ = SkPreMultiplyARGB(a, r, g, b); | 155 *dptr++ = SkPreMultiplyARGB(a, r, g, b); |
141 } else { | 156 } else { |
142 *dptr++ = SkPackARGB32(a, r, g, b); | 157 *dptr++ = SkPackARGB32(a, r, g, b); |
143 } | 158 } |
144 } | 159 } |
145 } | 160 } |
146 } | 161 } |
147 | 162 |
148 template<class PixelFetcher> | 163 template<class PixelFetcher> |
149 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap*
result, const SkIRect& rect) { | 164 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, |
| 165 SkBitmap* result, |
| 166 const SkIRect& rect, |
| 167 const SkIRect& bounds) { |
150 if (fConvolveAlpha) { | 168 if (fConvolveAlpha) { |
151 filterPixels<PixelFetcher, true>(src, result, rect); | 169 filterPixels<PixelFetcher, true>(src, result, rect, bounds); |
152 } else { | 170 } else { |
153 filterPixels<PixelFetcher, false>(src, result, rect); | 171 filterPixels<PixelFetcher, false>(src, result, rect, bounds); |
154 } | 172 } |
155 } | 173 } |
156 | 174 |
157 void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, S
kBitmap* result, const SkIRect& rect) { | 175 void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, |
158 filterPixels<UncheckedPixelFetcher>(src, result, rect); | 176 SkBitmap* result, |
| 177 const SkIRect& rect, |
| 178 const SkIRect& bounds)
{ |
| 179 filterPixels<UncheckedPixelFetcher>(src, result, rect, bounds); |
159 } | 180 } |
160 | 181 |
161 void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, SkB
itmap* result, const SkIRect& rect) { | 182 void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, |
| 183 SkBitmap* result, |
| 184 const SkIRect& rect, |
| 185 const SkIRect& bounds) { |
162 switch (fTileMode) { | 186 switch (fTileMode) { |
163 case kClamp_TileMode: | 187 case kClamp_TileMode: |
164 filterPixels<ClampPixelFetcher>(src, result, rect); | 188 filterPixels<ClampPixelFetcher>(src, result, rect, bounds); |
165 break; | 189 break; |
166 case kRepeat_TileMode: | 190 case kRepeat_TileMode: |
167 filterPixels<RepeatPixelFetcher>(src, result, rect); | 191 filterPixels<RepeatPixelFetcher>(src, result, rect, bounds); |
168 break; | 192 break; |
169 case kClampToBlack_TileMode: | 193 case kClampToBlack_TileMode: |
170 filterPixels<ClampToBlackPixelFetcher>(src, result, rect); | 194 filterPixels<ClampToBlackPixelFetcher>(src, result, rect, bounds); |
171 break; | 195 break; |
172 } | 196 } |
173 } | 197 } |
174 | 198 |
175 // FIXME: This should be refactored to SkImageFilterUtils for | 199 // FIXME: This should be refactored to SkImageFilterUtils for |
176 // use by other filters. For now, we assume the input is always | 200 // use by other filters. For now, we assume the input is always |
177 // premultiplied and unpremultiply it | 201 // premultiplied and unpremultiply it |
178 static SkBitmap unpremultiplyBitmap(const SkBitmap& src) | 202 static SkBitmap unpremultiplyBitmap(const SkBitmap& src) |
179 { | 203 { |
180 SkAutoLockPixels alp(src); | 204 SkAutoLockPixels alp(src); |
(...skipping 23 matching lines...) Expand all Loading... |
204 SkIPoint* loc) { | 228 SkIPoint* loc) { |
205 SkBitmap src = source; | 229 SkBitmap src = source; |
206 if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, lo
c)) { | 230 if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, lo
c)) { |
207 return false; | 231 return false; |
208 } | 232 } |
209 | 233 |
210 if (src.config() != SkBitmap::kARGB_8888_Config) { | 234 if (src.config() != SkBitmap::kARGB_8888_Config) { |
211 return false; | 235 return false; |
212 } | 236 } |
213 | 237 |
| 238 SkIRect bounds; |
| 239 src.getBounds(&bounds); |
| 240 if (!this->applyCropRect(&bounds, matrix)) { |
| 241 return false; |
| 242 } |
| 243 |
214 if (!fConvolveAlpha && !src.isOpaque()) { | 244 if (!fConvolveAlpha && !src.isOpaque()) { |
215 src = unpremultiplyBitmap(src); | 245 src = unpremultiplyBitmap(src); |
216 } | 246 } |
217 | 247 |
218 SkAutoLockPixels alp(src); | 248 SkAutoLockPixels alp(src); |
219 if (!src.getPixels()) { | 249 if (!src.getPixels()) { |
220 return false; | 250 return false; |
221 } | 251 } |
222 | 252 |
223 result->setConfig(src.config(), src.width(), src.height()); | 253 result->setConfig(src.config(), bounds.width(), bounds.height()); |
224 result->allocPixels(); | 254 result->allocPixels(); |
225 | 255 |
226 SkIRect interior = SkIRect::MakeXYWH(fTarget.fX, fTarget.fY, | 256 SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fTarget.fX, |
227 src.width() - fKernelSize.fWidth + 1, | 257 bounds.top() + fTarget.fY, |
228 src.height() - fKernelSize.fHeight + 1)
; | 258 bounds.width() - fKernelSize.fWidth + 1
, |
229 SkIRect top = SkIRect::MakeWH(src.width(), fTarget.fY); | 259 bounds.height() - fKernelSize.fHeight +
1); |
230 SkIRect bottom = SkIRect::MakeLTRB(0, interior.bottom(), | 260 SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(),
interior.top()); |
231 src.width(), src.height()); | 261 SkIRect bottom = SkIRect::MakeLTRB(bounds.left(), interior.bottom(), |
232 SkIRect left = SkIRect::MakeXYWH(0, interior.top(), | 262 bounds.right(), bounds.bottom()); |
233 fTarget.fX, interior.height()); | 263 SkIRect left = SkIRect::MakeLTRB(bounds.left(), interior.top(), |
| 264 interior.left(), interior.bottom()); |
234 SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(), | 265 SkIRect right = SkIRect::MakeLTRB(interior.right(), interior.top(), |
235 src.width(), interior.bottom()); | 266 bounds.right(), interior.bottom()); |
236 filterBorderPixels(src, result, top); | 267 filterBorderPixels(src, result, top, bounds); |
237 filterBorderPixels(src, result, left); | 268 filterBorderPixels(src, result, left, bounds); |
238 filterInteriorPixels(src, result, interior); | 269 filterInteriorPixels(src, result, interior, bounds); |
239 filterBorderPixels(src, result, right); | 270 filterBorderPixels(src, result, right, bounds); |
240 filterBorderPixels(src, result, bottom); | 271 filterBorderPixels(src, result, bottom, bounds); |
| 272 loc->fX += bounds.fLeft; |
| 273 loc->fY += bounds.fTop; |
241 return true; | 274 return true; |
242 } | 275 } |
243 | 276 |
244 #if SK_SUPPORT_GPU | 277 #if SK_SUPPORT_GPU |
245 | 278 |
246 /////////////////////////////////////////////////////////////////////////////// | 279 /////////////////////////////////////////////////////////////////////////////// |
247 | 280 |
248 class GrGLMatrixConvolutionEffect; | 281 class GrGLMatrixConvolutionEffect; |
249 | 282 |
250 class GrMatrixConvolutionEffect : public GrSingleTextureEffect { | 283 class GrMatrixConvolutionEffect : public GrSingleTextureEffect { |
251 public: | 284 public: |
252 typedef SkMatrixConvolutionImageFilter::TileMode TileMode; | 285 typedef SkMatrixConvolutionImageFilter::TileMode TileMode; |
253 static GrEffectRef* Create(GrTexture* texture, | 286 static GrEffectRef* Create(GrTexture* texture, |
| 287 const SkIRect& bounds, |
254 const SkISize& kernelSize, | 288 const SkISize& kernelSize, |
255 const SkScalar* kernel, | 289 const SkScalar* kernel, |
256 SkScalar gain, | 290 SkScalar gain, |
257 SkScalar bias, | 291 SkScalar bias, |
258 const SkIPoint& target, | 292 const SkIPoint& target, |
259 TileMode tileMode, | 293 TileMode tileMode, |
260 bool convolveAlpha) { | 294 bool convolveAlpha) { |
261 AutoEffectUnref effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture, | 295 AutoEffectUnref effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture, |
| 296 bounds, |
262 kernelSize
, | 297 kernelSize
, |
263 kernel, | 298 kernel, |
264 gain, | 299 gain, |
265 bias, | 300 bias, |
266 target, | 301 target, |
267 tileMode, | 302 tileMode, |
268 convolveAl
pha))); | 303 convolveAl
pha))); |
269 return CreateEffectRef(effect); | 304 return CreateEffectRef(effect); |
270 } | 305 } |
271 virtual ~GrMatrixConvolutionEffect(); | 306 virtual ~GrMatrixConvolutionEffect(); |
272 | 307 |
273 virtual void getConstantColorComponents(GrColor* color, | 308 virtual void getConstantColorComponents(GrColor* color, |
274 uint32_t* validFlags) const SK_OVERR
IDE { | 309 uint32_t* validFlags) const SK_OVERR
IDE { |
275 // TODO: Try to do better? | 310 // TODO: Try to do better? |
276 *validFlags = 0; | 311 *validFlags = 0; |
277 } | 312 } |
278 | 313 |
279 static const char* Name() { return "MatrixConvolution"; } | 314 static const char* Name() { return "MatrixConvolution"; } |
| 315 const SkIRect& bounds() const { return fBounds; } |
280 const SkISize& kernelSize() const { return fKernelSize; } | 316 const SkISize& kernelSize() const { return fKernelSize; } |
281 const float* target() const { return fTarget; } | 317 const float* target() const { return fTarget; } |
282 const float* kernel() const { return fKernel; } | 318 const float* kernel() const { return fKernel; } |
283 float gain() const { return fGain; } | 319 float gain() const { return fGain; } |
284 float bias() const { return fBias; } | 320 float bias() const { return fBias; } |
285 TileMode tileMode() const { return fTileMode; } | 321 TileMode tileMode() const { return fTileMode; } |
286 bool convolveAlpha() const { return fConvolveAlpha; } | 322 bool convolveAlpha() const { return fConvolveAlpha; } |
287 | 323 |
288 typedef GrGLMatrixConvolutionEffect GLEffect; | 324 typedef GrGLMatrixConvolutionEffect GLEffect; |
289 | 325 |
290 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 326 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
291 | 327 |
292 private: | 328 private: |
293 GrMatrixConvolutionEffect(GrTexture*, | 329 GrMatrixConvolutionEffect(GrTexture*, |
| 330 const SkIRect& bounds, |
294 const SkISize& kernelSize, | 331 const SkISize& kernelSize, |
295 const SkScalar* kernel, | 332 const SkScalar* kernel, |
296 SkScalar gain, | 333 SkScalar gain, |
297 SkScalar bias, | 334 SkScalar bias, |
298 const SkIPoint& target, | 335 const SkIPoint& target, |
299 TileMode tileMode, | 336 TileMode tileMode, |
300 bool convolveAlpha); | 337 bool convolveAlpha); |
301 | 338 |
302 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; | 339 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; |
303 | 340 |
| 341 SkIRect fBounds; |
304 SkISize fKernelSize; | 342 SkISize fKernelSize; |
305 float *fKernel; | 343 float *fKernel; |
306 float fGain; | 344 float fGain; |
307 float fBias; | 345 float fBias; |
308 float fTarget[2]; | 346 float fTarget[2]; |
309 TileMode fTileMode; | 347 TileMode fTileMode; |
310 bool fConvolveAlpha; | 348 bool fConvolveAlpha; |
311 | 349 |
312 GR_DECLARE_EFFECT_TEST; | 350 GR_DECLARE_EFFECT_TEST; |
313 | 351 |
(...skipping 16 matching lines...) Expand all Loading... |
330 | 368 |
331 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 369 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
332 | 370 |
333 private: | 371 private: |
334 typedef GrGLUniformManager::UniformHandle UniformHandle; | 372 typedef GrGLUniformManager::UniformHandle UniformHandle; |
335 typedef SkMatrixConvolutionImageFilter::TileMode TileMode; | 373 typedef SkMatrixConvolutionImageFilter::TileMode TileMode; |
336 SkISize fKernelSize; | 374 SkISize fKernelSize; |
337 TileMode fTileMode; | 375 TileMode fTileMode; |
338 bool fConvolveAlpha; | 376 bool fConvolveAlpha; |
339 | 377 |
| 378 UniformHandle fBoundsUni; |
340 UniformHandle fKernelUni; | 379 UniformHandle fKernelUni; |
341 UniformHandle fImageIncrementUni; | 380 UniformHandle fImageIncrementUni; |
342 UniformHandle fTargetUni; | 381 UniformHandle fTargetUni; |
343 UniformHandle fGainUni; | 382 UniformHandle fGainUni; |
344 UniformHandle fBiasUni; | 383 UniformHandle fBiasUni; |
345 | 384 |
346 typedef GrGLEffect INHERITED; | 385 typedef GrGLEffect INHERITED; |
347 }; | 386 }; |
348 | 387 |
349 GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa
ctory& factory, | 388 GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa
ctory& factory, |
350 const GrDrawEffect& dra
wEffect) | 389 const GrDrawEffect& dra
wEffect) |
351 : INHERITED(factory) { | 390 : INHERITED(factory) { |
352 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti
onEffect>(); | 391 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti
onEffect>(); |
353 fKernelSize = m.kernelSize(); | 392 fKernelSize = m.kernelSize(); |
354 fTileMode = m.tileMode(); | 393 fTileMode = m.tileMode(); |
355 fConvolveAlpha = m.convolveAlpha(); | 394 fConvolveAlpha = m.convolveAlpha(); |
356 } | 395 } |
357 | 396 |
358 static void appendTextureLookup(GrGLShaderBuilder* builder, | 397 static void appendTextureLookup(GrGLShaderBuilder* builder, |
359 const GrGLShaderBuilder::TextureSampler& sampler
, | 398 const GrGLShaderBuilder::TextureSampler& sampler
, |
360 const char* coord, | 399 const char* coord, |
| 400 const char* bounds, |
361 SkMatrixConvolutionImageFilter::TileMode tileMod
e) { | 401 SkMatrixConvolutionImageFilter::TileMode tileMod
e) { |
362 SkString clampedCoord; | 402 SkString clampedCoord; |
363 switch (tileMode) { | 403 switch (tileMode) { |
364 case SkMatrixConvolutionImageFilter::kClamp_TileMode: | 404 case SkMatrixConvolutionImageFilter::kClamp_TileMode: |
365 clampedCoord.printf("clamp(%s, 0.0, 1.0)", coord); | 405 clampedCoord.printf("clamp(%s, %s.xy, %s.zw)", coord, bounds, bounds
); |
366 coord = clampedCoord.c_str(); | 406 coord = clampedCoord.c_str(); |
367 break; | 407 break; |
368 case SkMatrixConvolutionImageFilter::kRepeat_TileMode: | 408 case SkMatrixConvolutionImageFilter::kRepeat_TileMode: |
369 clampedCoord.printf("fract(%s)", coord); | 409 clampedCoord.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy", coord,
bounds, bounds, bounds, bounds); |
370 coord = clampedCoord.c_str(); | 410 coord = clampedCoord.c_str(); |
371 break; | 411 break; |
372 case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: | 412 case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: |
373 builder->fsCodeAppendf("clamp(%s, 0.0, 1.0) != %s ? vec4(0, 0, 0, 0)
: ", coord, coord); | 413 builder->fsCodeAppendf("clamp(%s, %s.xy, %s.zw) != %s ? vec4(0, 0, 0
, 0) : ", coord, bounds, bounds, coord); |
374 break; | 414 break; |
375 } | 415 } |
376 builder->fsAppendTextureLookup(sampler, coord); | 416 builder->fsAppendTextureLookup(sampler, coord); |
377 } | 417 } |
378 | 418 |
379 void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, | 419 void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, |
380 const GrDrawEffect&, | 420 const GrDrawEffect&, |
381 EffectKey key, | 421 EffectKey key, |
382 const char* outputColor, | 422 const char* outputColor, |
383 const char* inputColor, | 423 const char* inputColor, |
384 const TransformedCoordsArray& coords, | 424 const TransformedCoordsArray& coords, |
385 const TextureSamplerArray& samplers)
{ | 425 const TextureSamplerArray& samplers)
{ |
386 SkString coords2D = builder->ensureFSCoords2D(coords, 0); | 426 SkString coords2D = builder->ensureFSCoords2D(coords, 0); |
| 427 fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
| 428 kVec4f_GrSLType, "Bounds"); |
387 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi
lity, | 429 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi
lity, |
388 kVec2f_GrSLType, "ImageIncrement"); | 430 kVec2f_GrSLType, "ImageIncrement"); |
389 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibilit
y, | 431 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibilit
y, |
390 kFloat_GrSLType, "Kernel", fKernelS
ize.width() * fKernelSize.height()); | 432 kFloat_GrSLType, |
| 433 "Kernel", |
| 434 fKernelSize.width() * fKernelSize.h
eight()); |
391 fTargetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 435 fTargetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
392 kVec2f_GrSLType, "Target"); | 436 kVec2f_GrSLType, "Target"); |
393 fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 437 fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
394 kFloat_GrSLType, "Gain"); | 438 kFloat_GrSLType, "Gain"); |
395 fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 439 fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
396 kFloat_GrSLType, "Bias"); | 440 kFloat_GrSLType, "Bias"); |
397 | 441 |
| 442 const char* bounds = builder->getUniformCStr(fBoundsUni); |
398 const char* target = builder->getUniformCStr(fTargetUni); | 443 const char* target = builder->getUniformCStr(fTargetUni); |
399 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | 444 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); |
400 const char* kernel = builder->getUniformCStr(fKernelUni); | 445 const char* kernel = builder->getUniformCStr(fKernelUni); |
401 const char* gain = builder->getUniformCStr(fGainUni); | 446 const char* gain = builder->getUniformCStr(fGainUni); |
402 const char* bias = builder->getUniformCStr(fBiasUni); | 447 const char* bias = builder->getUniformCStr(fBiasUni); |
403 int kWidth = fKernelSize.width(); | 448 int kWidth = fKernelSize.width(); |
404 int kHeight = fKernelSize.height(); | 449 int kHeight = fKernelSize.height(); |
405 | 450 |
406 builder->fsCodeAppend("\t\tvec4 sum = vec4(0, 0, 0, 0);\n"); | 451 builder->fsCodeAppend("\t\tvec4 sum = vec4(0, 0, 0, 0);\n"); |
407 builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(),
target, imgInc); | 452 builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(),
target, imgInc); |
408 builder->fsCodeAppendf("\t\tfor (int y = 0; y < %d; y++) {\n", kHeight); | 453 builder->fsCodeAppendf("\t\tfor (int y = 0; y < %d; y++) {\n", kHeight); |
409 builder->fsCodeAppendf("\t\t\tfor (int x = 0; x < %d; x++) {\n", kWidth); | 454 builder->fsCodeAppendf("\t\t\tfor (int x = 0; x < %d; x++) {\n", kWidth); |
410 builder->fsCodeAppendf("\t\t\t\tfloat k = %s[y * %d + x];\n", kernel, kWidth
); | 455 builder->fsCodeAppendf("\t\t\t\tfloat k = %s[y * %d + x];\n", kernel, kWidth
); |
411 builder->fsCodeAppendf("\t\t\t\tvec2 coord2 = coord + vec2(x, y) * %s;\n", i
mgInc); | 456 builder->fsCodeAppendf("\t\t\t\tvec2 coord2 = coord + vec2(x, y) * %s;\n", i
mgInc); |
412 builder->fsCodeAppend("\t\t\t\tvec4 c = "); | 457 builder->fsCodeAppend("\t\t\t\tvec4 c = "); |
413 appendTextureLookup(builder, samplers[0], "coord2", fTileMode); | 458 appendTextureLookup(builder, samplers[0], "coord2", bounds, fTileMode); |
414 builder->fsCodeAppend(";\n"); | 459 builder->fsCodeAppend(";\n"); |
415 if (!fConvolveAlpha) { | 460 if (!fConvolveAlpha) { |
416 builder->fsCodeAppend("\t\t\t\tc.rgb /= c.a;\n"); | 461 builder->fsCodeAppend("\t\t\t\tc.rgb /= c.a;\n"); |
417 } | 462 } |
418 builder->fsCodeAppend("\t\t\t\tsum += c * k;\n"); | 463 builder->fsCodeAppend("\t\t\t\tsum += c * k;\n"); |
419 builder->fsCodeAppend("\t\t\t}\n"); | 464 builder->fsCodeAppend("\t\t\t}\n"); |
420 builder->fsCodeAppend("\t\t}\n"); | 465 builder->fsCodeAppend("\t\t}\n"); |
421 if (fConvolveAlpha) { | 466 if (fConvolveAlpha) { |
422 builder->fsCodeAppendf("\t\t%s = sum * %s + %s;\n", outputColor, gain, b
ias); | 467 builder->fsCodeAppendf("\t\t%s = sum * %s + %s;\n", outputColor, gain, b
ias); |
423 builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", outpu
tColor, outputColor, outputColor); | 468 builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", |
| 469 outputColor, outputColor, outputColor); |
424 } else { | 470 } else { |
425 builder->fsCodeAppend("\t\tvec4 c = "); | 471 builder->fsCodeAppend("\t\tvec4 c = "); |
426 appendTextureLookup(builder, samplers[0], coords2D.c_str(), fTileMode); | 472 appendTextureLookup(builder, samplers[0], coords2D.c_str(), bounds, fTil
eMode); |
427 builder->fsCodeAppend(";\n"); | 473 builder->fsCodeAppend(";\n"); |
428 builder->fsCodeAppendf("\t\t%s.a = c.a;\n", outputColor); | 474 builder->fsCodeAppendf("\t\t%s.a = c.a;\n", outputColor); |
429 builder->fsCodeAppendf("\t\t%s.rgb = sum.rgb * %s + %s;\n", outputColor,
gain, bias); | 475 builder->fsCodeAppendf("\t\t%s.rgb = sum.rgb * %s + %s;\n", outputColor,
gain, bias); |
430 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor
); | 476 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor
); |
431 } | 477 } |
432 } | 478 } |
433 | 479 |
434 namespace { | 480 namespace { |
435 | 481 |
436 int encodeXY(int x, int y) { | 482 int encodeXY(int x, int y) { |
(...skipping 24 matching lines...) Expand all Loading... |
461 SkASSERT(conv.tileMode() == fTileMode); | 507 SkASSERT(conv.tileMode() == fTileMode); |
462 float imageIncrement[2]; | 508 float imageIncrement[2]; |
463 float ySign = texture.origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; | 509 float ySign = texture.origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; |
464 imageIncrement[0] = 1.0f / texture.width(); | 510 imageIncrement[0] = 1.0f / texture.width(); |
465 imageIncrement[1] = ySign / texture.height(); | 511 imageIncrement[1] = ySign / texture.height(); |
466 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); | 512 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); |
467 uman.set2fv(fTargetUni, 0, 1, conv.target()); | 513 uman.set2fv(fTargetUni, 0, 1, conv.target()); |
468 uman.set1fv(fKernelUni, 0, fKernelSize.width() * fKernelSize.height(), conv.
kernel()); | 514 uman.set1fv(fKernelUni, 0, fKernelSize.width() * fKernelSize.height(), conv.
kernel()); |
469 uman.set1f(fGainUni, conv.gain()); | 515 uman.set1f(fGainUni, conv.gain()); |
470 uman.set1f(fBiasUni, conv.bias()); | 516 uman.set1f(fBiasUni, conv.bias()); |
| 517 const SkIRect& bounds = conv.bounds(); |
| 518 uman.set4f(fBoundsUni, |
| 519 (float) bounds.left() / texture.width(), |
| 520 (float) bounds.top() / texture.height(), |
| 521 (float) bounds.right() / texture.width(), |
| 522 (float) bounds.bottom() / texture.height()); |
471 } | 523 } |
472 | 524 |
473 GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, | 525 GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, |
| 526 const SkIRect& bounds, |
474 const SkISize& kernelSize, | 527 const SkISize& kernelSize, |
475 const SkScalar* kernel, | 528 const SkScalar* kernel, |
476 SkScalar gain, | 529 SkScalar gain, |
477 SkScalar bias, | 530 SkScalar bias, |
478 const SkIPoint& target, | 531 const SkIPoint& target, |
479 TileMode tileMode, | 532 TileMode tileMode, |
480 bool convolveAlpha) | 533 bool convolveAlpha) |
481 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)), | 534 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)), |
| 535 fBounds(bounds), |
482 fKernelSize(kernelSize), | 536 fKernelSize(kernelSize), |
483 fGain(SkScalarToFloat(gain)), | 537 fGain(SkScalarToFloat(gain)), |
484 fBias(SkScalarToFloat(bias) / 255.0f), | 538 fBias(SkScalarToFloat(bias) / 255.0f), |
485 fTileMode(tileMode), | 539 fTileMode(tileMode), |
486 fConvolveAlpha(convolveAlpha) { | 540 fConvolveAlpha(convolveAlpha) { |
487 fKernel = new float[kernelSize.width() * kernelSize.height()]; | 541 fKernel = new float[kernelSize.width() * kernelSize.height()]; |
488 for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) { | 542 for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) { |
489 fKernel[i] = SkScalarToFloat(kernel[i]); | 543 fKernel[i] = SkScalarToFloat(kernel[i]); |
490 } | 544 } |
491 fTarget[0] = static_cast<float>(target.x()); | 545 fTarget[0] = static_cast<float>(target.x()); |
492 fTarget[1] = static_cast<float>(target.y()); | 546 fTarget[1] = static_cast<float>(target.y()); |
493 } | 547 } |
494 | 548 |
495 GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() { | 549 GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() { |
496 delete[] fKernel; | 550 delete[] fKernel; |
497 } | 551 } |
498 | 552 |
499 const GrBackendEffectFactory& GrMatrixConvolutionEffect::getFactory() const { | 553 const GrBackendEffectFactory& GrMatrixConvolutionEffect::getFactory() const { |
500 return GrTBackendEffectFactory<GrMatrixConvolutionEffect>::getInstance(); | 554 return GrTBackendEffectFactory<GrMatrixConvolutionEffect>::getInstance(); |
501 } | 555 } |
502 | 556 |
503 bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const { | 557 bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const { |
504 const GrMatrixConvolutionEffect& s = CastEffect<GrMatrixConvolutionEffect>(s
Base); | 558 const GrMatrixConvolutionEffect& s = CastEffect<GrMatrixConvolutionEffect>(s
Base); |
505 return this->texture(0) == s.texture(0) && | 559 return this->texture(0) == s.texture(0) && |
506 fKernelSize == s.kernelSize() && | 560 fKernelSize == s.kernelSize() && |
507 !memcmp(fKernel, s.kernel(), fKernelSize.width() * fKernelSize.height
() * sizeof(float)) && | 561 !memcmp(fKernel, s.kernel(), |
| 562 fKernelSize.width() * fKernelSize.height() * sizeof(float)) &
& |
508 fGain == s.gain() && | 563 fGain == s.gain() && |
509 fBias == s.bias() && | 564 fBias == s.bias() && |
510 fTarget == s.target() && | 565 fTarget == s.target() && |
511 fTileMode == s.tileMode() && | 566 fTileMode == s.tileMode() && |
512 fConvolveAlpha == s.convolveAlpha(); | 567 fConvolveAlpha == s.convolveAlpha(); |
513 } | 568 } |
514 | 569 |
515 GR_DEFINE_EFFECT_TEST(GrMatrixConvolutionEffect); | 570 GR_DEFINE_EFFECT_TEST(GrMatrixConvolutionEffect); |
516 | 571 |
517 // A little bit less than the minimum # uniforms required by DX9SM2 (32). | 572 // A little bit less than the minimum # uniforms required by DX9SM2 (32). |
(...skipping 10 matching lines...) Expand all Loading... |
528 int height = random->nextRangeU(1, MAX_KERNEL_SIZE / width); | 583 int height = random->nextRangeU(1, MAX_KERNEL_SIZE / width); |
529 SkISize kernelSize = SkISize::Make(width, height); | 584 SkISize kernelSize = SkISize::Make(width, height); |
530 SkAutoTDeleteArray<SkScalar> kernel(new SkScalar[width * height]); | 585 SkAutoTDeleteArray<SkScalar> kernel(new SkScalar[width * height]); |
531 for (int i = 0; i < width * height; i++) { | 586 for (int i = 0; i < width * height; i++) { |
532 kernel.get()[i] = random->nextSScalar1(); | 587 kernel.get()[i] = random->nextSScalar1(); |
533 } | 588 } |
534 SkScalar gain = random->nextSScalar1(); | 589 SkScalar gain = random->nextSScalar1(); |
535 SkScalar bias = random->nextSScalar1(); | 590 SkScalar bias = random->nextSScalar1(); |
536 SkIPoint target = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()), | 591 SkIPoint target = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()), |
537 random->nextRangeU(0, kernelSize.height()))
; | 592 random->nextRangeU(0, kernelSize.height()))
; |
| 593 SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->w
idth()), |
| 594 random->nextRangeU(0, textures[texIdx]->h
eight()), |
| 595 random->nextRangeU(0, textures[texIdx]->w
idth()), |
| 596 random->nextRangeU(0, textures[texIdx]->h
eight())); |
538 TileMode tileMode = static_cast<TileMode>(random->nextRangeU(0, 2)); | 597 TileMode tileMode = static_cast<TileMode>(random->nextRangeU(0, 2)); |
539 bool convolveAlpha = random->nextBool(); | 598 bool convolveAlpha = random->nextBool(); |
540 return GrMatrixConvolutionEffect::Create(textures[texIdx], | 599 return GrMatrixConvolutionEffect::Create(textures[texIdx], |
| 600 bounds, |
541 kernelSize, | 601 kernelSize, |
542 kernel.get(), | 602 kernel.get(), |
543 gain, | 603 gain, |
544 bias, | 604 bias, |
545 target, | 605 target, |
546 tileMode, | 606 tileMode, |
547 convolveAlpha); | 607 convolveAlpha); |
548 } | 608 } |
549 | 609 |
550 bool SkMatrixConvolutionImageFilter::asNewEffect(GrEffectRef** effect, | 610 bool SkMatrixConvolutionImageFilter::asNewEffect(GrEffectRef** effect, |
551 GrTexture* texture, | 611 GrTexture* texture, |
552 const SkMatrix&) const { | 612 const SkMatrix&, |
| 613 const SkIRect& bounds |
| 614 ) const { |
553 if (!effect) { | 615 if (!effect) { |
554 return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE; | 616 return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE; |
555 } | 617 } |
556 SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE); | 618 SkASSERT(fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE); |
557 *effect = GrMatrixConvolutionEffect::Create(texture, | 619 *effect = GrMatrixConvolutionEffect::Create(texture, |
| 620 bounds, |
558 fKernelSize, | 621 fKernelSize, |
559 fKernel, | 622 fKernel, |
560 fGain, | 623 fGain, |
561 fBias, | 624 fBias, |
562 fTarget, | 625 fTarget, |
563 fTileMode, | 626 fTileMode, |
564 fConvolveAlpha); | 627 fConvolveAlpha); |
565 return true; | 628 return true; |
566 } | 629 } |
567 | 630 |
568 /////////////////////////////////////////////////////////////////////////////// | 631 /////////////////////////////////////////////////////////////////////////////// |
569 | 632 |
570 #endif | 633 #endif |
OLD | NEW |