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

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

Issue 1216623003: Bilinear optimization for 1D convolution. 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 * GrGLBilerpConvolutionEffect.
19 */
16 class GrGLConvolutionEffect : public GrGLFragmentProcessor { 20 class GrGLConvolutionEffect : public GrGLFragmentProcessor {
17 public: 21 public:
18 GrGLConvolutionEffect(const GrProcessor&); 22 GrGLConvolutionEffect(const GrProcessor&);
23 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
24
25 protected:
26 int radius() const { return fRadius; }
27 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
28 Gr1DKernelEffect::Direction direction() const { return fDirection; }
29 void getImageIncrement(const GrConvolutionEffect&, float (*)[2]) const;
30
31 private:
32 int fRadius;
33 Gr1DKernelEffect::Direction fDirection;
34
35 typedef GrGLFragmentProcessor INHERITED;
36 };
37
38 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrProcessor& processor) {
39 const GrConvolutionEffect& c = processor.cast<GrConvolutionEffect>();
40 fRadius = c.radius();
41 fDirection = c.direction();
42 }
43
44 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor,
45 const GrGLSLCaps&,
46 GrProcessorKeyBuilder* b) {
47 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
48 uint32_t key = conv.radius();
49 key <<= 2;
50 if (conv.useBounds()) {
51 key |= 0x2;
52 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ;
53 }
54 b->add32(key);
55 }
56
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) {}
19 83
20 virtual void emitCode(GrGLFPBuilder*, 84 virtual void emitCode(GrGLFPBuilder*,
21 const GrFragmentProcessor&, 85 const GrFragmentProcessor&,
22 const char* outputColor, 86 const char* outputColor,
23 const char* inputColor, 87 const char* inputColor,
24 const TransformedCoordsArray&, 88 const TransformedCoordsArray&,
25 const TextureSamplerArray&) override; 89 const TextureSamplerArray&) override;
26 90
27 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de; 91 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de;
28 92
29 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
30
31 private: 93 private:
32 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
33 bool useBounds() const { return fUseBounds; }
34 Gr1DKernelEffect::Direction direction() const { return fDirection; }
35
36 int fRadius;
37 bool fUseBounds;
38 Gr1DKernelEffect::Direction fDirection;
39 UniformHandle fKernelUni; 94 UniformHandle fKernelUni;
40 UniformHandle fImageIncrementUni; 95 UniformHandle fImageIncrementUni;
41 UniformHandle fBoundsUni; 96 UniformHandle fBoundsUni;
42 97
43 typedef GrGLFragmentProcessor INHERITED; 98 typedef GrGLConvolutionEffect INHERITED;
44 }; 99 };
45 100
46 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrProcessor& processor) { 101 void GrGLBoundedConvolutionEffect::emitCode(GrGLFPBuilder* builder,
47 const GrConvolutionEffect& c = processor.cast<GrConvolutionEffect>(); 102 const GrFragmentProcessor& processor ,
48 fRadius = c.radius(); 103 const char* outputColor,
49 fUseBounds = c.useBounds(); 104 const char* inputColor,
50 fDirection = c.direction(); 105 const TransformedCoordsArray& coords ,
51 } 106 const TextureSamplerArray& samplers) {
107 fImageIncrementUni =
108 builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrS LType,
109 kDefault_GrSLPrecision, "ImageIncrement");
52 110
53 void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder, 111 fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, k Vec2f_GrSLType,
54 const GrFragmentProcessor&, 112 kDefault_GrSLPrecision, "Bounds");
55 const char* outputColor, 113
56 const char* inputColor, 114 fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibili ty, kFloat_GrSLType,
57 const TransformedCoordsArray& coords, 115 kDefault_GrSLPrecision, "Kernel", this ->width());
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 116
71 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 117 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
72 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); 118 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
73 119
74 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); 120 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
75 121
76 int width = this->width(); 122 int width = this->width();
77 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); 123 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
78 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 124 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
79 125
80 fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str( ), fRadius, imgInc); 126 fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str( ), this->radius(),
127 imgInc);
81 128
82 // Manually unroll loop because some drivers don't; yields 20-30% speedup. 129 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
83 for (int i = 0; i < width; i++) { 130 for (int i = 0; i < width; i++) {
84 SkString index; 131 SkString index;
85 SkString kernelIndex; 132 SkString kernelIndex;
86 index.appendS32(i); 133 index.appendS32(i);
87 kernel.appendArrayAccess(index.c_str(), &kernelIndex); 134 kernel.appendArrayAccess(index.c_str(), &kernelIndex);
88 fsBuilder->codeAppendf("\t\t%s += ", outputColor); 135 fsBuilder->codeAppendf("\t\t%s += ", outputColor);
89 fsBuilder->appendTextureLookup(samplers[0], "coord"); 136 fsBuilder->appendTextureLookup(samplers[0], "coord");
90 if (this->useBounds()) { 137 const char* bounds = builder->getUniformCStr(fBoundsUni);
91 const char* bounds = builder->getUniformCStr(fBoundsUni); 138 const char* component = this->direction() == Gr1DKernelEffect::kY_Direct ion ? "y" : "x";
92 const char* component = this->direction() == Gr1DKernelEffect::kY_Di rection ? "y" : "x"; 139 fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)", component, bounds,
93 fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s. y)", 140 component, bounds);
94 component, bounds, component, bounds);
95 }
96 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); 141 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
97 fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc); 142 fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
98 } 143 }
99 144
100 SkString modulate; 145 SkString modulate;
101 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); 146 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
102 fsBuilder->codeAppend(modulate.c_str()); 147 fsBuilder->codeAppend(modulate.c_str());
103 } 148 }
104 149
105 void GrGLConvolutionEffect::setData(const GrGLProgramDataManager& pdman, 150 void GrGLBoundedConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
106 const GrProcessor& processor) { 151 const GrProcessor& processor) {
107 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); 152 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
153
154 // the code we generated was for a specific kernel radius
155 SkASSERT(conv.radius() == this->radius());
156
157 // the code we generated was for a specific bounding mode.
158 SkASSERT(conv.useBounds() == true);
159
108 GrTexture& texture = *conv.texture(0); 160 GrTexture& texture = *conv.texture(0);
109 // the code we generated was for a specific kernel radius 161 float imageIncrement[2];
110 SkASSERT(conv.radius() == fRadius); 162 getImageIncrement(conv, &imageIncrement);
111 float imageIncrement[2] = { 0 };
112 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
113 switch (conv.direction()) {
114 case Gr1DKernelEffect::kX_Direction:
115 imageIncrement[0] = 1.0f / texture.width();
116 break;
117 case Gr1DKernelEffect::kY_Direction:
118 imageIncrement[1] = ySign / texture.height();
119 break;
120 default:
121 SkFAIL("Unknown filter direction.");
122 }
123 pdman.set2fv(fImageIncrementUni, 1, imageIncrement); 163 pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
124 if (conv.useBounds()) { 164 const float* bounds = conv.bounds();
125 const float* bounds = conv.bounds(); 165 if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
126 if (Gr1DKernelEffect::kY_Direction == conv.direction() && 166 texture.origin() != kTopLeft_GrSurfaceOrigin) {
127 texture.origin() != kTopLeft_GrSurfaceOrigin) { 167 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
128 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]); 168 } else {
129 } else { 169 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
130 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
131 }
132 } 170 }
133 pdman.set1fv(fKernelUni, this->width(), conv.kernel()); 171 pdman.set1fv(fKernelUni, this->width(), conv.kernel());
134 } 172 }
135 173
136 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&, 174 ///////////////////////////////////////////////////////////////////////////////
137 GrProcessorKeyBuilder* b) { 175
176 /**
177 * Applies a convolution effect which applies the convolution using a bilinear
178 * sampling optimization to use half as many samples.
179 */
180 class GrGLBilerpConvolutionEffect : public GrGLConvolutionEffect {
Stephen White 2015/06/26 21:28:31 <bikeshed> is this really a bilinear fetch? Or ess
ericrk 2015/06/29 17:33:21 yup - that's better :D
181 public:
182 GrGLBilerpConvolutionEffect(const GrProcessor& processor) : INHERITED(proces sor) {}
183
184 virtual void emitCode(GrGLFPBuilder*,
185 const GrFragmentProcessor&,
186 const char* outputColor,
187 const char* inputColor,
188 const TransformedCoordsArray&,
189 const TextureSamplerArray&) override;
190
191 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de;
192
193 private:
194 int bilerpSampleCount() const;
195
196 // Bounded uniforms
197 UniformHandle fSampleWeightUni;
198 UniformHandle fSampleOffsetUni;
199
200 typedef GrGLConvolutionEffect INHERITED;
201 };
202
203 void GrGLBilerpConvolutionEffect::emitCode(GrGLFPBuilder* builder,
204 const GrFragmentProcessor& processor,
205 const char* outputColor,
206 const char* inputColor,
207 const TransformedCoordsArray& coords,
208 const TextureSamplerArray& samplers) {
209 int sampleCount = bilerpSampleCount();
210
211 fSampleOffsetUni =
Stephen White 2015/06/26 21:28:31 How many uniform values does this add up to? You m
ericrk 2015/06/29 17:33:21 I think we're safe (assuming we keep the limit of
Stephen White 2015/06/29 19:04:06 Yep; makes sense. Thanks!
212 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kVec2 f_GrSLType,
213 kDefault_GrSLPrecision, "SampleOffset", sampleC ount);
214 fSampleWeightUni =
215 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloa t_GrSLType,
216 kDefault_GrSLPrecision, "SampleWeight", sampleC ount);
217
218 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
219 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
220
221 fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
bsalomon 2015/06/26 21:07:33 You don't really need the \t's anymore (we now "pr
ericrk 2015/06/26 21:28:22 removed the \t\ts throughout the file
222
223 const GrGLShaderVar& kernel = builder->getUniformVariable(fSampleWeightUni);
224 const GrGLShaderVar& imgInc = builder->getUniformVariable(fSampleOffsetUni);
225
226 fsBuilder->codeAppendf("\t\tvec2 coord; \n");
227
228 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
229 for (int i = 0; i < sampleCount; i++) {
230 SkString index;
231 SkString weightIndex;
232 SkString offsetIndex;
233 index.appendS32(i);
234 kernel.appendArrayAccess(index.c_str(), &weightIndex);
235 imgInc.appendArrayAccess(index.c_str(), &offsetIndex);
236 fsBuilder->codeAppendf("\t\tcoord = %s + %s;\n", coords2D.c_str(), offse tIndex.c_str());
237 fsBuilder->codeAppendf("\t\t%s += ", outputColor);
238 fsBuilder->appendTextureLookup(samplers[0], "coord");
239 fsBuilder->codeAppendf(" * %s;\n", weightIndex.c_str());
240 }
241
242 SkString modulate;
243 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
244 fsBuilder->codeAppend(modulate.c_str());
245 }
246
247 void GrGLBilerpConvolutionEffect::setData(const GrGLProgramDataManager& pdman,
248 const GrProcessor& processor) {
138 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); 249 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
139 uint32_t key = conv.radius(); 250
140 key <<= 2; 251 // the code we generated was for a specific kernel radius
141 if (conv.useBounds()) { 252 SkASSERT(conv.radius() == this->radius());
142 key |= 0x2; 253
143 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ; 254 // the code we generated was for a specific bounding mode.
255 SkASSERT(conv.useBounds() == false);
bsalomon 2015/06/26 21:07:34 !conv.useBounds()?
ericrk 2015/06/26 21:28:22 yup
256
257 int sampleCount = bilerpSampleCount();
258 SkAutoTArray<float> imageIncrements(sampleCount * 2); // X and Y floats per sample.
259 SkAutoTArray<float> kernel(sampleCount);
260
261 float baseImageIncrement[2];
262 getImageIncrement(conv, &baseImageIncrement);
263
264 for (int i = 0; i < sampleCount; i++) {
265 int sampleIndex1 = i * 2;
266 int sampleIndex2 = sampleIndex1 + 1;
267
268 // If we have an odd number of samples in our filter, the last sample wo n't use
269 // the bilinear optimization (it will be pixel aligned).
270 if (sampleIndex2 >= this->width()) {
271 sampleIndex2 = sampleIndex1;
272 }
273
274 float kernelWeight1 = conv.kernel()[sampleIndex1];
275 float kernelWeight2 = conv.kernel()[sampleIndex2];
276
277 float totalKernalWeight =
Stephen White 2015/06/26 21:28:31 Nit: kernal -> kernel?
278 (sampleIndex1 == sampleIndex2) ? kernelWeight1 : (kernelWeight1 + ke rnelWeight2);
279
280 float sampleRatio =
281 (sampleIndex1 == sampleIndex2) ? 0 : kernelWeight2 / (kernelWeight1 + kernelWeight2);
282
283 imageIncrements[i * 2] = (-this->radius() + i * 2 + sampleRatio) * baseI mageIncrement[0];
284 imageIncrements[i * 2 + 1] =
285 (-this->radius() + i * 2 + sampleRatio) * baseImageIncrement[1];
286
287 kernel[i] = totalKernalWeight;
144 } 288 }
145 b->add32(key); 289 pdman.set2fv(fSampleOffsetUni, sampleCount, imageIncrements.get());
290 pdman.set1fv(fSampleWeightUni, sampleCount, kernel.get());
291 }
292
293 int GrGLBilerpConvolutionEffect::bilerpSampleCount() const {
294 // We use a bilinear optimization to only sample once for each two pixel ali gned
295 // samples in the kernel. If we have an odd number of samples, we will have to
296 // skip this optimization for the last sample. Because of this we always rou nd
297 // up our sample count (by adding 1 before dividing).
298 return (this->width() + 1) / 2;
146 } 299 }
147 300
148 /////////////////////////////////////////////////////////////////////////////// 301 ///////////////////////////////////////////////////////////////////////////////
149 302
150 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 303 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
151 Direction direction, 304 Direction direction,
152 int radius, 305 int radius,
153 const float* kernel, 306 const float* kernel,
154 bool useBounds, 307 bool useBounds,
155 float bounds[2]) 308 float bounds[2])
156 : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) { 309 : Gr1DKernelEffect(texture,
310 direction,
311 radius,
312 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
313 : GrTextureParams::FilterMode::kBilerp_FilterMo de)
314 , fUseBounds(useBounds) {
157 this->initClassID<GrConvolutionEffect>(); 315 this->initClassID<GrConvolutionEffect>();
158 SkASSERT(radius <= kMaxKernelRadius); 316 SkASSERT(radius <= kMaxKernelRadius);
159 SkASSERT(kernel); 317 SkASSERT(kernel);
160 int width = this->width(); 318 int width = this->width();
161 for (int i = 0; i < width; i++) { 319 for (int i = 0; i < width; i++) {
162 fKernel[i] = kernel[i]; 320 fKernel[i] = kernel[i];
163 } 321 }
164 memcpy(fBounds, bounds, sizeof(fBounds)); 322 memcpy(fBounds, bounds, sizeof(fBounds));
165 } 323 }
166 324
167 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 325 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
168 Direction direction, 326 Direction direction,
169 int radius, 327 int radius,
170 float gaussianSigma, 328 float gaussianSigma,
171 bool useBounds, 329 bool useBounds,
172 float bounds[2]) 330 float bounds[2])
173 : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) { 331 : Gr1DKernelEffect(texture,
332 direction,
333 radius,
334 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
335 : GrTextureParams::FilterMode::kBilerp_FilterMo de)
336 , fUseBounds(useBounds) {
174 this->initClassID<GrConvolutionEffect>(); 337 this->initClassID<GrConvolutionEffect>();
175 SkASSERT(radius <= kMaxKernelRadius); 338 SkASSERT(radius <= kMaxKernelRadius);
176 int width = this->width(); 339 int width = this->width();
177 340
178 float sum = 0.0f; 341 float sum = 0.0f;
179 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); 342 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma);
180 for (int i = 0; i < width; ++i) { 343 for (int i = 0; i < width; ++i) {
181 float x = static_cast<float>(i - this->radius()); 344 float x = static_cast<float>(i - this->radius());
182 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian 345 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
183 // is dropped here, since we renormalize the kernel below. 346 // is dropped here, since we renormalize the kernel below.
(...skipping 10 matching lines...) Expand all
194 357
195 GrConvolutionEffect::~GrConvolutionEffect() { 358 GrConvolutionEffect::~GrConvolutionEffect() {
196 } 359 }
197 360
198 void GrConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps, 361 void GrConvolutionEffect::getGLProcessorKey(const GrGLSLCaps& caps,
199 GrProcessorKeyBuilder* b) const { 362 GrProcessorKeyBuilder* b) const {
200 GrGLConvolutionEffect::GenKey(*this, caps, b); 363 GrGLConvolutionEffect::GenKey(*this, caps, b);
201 } 364 }
202 365
203 GrGLFragmentProcessor* GrConvolutionEffect::createGLInstance() const { 366 GrGLFragmentProcessor* GrConvolutionEffect::createGLInstance() const {
204 return SkNEW_ARGS(GrGLConvolutionEffect, (*this)); 367 // We support a bilinear optimization which (when feasible) uses half the nu mber
368 // of samples to apply the kernel. This is not always applicable, as the
369 // bilinear sampling optimization does not support bounded sampling.
370 if (this->useBounds()) {
371 return SkNEW_ARGS(GrGLBoundedConvolutionEffect, (*this));
372 } else {
373 return SkNEW_ARGS(GrGLBilerpConvolutionEffect, (*this));
374 }
205 } 375 }
206 376
207 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 377 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
208 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>(); 378 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>();
209 return (this->radius() == s.radius() && 379 return (this->radius() == s.radius() &&
210 this->direction() == s.direction() && 380 this->direction() == s.direction() &&
211 this->useBounds() == s.useBounds() && 381 this->useBounds() == s.useBounds() &&
212 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) && 382 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
213 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); 383 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
214 } 384 }
(...skipping 20 matching lines...) Expand all
235 } 405 }
236 406
237 bool useBounds = random->nextBool(); 407 bool useBounds = random->nextBool();
238 return GrConvolutionEffect::Create(textures[texIdx], 408 return GrConvolutionEffect::Create(textures[texIdx],
239 dir, 409 dir,
240 radius, 410 radius,
241 kernel, 411 kernel,
242 useBounds, 412 useBounds,
243 bounds); 413 bounds);
244 } 414 }
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