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

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

Issue 27471002: Implement crop rect support for SkMatrixConvolutionImageFilter. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fix comment Created 7 years, 2 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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()),
bsalomon 2013/10/18 18:56:23 I guess it doesn't really matter, but it's a littl
Stephen White 2013/10/18 20:05:44 True, but we might catch more bugs this way too. :
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
OLDNEW
« include/core/SkImageFilter.h ('K') | « src/effects/SkMagnifierImageFilter.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698