OLD | NEW |
---|---|
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/GrGLFragmentProcessor.h" | 9 #include "gl/GrGLFragmentProcessor.h" |
10 #include "gl/GrGLTexture.h" | 10 #include "gl/GrGLTexture.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 /////////////////////////////////////////////////////////////////////////////// | 74 /////////////////////////////////////////////////////////////////////////////// |
75 | 75 |
76 /** | 76 /** |
77 * Applies a convolution effect which restricts samples to the provided bounds | 77 * Applies a convolution effect which restricts samples to the provided bounds |
78 * using shader logic. | 78 * using shader logic. |
79 */ | 79 */ |
80 class GrGLBoundedConvolutionEffect : public GrGLConvolutionEffect { | 80 class GrGLBoundedConvolutionEffect : public GrGLConvolutionEffect { |
81 public: | 81 public: |
82 GrGLBoundedConvolutionEffect(const GrProcessor& processor) : INHERITED(proce ssor) {} | 82 GrGLBoundedConvolutionEffect(const GrProcessor& processor) : INHERITED(proce ssor) {} |
83 | 83 |
84 virtual void emitCode(GrGLFPBuilder*, | 84 virtual void emitCode(EmitArgs&) override; |
85 const GrFragmentProcessor&, | |
86 const char* outputColor, | |
87 const char* inputColor, | |
88 const TransformedCoordsArray&, | |
89 const TextureSamplerArray&) override; | |
90 | 85 |
91 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de; | 86 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de; |
92 | 87 |
93 private: | 88 private: |
94 UniformHandle fKernelUni; | 89 UniformHandle fKernelUni; |
95 UniformHandle fImageIncrementUni; | 90 UniformHandle fImageIncrementUni; |
96 UniformHandle fBoundsUni; | 91 UniformHandle fBoundsUni; |
97 | 92 |
98 typedef GrGLConvolutionEffect INHERITED; | 93 typedef GrGLConvolutionEffect INHERITED; |
99 }; | 94 }; |
100 | 95 |
101 void GrGLBoundedConvolutionEffect::emitCode(GrGLFPBuilder* builder, | 96 void GrGLBoundedConvolutionEffect::emitCode(EmitArgs& args) { |
102 const GrFragmentProcessor& processor , | |
103 const char* outputColor, | |
104 const char* inputColor, | |
105 const TransformedCoordsArray& coords , | |
106 const TextureSamplerArray& samplers) { | |
107 fImageIncrementUni = | 97 fImageIncrementUni = |
108 builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrS LType, | 98 args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, |
109 kDefault_GrSLPrecision, "ImageIncrement"); | 99 kDefault_GrSLPrecision, "ImageIncrement"); |
110 | 100 |
111 fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, k Vec2f_GrSLType, | 101 fBoundsUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibil ity, kVec2f_GrSLType, |
joshualitt
2015/07/22 19:34:05
line wrap @100
| |
112 kDefault_GrSLPrecision, "Bounds"); | 102 kDefault_GrSLPrecision, "Bounds"); |
113 | 103 |
114 fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibili ty, kFloat_GrSLType, | 104 fKernelUni = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Vi sibility, kFloat_GrSLType, |
joshualitt
2015/07/22 19:34:05
line wrap @100
| |
115 kDefault_GrSLPrecision, "Kernel", this ->width()); | 105 kDefault_GrSLPrecision, "Kernel", this ->width()); |
116 | 106 |
117 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 107 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
118 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); | 108 SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0); |
119 | 109 |
120 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", outputColor); | 110 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", args.fOutputColor); |
121 | 111 |
122 int width = this->width(); | 112 int width = this->width(); |
123 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); | 113 const GrGLShaderVar& kernel = args.fBuilder->getUniformVariable(fKernelUni); |
124 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | 114 const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni); |
125 | 115 |
126 fsBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), t his->radius(), | 116 fsBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), t his->radius(), |
127 imgInc); | 117 imgInc); |
128 | 118 |
129 // Manually unroll loop because some drivers don't; yields 20-30% speedup. | 119 // Manually unroll loop because some drivers don't; yields 20-30% speedup. |
130 for (int i = 0; i < width; i++) { | 120 for (int i = 0; i < width; i++) { |
131 SkString index; | 121 SkString index; |
132 SkString kernelIndex; | 122 SkString kernelIndex; |
133 index.appendS32(i); | 123 index.appendS32(i); |
134 kernel.appendArrayAccess(index.c_str(), &kernelIndex); | 124 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 | 125 // 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 | 126 // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems |
137 // to have a bug that caused corruption. | 127 // to have a bug that caused corruption. |
138 const char* bounds = builder->getUniformCStr(fBoundsUni); | 128 const char* bounds = args.fBuilder->getUniformCStr(fBoundsUni); |
139 const char* component = this->direction() == Gr1DKernelEffect::kY_Direct ion ? "y" : "x"; | 129 const char* component = this->direction() == Gr1DKernelEffect::kY_Direct ion ? "y" : "x"; |
140 fsBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {", | 130 fsBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {", |
141 component, bounds, component, bounds); | 131 component, bounds, component, bounds); |
142 fsBuilder->codeAppendf("%s += ", outputColor); | 132 fsBuilder->codeAppendf("%s += ", args.fOutputColor); |
143 fsBuilder->appendTextureLookup(samplers[0], "coord"); | 133 fsBuilder->appendTextureLookup(args.fSamplers[0], "coord"); |
144 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); | 134 fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); |
145 fsBuilder->codeAppend("}"); | 135 fsBuilder->codeAppend("}"); |
146 fsBuilder->codeAppendf("coord += %s;\n", imgInc); | 136 fsBuilder->codeAppendf("coord += %s;\n", imgInc); |
147 } | 137 } |
148 | 138 |
149 SkString modulate; | 139 SkString modulate; |
150 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); | 140 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); |
151 fsBuilder->codeAppend(modulate.c_str()); | 141 fsBuilder->codeAppend(modulate.c_str()); |
152 } | 142 } |
153 | 143 |
154 void GrGLBoundedConvolutionEffect::setData(const GrGLProgramDataManager& pdman, | 144 void GrGLBoundedConvolutionEffect::setData(const GrGLProgramDataManager& pdman, |
155 const GrProcessor& processor) { | 145 const GrProcessor& processor) { |
156 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); | 146 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); |
157 | 147 |
158 // the code we generated was for a specific kernel radius | 148 // the code we generated was for a specific kernel radius |
159 SkASSERT(conv.radius() == this->radius()); | 149 SkASSERT(conv.radius() == this->radius()); |
160 | 150 |
(...skipping 17 matching lines...) Expand all Loading... | |
178 /////////////////////////////////////////////////////////////////////////////// | 168 /////////////////////////////////////////////////////////////////////////////// |
179 | 169 |
180 /** | 170 /** |
181 * Applies a convolution effect which applies the convolution using a linear | 171 * Applies a convolution effect which applies the convolution using a linear |
182 * interpolation optimization to use half as many samples. | 172 * interpolation optimization to use half as many samples. |
183 */ | 173 */ |
184 class GrGLLerpConvolutionEffect : public GrGLConvolutionEffect { | 174 class GrGLLerpConvolutionEffect : public GrGLConvolutionEffect { |
185 public: | 175 public: |
186 GrGLLerpConvolutionEffect(const GrProcessor& processor) : INHERITED(processo r) {} | 176 GrGLLerpConvolutionEffect(const GrProcessor& processor) : INHERITED(processo r) {} |
187 | 177 |
188 virtual void emitCode(GrGLFPBuilder*, | 178 virtual void emitCode(EmitArgs&) override; |
189 const GrFragmentProcessor&, | |
190 const char* outputColor, | |
191 const char* inputColor, | |
192 const TransformedCoordsArray&, | |
193 const TextureSamplerArray&) override; | |
194 | 179 |
195 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de; | 180 void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) overri de; |
196 | 181 |
197 private: | 182 private: |
198 int bilerpSampleCount() const; | 183 int bilerpSampleCount() const; |
199 | 184 |
200 // Bounded uniforms | 185 // Bounded uniforms |
201 UniformHandle fSampleWeightUni; | 186 UniformHandle fSampleWeightUni; |
202 UniformHandle fSampleOffsetUni; | 187 UniformHandle fSampleOffsetUni; |
203 | 188 |
204 typedef GrGLConvolutionEffect INHERITED; | 189 typedef GrGLConvolutionEffect INHERITED; |
205 }; | 190 }; |
206 | 191 |
207 void GrGLLerpConvolutionEffect::emitCode(GrGLFPBuilder* builder, | 192 void GrGLLerpConvolutionEffect::emitCode(EmitArgs& args) { |
208 const GrFragmentProcessor& processor, | |
209 const char* outputColor, | |
210 const char* inputColor, | |
211 const TransformedCoordsArray& coords, | |
212 const TextureSamplerArray& samplers) { | |
213 int sampleCount = bilerpSampleCount(); | 193 int sampleCount = bilerpSampleCount(); |
214 | 194 |
215 // We use 2 * sampleCount uniforms. The maximum allowed by PS2.0 is 32, so | 195 // 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 | 196 // ensure we don't exceed this. Note that it is currently impossible to |
217 // exceed this as bilerpSampleCount = (kernelWidth + 1) / 2, and kernelWidth | 197 // exceed this as bilerpSampleCount = (kernelWidth + 1) / 2, and kernelWidth |
218 // maxes out at 25, resulting in a max sampleCount of 26. | 198 // maxes out at 25, resulting in a max sampleCount of 26. |
219 SkASSERT(sampleCount < 16); | 199 SkASSERT(sampleCount < 16); |
220 | 200 |
221 fSampleOffsetUni = | 201 fSampleOffsetUni = |
222 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kVec2 f_GrSLType, | 202 args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, |
223 kDefault_GrSLPrecision, "SampleOffset", sampleC ount); | 203 kDefault_GrSLPrecision, "SampleOffset", sampleC ount); |
224 fSampleWeightUni = | 204 fSampleWeightUni = |
225 builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloa t_GrSLType, | 205 args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, |
226 kDefault_GrSLPrecision, "SampleWeight", sampleC ount); | 206 kDefault_GrSLPrecision, "SampleWeight", sampleC ount); |
227 | 207 |
228 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 208 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
229 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); | 209 SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0); |
230 | 210 |
231 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", outputColor); | 211 fsBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);\n", args.fOutputColor); |
232 | 212 |
233 const GrGLShaderVar& kernel = builder->getUniformVariable(fSampleWeightUni); | 213 const GrGLShaderVar& kernel = args.fBuilder->getUniformVariable(fSampleWeigh tUni); |
234 const GrGLShaderVar& imgInc = builder->getUniformVariable(fSampleOffsetUni); | 214 const GrGLShaderVar& imgInc = args.fBuilder->getUniformVariable(fSampleOffse tUni); |
235 | 215 |
236 fsBuilder->codeAppendf("vec2 coord; \n"); | 216 fsBuilder->codeAppendf("vec2 coord; \n"); |
237 | 217 |
238 // Manually unroll loop because some drivers don't; yields 20-30% speedup. | 218 // Manually unroll loop because some drivers don't; yields 20-30% speedup. |
239 for (int i = 0; i < sampleCount; i++) { | 219 for (int i = 0; i < sampleCount; i++) { |
240 SkString index; | 220 SkString index; |
241 SkString weightIndex; | 221 SkString weightIndex; |
242 SkString offsetIndex; | 222 SkString offsetIndex; |
243 index.appendS32(i); | 223 index.appendS32(i); |
244 kernel.appendArrayAccess(index.c_str(), &weightIndex); | 224 kernel.appendArrayAccess(index.c_str(), &weightIndex); |
245 imgInc.appendArrayAccess(index.c_str(), &offsetIndex); | 225 imgInc.appendArrayAccess(index.c_str(), &offsetIndex); |
246 fsBuilder->codeAppendf("coord = %s + %s;\n", coords2D.c_str(), offsetInd ex.c_str()); | 226 fsBuilder->codeAppendf("coord = %s + %s;\n", coords2D.c_str(), offsetInd ex.c_str()); |
247 fsBuilder->codeAppendf("%s += ", outputColor); | 227 fsBuilder->codeAppendf("%s += ", args.fOutputColor); |
248 fsBuilder->appendTextureLookup(samplers[0], "coord"); | 228 fsBuilder->appendTextureLookup(args.fSamplers[0], "coord"); |
249 fsBuilder->codeAppendf(" * %s;\n", weightIndex.c_str()); | 229 fsBuilder->codeAppendf(" * %s;\n", weightIndex.c_str()); |
250 } | 230 } |
251 | 231 |
252 SkString modulate; | 232 SkString modulate; |
253 GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); | 233 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); |
254 fsBuilder->codeAppend(modulate.c_str()); | 234 fsBuilder->codeAppend(modulate.c_str()); |
255 } | 235 } |
256 | 236 |
257 void GrGLLerpConvolutionEffect::setData(const GrGLProgramDataManager& pdman, | 237 void GrGLLerpConvolutionEffect::setData(const GrGLProgramDataManager& pdman, |
258 const GrProcessor& processor) { | 238 const GrProcessor& processor) { |
259 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); | 239 const GrConvolutionEffect& conv = processor.cast<GrConvolutionEffect>(); |
260 | 240 |
261 // the code we generated was for a specific kernel radius | 241 // the code we generated was for a specific kernel radius |
262 SkASSERT(conv.radius() == this->radius()); | 242 SkASSERT(conv.radius() == this->radius()); |
263 | 243 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 | 399 |
420 bool useBounds = d->fRandom->nextBool(); | 400 bool useBounds = d->fRandom->nextBool(); |
421 return GrConvolutionEffect::Create(d->fProcDataManager, | 401 return GrConvolutionEffect::Create(d->fProcDataManager, |
422 d->fTextures[texIdx], | 402 d->fTextures[texIdx], |
423 dir, | 403 dir, |
424 radius, | 404 radius, |
425 kernel, | 405 kernel, |
426 useBounds, | 406 useBounds, |
427 bounds); | 407 bounds); |
428 } | 408 } |
OLD | NEW |