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

Side by Side Diff: src/gpu/effects/GrConvolutionEffect.cpp

Issue 1247063005: Revert of Bilinear optimization for 1D convolution. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/Gr1DKernelEffect.h ('k') | no next file » | 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 2012 Google Inc. 2 * Copyright 2012 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 "GrConvolutionEffect.h" 8 #include "GrConvolutionEffect.h"
9 #include "gl/GrGLProcessor.h" 9 #include "gl/GrGLProcessor.h"
10 #include "gl/GrGLTexture.h" 10 #include "gl/GrGLTexture.h"
11 #include "gl/builders/GrGLProgramBuilder.h" 11 #include "gl/builders/GrGLProgramBuilder.h"
12 12
13 // For brevity 13 // For brevity
14 typedef GrGLProgramDataManager::UniformHandle UniformHandle; 14 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
15 15
16 /**
17 * Base class with shared functionality for GrGLBoundedConvolutionEffect and
18 * GrGLLerpConvolutionEffect.
19 */
20 class GrGLConvolutionEffect : public GrGLFragmentProcessor { 16 class GrGLConvolutionEffect : public GrGLFragmentProcessor {
21 public: 17 public:
22 GrGLConvolutionEffect(const GrProcessor&); 18 GrGLConvolutionEffect(const GrProcessor&);
19
20 virtual void emitCode(GrGLFPBuilder*,
21 const GrFragmentProcessor&,
22 const char* outputColor,
23 const char* inputColor,
24 const TransformedCoordsArray&,
25 const TextureSamplerArray&) override;
26
27 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de;
28
23 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*); 29 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
24 30
25 protected: 31 private:
26 int radius() const { return fRadius; }
27 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); } 32 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
33 bool useBounds() const { return fUseBounds; }
28 Gr1DKernelEffect::Direction direction() const { return fDirection; } 34 Gr1DKernelEffect::Direction direction() const { return fDirection; }
29 void getImageIncrement(const GrConvolutionEffect&, float (*)[2]) const;
30 35
31 private: 36 int fRadius;
32 int fRadius; 37 bool fUseBounds;
33 Gr1DKernelEffect::Direction fDirection; 38 Gr1DKernelEffect::Direction fDirection;
39 UniformHandle fKernelUni;
40 UniformHandle fImageIncrementUni;
41 UniformHandle fBoundsUni;
34 42
35 typedef GrGLFragmentProcessor INHERITED; 43 typedef GrGLFragmentProcessor INHERITED;
36 }; 44 };
37 45
38 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrProcessor& processor) { 46 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrProcessor& processor) {
39 const GrConvolutionEffect& c = processor.cast<GrConvolutionEffect>(); 47 const GrConvolutionEffect& c = processor.cast<GrConvolutionEffect>();
40 fRadius = c.radius(); 48 fRadius = c.radius();
49 fUseBounds = c.useBounds();
41 fDirection = c.direction(); 50 fDirection = c.direction();
42 } 51 }
43 52
44 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor, 53 void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder,
45 const GrGLSLCaps&, 54 const GrFragmentProcessor&,
55 const char* outputColor,
56 const char* inputColor,
57 const TransformedCoordsArray& coords,
58 const TextureSamplerArray& samplers) {
59 fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visib ility,
60 kVec2f_GrSLType, kDefault_GrSLPreci sion,
61 "ImageIncrement");
62 if (this->useBounds()) {
63 fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibilit y,
64 kVec2f_GrSLType, kDefault_GrSLPrecision ,
65 "Bounds");
66 }
67 fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibili ty,
68 kFloat_GrSLType, kDefault_GrSLPrecisio n,
69 "Kernel", this->width());
70
71 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
72 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
73
74 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
75
76 int width = this->width();
77 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
78 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
79
80 fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str( ), fRadius, imgInc);
81
82 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
83 for (int i = 0; i < width; i++) {
84 SkString index;
85 SkString kernelIndex;
86 index.appendS32(i);
87 kernel.appendArrayAccess(index.c_str(), &kernelIndex);
88
89 if (this->useBounds()) {
90 // We used to compute a bool indicating whether we're in bounds or n ot, cast it to a
91 // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems
92 // to have a bug that caused corruption.
93 const char* bounds = builder->getUniformCStr(fBoundsUni);
94 const char* component = this->direction() == Gr1DKernelEffect::kY_Di rection ? "y" : "x";
95 fsBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {" ,
96 component, bounds, component, bounds);
97 }
98 fsBuilder->codeAppendf("\t\t%s += ", outputColor);
99 fsBuilder->appendTextureLookup(samplers[0], "coord");
100 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
101 if (this->useBounds()) {
102 fsBuilder->codeAppend("}");
103 }
104 fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
105 }
106
107 SkString modulate;
108 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
109 fsBuilder->codeAppend(modulate.c_str());
110 }
111
112 void GrGLConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
113 const GrProcessor& processor) {
114 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
115 GrTexture& texture = *conv.texture(0);
116 // the code we generated was for a specific kernel radius
117 SkASSERT(conv.radius() == fRadius);
118 float imageIncrement[2] = { 0 };
119 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
120 switch (conv.direction()) {
121 case Gr1DKernelEffect::kX_Direction:
122 imageIncrement[0] = 1.0f / texture.width();
123 break;
124 case Gr1DKernelEffect::kY_Direction:
125 imageIncrement[1] = ySign / texture.height();
126 break;
127 default:
128 SkFAIL("Unknown filter direction.");
129 }
130 pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
131 if (conv.useBounds()) {
132 const float* bounds = conv.bounds();
133 if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
134 texture.origin() != kTopLeft_GrSurfaceOrigin) {
135 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
136 } else {
137 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
138 }
139 }
140 pdman.set1fv(fKernelUni, this->width(), conv.kernel());
141 }
142
143 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&,
46 GrProcessorKeyBuilder* b) { 144 GrProcessorKeyBuilder* b) {
47 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); 145 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
48 uint32_t key = conv.radius(); 146 uint32_t key = conv.radius();
49 key <<= 2; 147 key <<= 2;
50 if (conv.useBounds()) { 148 if (conv.useBounds()) {
51 key |= 0x2; 149 key |= 0x2;
52 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ; 150 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ;
53 } 151 }
54 b->add32(key); 152 b->add32(key);
55 } 153 }
56 154
57 void GrGLConvolutionEffect::getImageIncrement(const GrConvolutionEffect& conv,
58 float (*imageIncrement)[2]) const {
59 GrTexture& texture = *conv.texture(0);
60 (*imageIncrement)[0] = (*imageIncrement)[1] = 0;
61 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
62 switch (conv.direction()) {
63 case Gr1DKernelEffect::kX_Direction:
64 (*imageIncrement)[0] = 1.0f / texture.width();
65 break;
66 case Gr1DKernelEffect::kY_Direction:
67 (*imageIncrement)[1] = ySign / texture.height();
68 break;
69 default:
70 SkFAIL("Unknown filter direction.");
71 }
72 }
73
74 ///////////////////////////////////////////////////////////////////////////////
75
76 /**
77 * Applies a convolution effect which restricts samples to the provided bounds
78 * using shader logic.
79 */
80 class GrGLBoundedConvolutionEffect : public GrGLConvolutionEffect {
81 public:
82 GrGLBoundedConvolutionEffect(const GrProcessor& processor) : INHERITED(proce ssor) {}
83
84 virtual void emitCode(GrGLFPBuilder*,
85 const GrFragmentProcessor&,
86 const char* outputColor,
87 const char* inputColor,
88 const TransformedCoordsArray&,
89 const TextureSamplerArray&) override;
90
91 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de;
92
93 private:
94 UniformHandle fKernelUni;
95 UniformHandle fImageIncrementUni;
96 UniformHandle fBoundsUni;
97
98 typedef GrGLConvolutionEffect INHERITED;
99 };
100
101 void GrGLBoundedConvolutionEffect::emitCode(GrGLFPBuilder* builder,
102 const GrFragmentProcessor& processor ,
103 const char* outputColor,
104 const char* inputColor,
105 const TransformedCoordsArray& coords ,
106 const TextureSamplerArray& samplers) {
107 fImageIncrementUni =
108 builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrS LType,
109 kDefault_GrSLPrecision, "ImageIncrement");
110
111 fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, k Vec2f_GrSLType,
112 kDefault_GrSLPrecision, "Bounds");
113
114 fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibili ty, kFloat_GrSLType,
115 kDefault_GrSLPrecision, "Kernel", this ->width());
116
117 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
118 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
119
120 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", outputColor);
121
122 int width = this->width();
123 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
124 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
125
126 fsBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), t his->radius(),
127 imgInc);
128
129 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
130 for (int i = 0; i < width; i++) {
131 SkString index;
132 SkString kernelIndex;
133 index.appendS32(i);
134 kernel.appendArrayAccess(index.c_str(), &kernelIndex);
135 // We used to compute a bool indicating whether we're in bounds or not, cast it to a
136 // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems
137 // to have a bug that caused corruption.
138 const char* bounds = builder->getUniformCStr(fBoundsUni);
139 const char* component = this->direction() == Gr1DKernelEffect::kY_Direct ion ? "y" : "x";
140 fsBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {",
141 component, bounds, component, bounds);
142 fsBuilder->codeAppendf("%s += ", outputColor);
143 fsBuilder->appendTextureLookup(samplers[0], "coord");
144 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
145 fsBuilder->codeAppend("}");
146 fsBuilder->codeAppendf("coord += %s;\n", imgInc);
147 }
148
149 SkString modulate;
150 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
151 fsBuilder->codeAppend(modulate.c_str());
152 }
153
154 void GrGLBoundedConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
155 const GrProcessor& processor) {
156 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
157
158 // the code we generated was for a specific kernel radius
159 SkASSERT(conv.radius() == this->radius());
160
161 // the code we generated was for a specific bounding mode.
162 SkASSERT(conv.useBounds());
163
164 GrTexture& texture = *conv.texture(0);
165 float imageIncrement[2];
166 getImageIncrement(conv, &imageIncrement);
167 pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
168 const float* bounds = conv.bounds();
169 if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
170 texture.origin() != kTopLeft_GrSurfaceOrigin) {
171 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
172 } else {
173 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
174 }
175 pdman.set1fv(fKernelUni, this->width(), conv.kernel());
176 }
177
178 ///////////////////////////////////////////////////////////////////////////////
179
180 /**
181 * Applies a convolution effect which applies the convolution using a linear
182 * interpolation optimization to use half as many samples.
183 */
184 class GrGLLerpConvolutionEffect : public GrGLConvolutionEffect {
185 public:
186 GrGLLerpConvolutionEffect(const GrProcessor& processor) : INHERITED(processo r) {}
187
188 virtual void emitCode(GrGLFPBuilder*,
189 const GrFragmentProcessor&,
190 const char* outputColor,
191 const char* inputColor,
192 const TransformedCoordsArray&,
193 const TextureSamplerArray&) override;
194
195 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de;
196
197 private:
198 int bilerpSampleCount() const;
199
200 // Bounded uniforms
201 UniformHandle fSampleWeightUni;
202 UniformHandle fSampleOffsetUni;
203
204 typedef GrGLConvolutionEffect INHERITED;
205 };
206
207 void GrGLLerpConvolutionEffect::emitCode(GrGLFPBuilder* builder,
208 const GrFragmentProcessor& processor,
209 const char* outputColor,
210 const char* inputColor,
211 const TransformedCoordsArray& coords,
212 const TextureSamplerArray& samplers) {
213 int sampleCount = bilerpSampleCount();
214
215 // We use 2 * sampleCount uniforms. The maximum allowed by PS2.0 is 32, so
216 // ensure we don't exceed this. Note that it is currently impossible to
217 // exceed this as bilerpSampleCount = (kernelWidth + 1) / 2, and kernelWidth
218 // maxes out at 25, resulting in a max sampleCount of 26.
219 SkASSERT(sampleCount < 16);
220
221 fSampleOffsetUni =
222 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kVec2 f_GrSLType,
223 kDefault_GrSLPrecision, "SampleOffset", sampleC ount);
224 fSampleWeightUni =
225 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloa t_GrSLType,
226 kDefault_GrSLPrecision, "SampleWeight", sampleC ount);
227
228 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
229 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
230
231 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", outputColor);
232
233 const GrGLShaderVar& kernel = builder->getUniformVariable(fSampleWeightUni);
234 const GrGLShaderVar& imgInc = builder->getUniformVariable(fSampleOffsetUni);
235
236 fsBuilder->codeAppendf("vec2 coord; \n");
237
238 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
239 for (int i = 0; i < sampleCount; i++) {
240 SkString index;
241 SkString weightIndex;
242 SkString offsetIndex;
243 index.appendS32(i);
244 kernel.appendArrayAccess(index.c_str(), &weightIndex);
245 imgInc.appendArrayAccess(index.c_str(), &offsetIndex);
246 fsBuilder->codeAppendf("coord = %s + %s;\n", coords2D.c_str(), offsetInd ex.c_str());
247 fsBuilder->codeAppendf("%s += ", outputColor);
248 fsBuilder->appendTextureLookup(samplers[0], "coord");
249 fsBuilder->codeAppendf(" * %s;\n", weightIndex.c_str());
250 }
251
252 SkString modulate;
253 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
254 fsBuilder->codeAppend(modulate.c_str());
255 }
256
257 void GrGLLerpConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
258 const GrProcessor& processor) {
259 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
260
261 // the code we generated was for a specific kernel radius
262 SkASSERT(conv.radius() == this->radius());
263
264 // the code we generated was for a specific bounding mode.
265 SkASSERT(!conv.useBounds());
266
267 int sampleCount = bilerpSampleCount();
268 SkAutoTArray<float> imageIncrements(sampleCount * 2); // X and Y floats per sample.
269 SkAutoTArray<float> kernel(sampleCount);
270
271 float baseImageIncrement[2];
272 getImageIncrement(conv, &baseImageIncrement);
273
274 for (int i = 0; i < sampleCount; i++) {
275 int sampleIndex1 = i * 2;
276 int sampleIndex2 = sampleIndex1 + 1;
277
278 // If we have an odd number of samples in our filter, the last sample wo n't use
279 // the linear interpolation optimization (it will be pixel aligned).
280 if (sampleIndex2 >= this->width()) {
281 sampleIndex2 = sampleIndex1;
282 }
283
284 float kernelWeight1 = conv.kernel()[sampleIndex1];
285 float kernelWeight2 = conv.kernel()[sampleIndex2];
286
287 float totalKernelWeight =
288 (sampleIndex1 == sampleIndex2) ? kernelWeight1 : (kernelWeight1 + ke rnelWeight2);
289
290 float sampleRatio =
291 (sampleIndex1 == sampleIndex2) ? 0 : kernelWeight2 / (kernelWeight1 + kernelWeight2);
292
293 imageIncrements[i * 2] = (-this->radius() + i * 2 + sampleRatio) * baseI mageIncrement[0];
294 imageIncrements[i * 2 + 1] =
295 (-this->radius() + i * 2 + sampleRatio) * baseImageIncrement[1];
296
297 kernel[i] = totalKernelWeight;
298 }
299 pdman.set2fv(fSampleOffsetUni, sampleCount, imageIncrements.get());
300 pdman.set1fv(fSampleWeightUni, sampleCount, kernel.get());
301 }
302
303 int GrGLLerpConvolutionEffect::bilerpSampleCount() const {
304 // We use a linear interpolation optimization to only sample once for each
305 // two pixel aligned samples in the kernel. If we have an odd number of
306 // samples, we will have to skip this optimization for the last sample.
307 // Because of this we always round up our sample count (by adding 1 before
308 // dividing).
309 return (this->width() + 1) / 2;
310 }
311
312 /////////////////////////////////////////////////////////////////////////////// 155 ///////////////////////////////////////////////////////////////////////////////
313 156
314 GrConvolutionEffect::GrConvolutionEffect(GrProcessorDataManager* procDataManager , 157 GrConvolutionEffect::GrConvolutionEffect(GrProcessorDataManager* procDataManager ,
315 GrTexture* texture, 158 GrTexture* texture,
316 Direction direction, 159 Direction direction,
317 int radius, 160 int radius,
318 const float* kernel, 161 const float* kernel,
319 bool useBounds, 162 bool useBounds,
320 float bounds[2]) 163 float bounds[2])
321 : INHERITED(procDataManager, 164 : INHERITED(procDataManager, texture, direction, radius), fUseBounds(useBoun ds) {
322 texture,
323 direction,
324 radius,
325 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
326 : GrTextureParams::FilterMode::kBilerp_FilterMode)
327 , fUseBounds(useBounds) {
328 this->initClassID<GrConvolutionEffect>(); 165 this->initClassID<GrConvolutionEffect>();
329 SkASSERT(radius <= kMaxKernelRadius); 166 SkASSERT(radius <= kMaxKernelRadius);
330 SkASSERT(kernel); 167 SkASSERT(kernel);
331 int width = this->width(); 168 int width = this->width();
332 for (int i = 0; i < width; i++) { 169 for (int i = 0; i < width; i++) {
333 fKernel[i] = kernel[i]; 170 fKernel[i] = kernel[i];
334 } 171 }
335 memcpy(fBounds, bounds, sizeof(fBounds)); 172 memcpy(fBounds, bounds, sizeof(fBounds));
336 } 173 }
337 174
338 GrConvolutionEffect::GrConvolutionEffect(GrProcessorDataManager* procDataManager , 175 GrConvolutionEffect::GrConvolutionEffect(GrProcessorDataManager* procDataManager ,
339 GrTexture* texture, 176 GrTexture* texture,
340 Direction direction, 177 Direction direction,
341 int radius, 178 int radius,
342 float gaussianSigma, 179 float gaussianSigma,
343 bool useBounds, 180 bool useBounds,
344 float bounds[2]) 181 float bounds[2])
345 : INHERITED(procDataManager, 182 : INHERITED(procDataManager, texture, direction, radius), fUseBounds(useBoun ds) {
346 texture,
347 direction,
348 radius,
349 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
350 : GrTextureParams::FilterMode::kBilerp_FilterMode)
351 , fUseBounds(useBounds) {
352 this->initClassID<GrConvolutionEffect>(); 183 this->initClassID<GrConvolutionEffect>();
353 SkASSERT(radius <= kMaxKernelRadius); 184 SkASSERT(radius <= kMaxKernelRadius);
354 int width = this->width(); 185 int width = this->width();
355 186
356 float sum = 0.0f; 187 float sum = 0.0f;
357 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); 188 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma);
358 for (int i = 0; i < width; ++i) { 189 for (int i = 0; i < width; ++i) {
359 float x = static_cast<float>(i - this->radius()); 190 float x = static_cast<float>(i - this->radius());
360 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian 191 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
361 // is dropped here, since we renormalize the kernel below. 192 // is dropped here, since we renormalize the kernel below.
(...skipping 10 matching lines...) Expand all
372 203
373 GrConvolutionEffect::~GrConvolutionEffect() { 204 GrConvolutionEffect::~GrConvolutionEffect() {
374 } 205 }
375 206
376 void GrConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps, 207 void GrConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps,
377 GrProcessorKeyBuilder* b) const { 208 GrProcessorKeyBuilder* b) const {
378 GrGLConvolutionEffect::GenKey(*this, caps, b); 209 GrGLConvolutionEffect::GenKey(*this, caps, b);
379 } 210 }
380 211
381 GrGLFragmentProcessor* GrConvolutionEffect::createGLInstance() const { 212 GrGLFragmentProcessor* GrConvolutionEffect::createGLInstance() const {
382 // We support a linear interpolation optimization which (when feasible) uses 213 return SkNEW_ARGS(GrGLConvolutionEffect, (*this));
383 // half the number of samples to apply the kernel. This is not always
384 // applicable, as the linear interpolation optimization does not support
385 // bounded sampling.
386 if (this->useBounds()) {
387 return SkNEW_ARGS(GrGLBoundedConvolutionEffect, (*this));
388 } else {
389 return SkNEW_ARGS(GrGLLerpConvolutionEffect, (*this));
390 }
391 } 214 }
392 215
393 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 216 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
394 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>(); 217 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>();
395 return (this->radius() == s.radius() && 218 return (this->radius() == s.radius() &&
396 this->direction() == s.direction() && 219 this->direction() == s.direction() &&
397 this->useBounds() == s.useBounds() && 220 this->useBounds() == s.useBounds() &&
398 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) && 221 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
399 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); 222 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
400 } 223 }
(...skipping 18 matching lines...) Expand all
419 242
420 bool useBounds = d->fRandom->nextBool(); 243 bool useBounds = d->fRandom->nextBool();
421 return GrConvolutionEffect::Create(d->fProcDataManager, 244 return GrConvolutionEffect::Create(d->fProcDataManager,
422 d->fTextures[texIdx], 245 d->fTextures[texIdx],
423 dir, 246 dir,
424 radius, 247 radius,
425 kernel, 248 kernel,
426 useBounds, 249 useBounds,
427 bounds); 250 bounds);
428 } 251 }
OLDNEW
« no previous file with comments | « src/gpu/effects/Gr1DKernelEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698