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

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 4 years, 8 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 "glsl/GrGLSLFragmentProcessor.h" 9 #include "glsl/GrGLSLFragmentProcessor.h"
10 #include "glsl/GrGLSLFragmentShaderBuilder.h" 10 #include "glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "glsl/GrGLSLProgramDataManager.h" 11 #include "glsl/GrGLSLProgramDataManager.h"
12 #include "glsl/GrGLSLUniformHandler.h" 12 #include "glsl/GrGLSLUniformHandler.h"
13 13
14 // For brevity 14 // For brevity
15 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 15 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
16 16
17 /**
18 * Base class with shared functionality for GrGLBoundedConvolutionEffect and
19 * GrGLLerpConvolutionEffect.
20 */
17 class GrGLConvolutionEffect : public GrGLSLFragmentProcessor { 21 class GrGLConvolutionEffect : public GrGLSLFragmentProcessor {
18 public: 22 public:
19 void emitCode(EmitArgs&) override;
20
21 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*); 23 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor KeyBuilder*);
22 24
23 protected: 25 protected:
26 void getImageIncrement(const GrConvolutionEffect&, float (*)[2]) const;
27
28 private:
29 typedef GrGLSLFragmentProcessor INHERITED;
30 };
31
32 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor,
33 const GrGLSLCaps&,
34 GrProcessorKeyBuilder* b) {
35 const GrConvolutionEffect& ce = processor.cast<GrConvolutionEffect>();
36 uint32_t key = ce.radius();
37 key <<= 2;
38 if (ce.useBounds()) {
39 key |= 0x2;
40 key |= GrConvolutionEffect::kY_Direction == ce.direction() ? 0x1 : 0x0;
41 }
42 b->add32(key);
43 }
44
45 void GrGLConvolutionEffect::getImageIncrement(const GrConvolutionEffect& ce,
46 float (*imageIncrement)[2]) const {
47 GrTexture& texture = *ce.texture(0);
48 (*imageIncrement)[0] = (*imageIncrement)[1] = 0;
49 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
50 switch (ce.direction()) {
51 case Gr1DKernelEffect::kX_Direction:
52 (*imageIncrement)[0] = 1.0f / texture.width();
53 break;
54 case Gr1DKernelEffect::kY_Direction:
55 (*imageIncrement)[1] = ySign / texture.height();
56 break;
57 default:
58 SkFAIL("Unknown filter direction.");
59 }
60 }
61
62 ///////////////////////////////////////////////////////////////////////////////
63
64 /**
65 * Applies a ceolution effect which restricts samples to the provided bounds
66 * using shader logic.
67 */
68 class GrGLBoundedConvolutionEffect : public GrGLConvolutionEffect {
69 public:
70 virtual void emitCode(EmitArgs&) override;
71
24 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor&) ov erride; 72 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor&) ov erride;
25 73
26 private: 74 private:
27 UniformHandle fKernelUni; 75 UniformHandle fKernelUni;
28 UniformHandle fImageIncrementUni; 76 UniformHandle fImageIncrementUni;
29 UniformHandle fBoundsUni; 77 UniformHandle fBoundsUni;
30 78
31 typedef GrGLSLFragmentProcessor INHERITED; 79 typedef GrGLConvolutionEffect INHERITED;
32 }; 80 };
33 81
34 void GrGLConvolutionEffect::emitCode(EmitArgs& args) { 82 void GrGLBoundedConvolutionEffect::emitCode(EmitArgs& args) {
35 const GrConvolutionEffect& ce = args.fFp.cast<GrConvolutionEffect>(); 83 const GrConvolutionEffect& ce = args.fFp.cast<GrConvolutionEffect>();
36 84
37 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 85 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
38 fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 86 fImageIncrementUni =
39 kVec2f_GrSLType, kDefault_Gr SLPrecision, 87 uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
40 "ImageIncrement"); 88 kDefault_GrSLPrecision, "ImageIncrement");
41 if (ce.useBounds()) { 89 fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLT ype,
42 fBoundsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 90 kDefault_GrSLPrecision, "Bounds");
43 kVec2f_GrSLType, kDefault_GrSLPr ecision,
44 "Bounds");
45 }
46 91
47 int width = Gr1DKernelEffect::WidthFromRadius(ce.radius()); 92 int width = Gr1DKernelEffect::WidthFromRadius(ce.radius());
93 fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kFloat_ GrSLType,
94 kDefault_GrSLPrecision, "Kernel", widt h);
48 95
49 int arrayCount = (width + 3) / 4; 96 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
50 SkASSERT(4 * arrayCount >= width);
51
52 fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
53 kVec4f_GrSLType, kDefault_GrSLP recision,
54 "Kernel", arrayCount);
55
56 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
57 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); 97 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
58 98
59 fragBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);", args.fOutputColor); 99 fragBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", args.fOutputColor);
60 100
61 const GrGLSLShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUn i); 101 const GrGLSLShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUn i);
62 const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); 102 const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
63 103
64 fragBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;", coords2D.c_str(), c e.radius(), imgInc); 104 fragBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), ce.radius(),
105 imgInc);
65 106
66 // Manually unroll loop because some drivers don't; yields 20-30% speedup. 107 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
67 const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" };
68 for (int i = 0; i < width; i++) { 108 for (int i = 0; i < width; i++) {
69 SkString index; 109 SkString index;
70 SkString kernelIndex; 110 SkString kernelIndex;
71 index.appendS32(i/4); 111 index.appendS32(i);
72 kernel.appendArrayAccess(index.c_str(), &kernelIndex); 112 kernel.appendArrayAccess(index.c_str(), &kernelIndex);
73 kernelIndex.append(kVecSuffix[i & 0x3]); 113 // We used to compute a bool indicating whether we're in bounds or not, cast it to a
74 114 // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems
75 if (ce.useBounds()) { 115 // to have a bug that caused corruption.
76 // We used to compute a bool indicating whether we're in bounds or n ot, cast it to a 116 const char* bounds = uniformHandler->getUniformCStr(fBoundsUni);
77 // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems 117 const char* component = ce.direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
78 // to have a bug that caused corruption. 118 fragBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {",
79 const char* bounds = uniformHandler->getUniformCStr(fBoundsUni); 119 component, bounds, component, bounds);
80 const char* component = ce.direction() == Gr1DKernelEffect::kY_Direc tion ? "y" : "x"; 120 fragBuilder->codeAppendf("%s += ", args.fOutputColor);
81 fragBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {",
82 component, bounds, component, bounds);
83 }
84 fragBuilder->codeAppendf("\t\t%s += ", args.fOutputColor);
85 fragBuilder->appendTextureLookup(args.fSamplers[0], "coord"); 121 fragBuilder->appendTextureLookup(args.fSamplers[0], "coord");
86 fragBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); 122 fragBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
87 if (ce.useBounds()) { 123 fragBuilder->codeAppend("}");
88 fragBuilder->codeAppend("}"); 124 fragBuilder->codeAppendf("coord += %s;\n", imgInc);
89 }
90 fragBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
91 } 125 }
92 126
93 SkString modulate; 127 SkString modulate;
94 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); 128 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
95 fragBuilder->codeAppend(modulate.c_str()); 129 fragBuilder->codeAppend(modulate.c_str());
96 } 130 }
97 131
98 void GrGLConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdman, 132 void GrGLBoundedConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdm an,
99 const GrProcessor& processor) { 133 const GrProcessor& processor) {
100 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); 134 const GrConvolutionEffect& ce = processor.cast<GrConvolutionEffect>();
101 GrTexture& texture = *conv.texture(0);
102 135
103 float imageIncrement[2] = { 0 }; 136 // the code we generated was for a specific bounding mode.
104 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; 137 SkASSERT(ce.useBounds());
105 switch (conv.direction()) { 138
106 case Gr1DKernelEffect::kX_Direction: 139 GrTexture& texture = *ce.texture(0);
107 imageIncrement[0] = 1.0f / texture.width(); 140 float imageIncrement[2];
108 break; 141 getImageIncrement(ce, &imageIncrement);
109 case Gr1DKernelEffect::kY_Direction: 142 pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
110 imageIncrement[1] = ySign / texture.height(); 143 const float* bounds = ce.bounds();
111 break; 144 if (Gr1DKernelEffect::kY_Direction == ce.direction() &&
112 default: 145 texture.origin() != kTopLeft_GrSurfaceOrigin) {
113 SkFAIL("Unknown filter direction."); 146 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
147 } else {
148 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
114 } 149 }
115 pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
116 if (conv.useBounds()) {
117 const float* bounds = conv.bounds();
118 if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
119 texture.origin() != kTopLeft_GrSurfaceOrigin) {
120 pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
121 } else {
122 pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
123 }
124 }
125 int width = Gr1DKernelEffect::WidthFromRadius(conv.radius());
126 150
127 int arrayCount = (width + 3) / 4; 151 int width = Gr1DKernelEffect::WidthFromRadius(ce.radius());
128 SkASSERT(4 * arrayCount >= width); 152 pdman.set1fv(fKernelUni, width, ce.kernel());
129 pdman.set4fv(fKernelUni, arrayCount, conv.kernel());
130 }
131
132 void GrGLConvolutionEffect::GenKey(const GrProcessor& processor, const GrGLSLCap s&,
133 GrProcessorKeyBuilder* b) {
134 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>();
135 uint32_t key = conv.radius();
136 key <<= 2;
137 if (conv.useBounds()) {
138 key |= 0x2;
139 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ;
140 }
141 b->add32(key);
142 } 153 }
143 154
144 /////////////////////////////////////////////////////////////////////////////// 155 ///////////////////////////////////////////////////////////////////////////////
156
157 /**
158 * Applies a ceolution effect which applies the ceolution using a linear
159 * interpolation optimization to use half as many samples.
160 */
161 class GrGLLerpConvolutionEffect : public GrGLConvolutionEffect {
162 public:
163 virtual void emitCode(EmitArgs&) override;
164
165 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor&) ov erride;
166
167 private:
168 int bilerpSampleCount(int width) const;
169
170 // Bounded uniforms
171 UniformHandle fSampleWeightUni;
172 UniformHandle fSampleOffsetUni;
173
174 typedef GrGLConvolutionEffect INHERITED;
175 };
176
177 void GrGLLerpConvolutionEffect::emitCode(EmitArgs& args) {
178 const GrConvolutionEffect& ce = args.fFp.cast<GrConvolutionEffect>();
179
180 int width = Gr1DKernelEffect::WidthFromRadius(ce.radius());
181 int sampleCount = bilerpSampleCount(width);
182 // We use 2 * sampleCount uniforms. The maximum allowed by PS2.0 is 32, so
183 // ensure we don't exceed this. Note that it is currently impossible to
184 // exceed this as bilerpSampleCount = (kernelWidth + 1) / 2, and kernelWidth
185 // maxes out at 25, resulting in a max sampleCount of 26.
186 SkASSERT(sampleCount < 16);
187
188
189 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
190 fSampleOffsetUni =
191 uniformHandler->addUniformArray(kFragment_GrShaderFlag, kVec2f_GrSLType,
192 kDefault_GrSLPrecision, "SampleOffset", sampleC ount);
193 fSampleWeightUni =
194 uniformHandler->addUniformArray(kFragment_GrShaderFlag, kFloat_GrSLType,
195 kDefault_GrSLPrecision, "SampleWeight", sampleC ount);
196
197 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
198 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
199
200 fragBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", args.fOutputColor);
201
202 const GrGLSLShaderVar& kernel = uniformHandler->getUniformVariable(fSampleWe ightUni);
203 const GrGLSLShaderVar& imgInc = uniformHandler->getUniformVariable(fSampleOf fsetUni);
204
205 fragBuilder->codeAppendf("vec2 coord; \n");
206
207 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
208 for (int i = 0; i < sampleCount; i++) {
209 SkString index;
210 SkString weightIndex;
211 SkString offsetIndex;
212 index.appendS32(i);
213 kernel.appendArrayAccess(index.c_str(), &weightIndex);
214 imgInc.appendArrayAccess(index.c_str(), &offsetIndex);
215 fragBuilder->codeAppendf("coord = %s + %s;\n", coords2D.c_str(), offsetI ndex.c_str());
216 fragBuilder->codeAppendf("%s += ", args.fOutputColor);
217 fragBuilder->appendTextureLookup(args.fSamplers[0], "coord");
218 fragBuilder->codeAppendf(" * %s;\n", weightIndex.c_str());
219 }
220
221 SkString modulate;
222 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
223 fragBuilder->codeAppend(modulate.c_str());
224 }
225
226 void GrGLLerpConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdman,
227 const GrProcessor& processor) {
228 const GrConvolutionEffect& ce = processor.cast<GrConvolutionEffect>();
229
230 // the code we generated was for a specific kernel radius
231 SkASSERT(ce.radius() == this->radius());
232
233 // the code we generated was for a specific bounding mode.
234 SkASSERT(!ce.useBounds());
235
236 int width = Gr1DKernelEffect::WidthFromRadius(ce.radius());
237 int sampleCount = bilerpSampleCount(width);
238 SkAutoTArray<float> imageIncrements(sampleCount * 2); // X and Y floats per sample.
239 SkAutoTArray<float> kernel(sampleCount);
240
241 float baseImageIncrement[2];
242 getImageIncrement(ce, &baseImageIncrement);
243
244 for (int i = 0; i < sampleCount; i++) {
245 int sampleIndex1 = i * 2;
246 int sampleIndex2 = sampleIndex1 + 1;
247
248 // If we have an odd number of samples in our filter, the last sample wo n't use
249 // the linear interpolation optimization (it will be pixel aligned).
250 if (sampleIndex2 >= width) {
251 sampleIndex2 = sampleIndex1;
252 }
253
254 float kernelWeight1 = ce.kernel()[sampleIndex1];
255 float kernelWeight2 = ce.kernel()[sampleIndex2];
256
257 float totalKernelWeight =
258 (sampleIndex1 == sampleIndex2) ? kernelWeight1 : (kernelWeight1 + ke rnelWeight2);
259
260 float sampleRatio =
261 (sampleIndex1 == sampleIndex2) ? 0 : kernelWeight2 / (kernelWeight1 + kernelWeight2);
262
263 imageIncrements[i * 2] = (-ce.radius() + i * 2 + sampleRatio) * baseImag eIncrement[0];
264 imageIncrements[i * 2 + 1] =
265 (-ce.radius() + i * 2 + sampleRatio) * baseImageIncrement[1];
266
267 kernel[i] = totalKernelWeight;
268 }
269 pdman.set2fv(fSampleOffsetUni, sampleCount, imageIncrements.get());
270 pdman.set1fv(fSampleWeightUni, sampleCount, kernel.get());
271 }
272
273 int GrGLLerpConvolutionEffect::bilerpSampleCount(int width) const {
274 // We use a linear interpolation optimization to only sample once for each
275 // two pixel aligned samples in the kernel. If we have an odd number of
276 // samples, we will have to skip this optimization for the last sample.
277 // Because of this we always round up our sample count (by adding 1 before
278 // dividing).
279 return (width + 1) / 2;
280 }
281
282 ///////////////////////////////////////////////////////////////////////////////
145 283
146 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 284 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
147 Direction direction, 285 Direction direction,
148 int radius, 286 int radius,
149 const float* kernel, 287 const float* kernel,
150 bool useBounds, 288 bool useBounds,
151 float bounds[2]) 289 float bounds[2])
152 : INHERITED(texture, direction, radius), fUseBounds(useBounds) { 290 : INHERITED(texture,
291 direction,
292 radius,
293 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
294 : GrTextureParams::FilterMode::kBilerp_FilterMode)
295 , fUseBounds(useBounds) {
153 this->initClassID<GrConvolutionEffect>(); 296 this->initClassID<GrConvolutionEffect>();
154 SkASSERT(radius <= kMaxKernelRadius); 297 SkASSERT(radius <= kMaxKernelRadius);
155 SkASSERT(kernel); 298 SkASSERT(kernel);
156 int width = this->width(); 299 int width = this->width();
157 for (int i = 0; i < width; i++) { 300 for (int i = 0; i < width; i++) {
158 fKernel[i] = kernel[i]; 301 fKernel[i] = kernel[i];
159 } 302 }
160 memcpy(fBounds, bounds, sizeof(fBounds)); 303 memcpy(fBounds, bounds, sizeof(fBounds));
161 } 304 }
162 305
163 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 306 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
164 Direction direction, 307 Direction direction,
165 int radius, 308 int radius,
166 float gaussianSigma, 309 float gaussianSigma,
167 bool useBounds, 310 bool useBounds,
168 float bounds[2]) 311 float bounds[2])
169 : INHERITED(texture, direction, radius), fUseBounds(useBounds) { 312 : INHERITED(texture,
313 direction,
314 radius,
315 useBounds ? GrTextureParams::FilterMode::kNone_FilterMode
316 : GrTextureParams::FilterMode::kBilerp_FilterMode)
317 , fUseBounds(useBounds) {
170 this->initClassID<GrConvolutionEffect>(); 318 this->initClassID<GrConvolutionEffect>();
171 SkASSERT(radius <= kMaxKernelRadius); 319 SkASSERT(radius <= kMaxKernelRadius);
172 int width = this->width(); 320 int width = this->width();
173 321
174 float sum = 0.0f; 322 float sum = 0.0f;
175 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); 323 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma);
176 for (int i = 0; i < width; ++i) { 324 for (int i = 0; i < width; ++i) {
177 float x = static_cast<float>(i - this->radius()); 325 float x = static_cast<float>(i - this->radius());
178 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian 326 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
179 // is dropped here, since we renormalize the kernel below. 327 // is dropped here, since we renormalize the kernel below.
180 fKernel[i] = sk_float_exp(- x * x * denom); 328 fKernel[i] = sk_float_exp(- x * x * denom);
181 sum += fKernel[i]; 329 sum += fKernel[i];
182 } 330 }
183 // Normalize the kernel 331 // Normalize the kernel
184 float scale = 1.0f / sum; 332 float scale = 1.0f / sum;
185 for (int i = 0; i < width; ++i) { 333 for (int i = 0; i < width; ++i) {
186 fKernel[i] *= scale; 334 fKernel[i] *= scale;
187 } 335 }
188 memcpy(fBounds, bounds, sizeof(fBounds)); 336 memcpy(fBounds, bounds, sizeof(fBounds));
189 } 337 }
190 338
191 GrConvolutionEffect::~GrConvolutionEffect() { 339 GrConvolutionEffect::~GrConvolutionEffect() {
192 } 340 }
193 341
194 void GrConvolutionEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 342 void GrConvolutionEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
195 GrProcessorKeyBuilder* b) const { 343 GrProcessorKeyBuilder* b) const {
196 GrGLConvolutionEffect::GenKey(*this, caps, b); 344 GrGLConvolutionEffect::GenKey(*this, caps, b);
197 } 345 }
198 346
199 GrGLSLFragmentProcessor* GrConvolutionEffect::onCreateGLSLInstance() const { 347 GrGLSLFragmentProcessor* GrConvolutionEffect::onCreateGLSLInstance() const {
200 return new GrGLConvolutionEffect; 348 // We support a linear interpolation optimization which (when feasible) uses
349 // half the number of samples to apply the kernel. This is not always
350 // applicable, as the linear interpolation optimization does not support
351 // bounded sampling.
352 if (this->useBounds()) {
353 return new GrGLBoundedConvolutionEffect;
354 } else {
355 return new GrGLLerpConvolutionEffect;
356 }
201 } 357 }
202 358
203 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 359 bool GrConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
204 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>(); 360 const GrConvolutionEffect& s = sBase.cast<GrConvolutionEffect>();
205 return (this->radius() == s.radius() && 361 return (this->radius() == s.radius() &&
206 this->direction() == s.direction() && 362 this->direction() == s.direction() &&
207 this->useBounds() == s.useBounds() && 363 this->useBounds() == s.useBounds() &&
208 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) && 364 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
209 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); 365 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
210 } 366 }
(...skipping 17 matching lines...) Expand all
228 } 384 }
229 385
230 bool useBounds = d->fRandom->nextBool(); 386 bool useBounds = d->fRandom->nextBool();
231 return GrConvolutionEffect::Create(d->fTextures[texIdx], 387 return GrConvolutionEffect::Create(d->fTextures[texIdx],
232 dir, 388 dir,
233 radius, 389 radius,
234 kernel, 390 kernel,
235 useBounds, 391 useBounds,
236 bounds); 392 bounds);
237 } 393 }
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