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

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

Issue 20789003: Small optimization for convolution shader: only apply the bounds check in (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Make direction() context Created 7 years, 4 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
« no previous file with comments | « src/gpu/effects/GrConvolutionEffect.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/GrGLEffect.h" 9 #include "gl/GrGLEffect.h"
10 #include "gl/GrGLEffectMatrix.h" 10 #include "gl/GrGLEffectMatrix.h"
(...skipping 15 matching lines...) Expand all
26 const char* outputColor, 26 const char* outputColor,
27 const char* inputColor, 27 const char* inputColor,
28 const TextureSamplerArray&) SK_OVERRIDE; 28 const TextureSamplerArray&) SK_OVERRIDE;
29 29
30 virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK _OVERRIDE; 30 virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK _OVERRIDE;
31 31
32 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 32 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
33 33
34 private: 34 private:
35 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); } 35 int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
36 bool useCropRect() const { return fUseCropRect; } 36 bool useBounds() const { return fUseBounds; }
37 Gr1DKernelEffect::Direction direction() const { return fDirection; }
37 38
38 int fRadius; 39 int fRadius;
39 bool fUseCropRect; 40 bool fUseBounds;
41 Gr1DKernelEffect::Direction fDirection;
40 UniformHandle fKernelUni; 42 UniformHandle fKernelUni;
41 UniformHandle fImageIncrementUni; 43 UniformHandle fImageIncrementUni;
42 UniformHandle fCropRectUni; 44 UniformHandle fBoundsUni;
43 GrGLEffectMatrix fEffectMatrix; 45 GrGLEffectMatrix fEffectMatrix;
44 46
45 typedef GrGLEffect INHERITED; 47 typedef GrGLEffect INHERITED;
46 }; 48 };
47 49
48 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto ry, 50 GrGLConvolutionEffect::GrGLConvolutionEffect(const GrBackendEffectFactory& facto ry,
49 const GrDrawEffect& drawEffect) 51 const GrDrawEffect& drawEffect)
50 : INHERITED(factory) 52 : INHERITED(factory)
51 , fKernelUni(kInvalidUniformHandle) 53 , fKernelUni(kInvalidUniformHandle)
52 , fImageIncrementUni(kInvalidUniformHandle) 54 , fImageIncrementUni(kInvalidUniformHandle)
53 , fCropRectUni(kInvalidUniformHandle) 55 , fBoundsUni(kInvalidUniformHandle)
54 , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) { 56 , fEffectMatrix(drawEffect.castEffect<GrConvolutionEffect>().coordsType()) {
55 const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>(); 57 const GrConvolutionEffect& c = drawEffect.castEffect<GrConvolutionEffect>();
56 fRadius = c.radius(); 58 fRadius = c.radius();
57 fUseCropRect = c.useCropRect(); 59 fUseBounds = c.useBounds();
60 fDirection = c.direction();
58 } 61 }
59 62
60 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder, 63 void GrGLConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
61 const GrDrawEffect&, 64 const GrDrawEffect&,
62 EffectKey key, 65 EffectKey key,
63 const char* outputColor, 66 const char* outputColor,
64 const char* inputColor, 67 const char* inputColor,
65 const TextureSamplerArray& samplers) { 68 const TextureSamplerArray& samplers) {
66 const char* coords; 69 const char* coords;
67 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); 70 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
68 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Shader Type, 71 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Shader Type,
69 kVec2f_GrSLType, "ImageIncrement"); 72 kVec2f_GrSLType, "ImageIncrement");
70 if (this->useCropRect()) { 73 if (this->useBounds()) {
71 fCropRectUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderTy pe, 74 fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType ,
72 kVec4f_GrSLType, "CropRect"); 75 kVec2f_GrSLType, "Bounds");
73 } 76 }
74 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderTyp e, 77 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_ShaderTyp e,
75 kFloat_GrSLType, "Kernel", this->width ()); 78 kFloat_GrSLType, "Kernel", this->width ());
76 79
77 builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); 80 builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
78 81
79 int width = this->width(); 82 int width = this->width();
80 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); 83 const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
81 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 84 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
82 85
83 builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius , imgInc); 86 builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius , imgInc);
84 87
85 // Manually unroll loop because some drivers don't; yields 20-30% speedup. 88 // Manually unroll loop because some drivers don't; yields 20-30% speedup.
86 for (int i = 0; i < width; i++) { 89 for (int i = 0; i < width; i++) {
87 SkString index; 90 SkString index;
88 SkString kernelIndex; 91 SkString kernelIndex;
89 index.appendS32(i); 92 index.appendS32(i);
90 kernel.appendArrayAccess(index.c_str(), &kernelIndex); 93 kernel.appendArrayAccess(index.c_str(), &kernelIndex);
91 builder->fsCodeAppendf("\t\t%s += ", outputColor); 94 builder->fsCodeAppendf("\t\t%s += ", outputColor);
92 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, sa mplers[0], "coord"); 95 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, sa mplers[0], "coord");
93 if (this->useCropRect()) { 96 if (this->useBounds()) {
94 const char* cropRect = builder->getUniformCStr(fCropRectUni); 97 const char* bounds = builder->getUniformCStr(fBoundsUni);
95 builder->fsCodeAppendf(" * float(coord.x >= %s.x && coord.x <= %s.y && coord.y >= %s.z && coord.y <= %s.w)", 98 const char* component = this->direction() == Gr1DKernelEffect::kY_Di rection ? "y" : "x";
96 cropRect, cropRect, cropRect, cropRect); 99 builder->fsCodeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s. y)",
100 component, bounds, component, bounds);
97 } 101 }
98 builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str()); 102 builder->fsCodeAppendf(" * %s;\n", kernelIndex.c_str());
99 builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc); 103 builder->fsCodeAppendf("\t\tcoord += %s;\n", imgInc);
100 } 104 }
101 105
102 SkString modulate; 106 SkString modulate;
103 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 107 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
104 builder->fsCodeAppend(modulate.c_str()); 108 builder->fsCodeAppend(modulate.c_str());
105 } 109 }
106 110
107 void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman, 111 void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
108 const GrDrawEffect& drawEffect) { 112 const GrDrawEffect& drawEffect) {
109 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect> (); 113 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect> ();
110 GrTexture& texture = *conv.texture(0); 114 GrTexture& texture = *conv.texture(0);
111 // the code we generated was for a specific kernel radius 115 // the code we generated was for a specific kernel radius
112 GrAssert(conv.radius() == fRadius); 116 GrAssert(conv.radius() == fRadius);
113 float imageIncrement[2] = { 0 }; 117 float imageIncrement[2] = { 0 };
114 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; 118 float ySign = texture.origin() != kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f;
115 switch (conv.direction()) { 119 switch (conv.direction()) {
116 case Gr1DKernelEffect::kX_Direction: 120 case Gr1DKernelEffect::kX_Direction:
117 imageIncrement[0] = 1.0f / texture.width(); 121 imageIncrement[0] = 1.0f / texture.width();
118 break; 122 break;
119 case Gr1DKernelEffect::kY_Direction: 123 case Gr1DKernelEffect::kY_Direction:
120 imageIncrement[1] = ySign / texture.height(); 124 imageIncrement[1] = ySign / texture.height();
121 break; 125 break;
122 default: 126 default:
123 GrCrash("Unknown filter direction."); 127 GrCrash("Unknown filter direction.");
124 } 128 }
125 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); 129 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
126 if (conv.useCropRect()) { 130 if (conv.useBounds()) {
127 float c[4]; 131 const float* bounds = conv.bounds();
128 memcpy(c, conv.cropRect(), sizeof(c)); 132 if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
129 if (texture.origin() != kTopLeft_GrSurfaceOrigin) { 133 texture.origin() != kTopLeft_GrSurfaceOrigin) {
130 float tmp = 1.0f - c[2]; 134 uman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
131 c[2] = 1.0f - c[3]; 135 } else {
132 c[3] = tmp; 136 uman.set2f(fBoundsUni, bounds[0], bounds[1]);
133 } 137 }
134 uman.set4fv(fCropRectUni, 0, 1, c);
135 } 138 }
136 uman.set1fv(fKernelUni, 0, this->width(), conv.kernel()); 139 uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
137 fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0)); 140 fEffectMatrix.setData(uman, conv.getMatrix(), drawEffect, conv.texture(0));
138 } 141 }
139 142
140 GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffe ct, 143 GrGLEffect::EffectKey GrGLConvolutionEffect::GenKey(const GrDrawEffect& drawEffe ct,
141 const GrGLCaps&) { 144 const GrGLCaps&) {
142 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect> (); 145 const GrConvolutionEffect& conv = drawEffect.castEffect<GrConvolutionEffect> ();
143 EffectKey key = conv.radius() << 1; 146 EffectKey key = conv.radius();
144 key |= conv.useCropRect() ? 0x1 : 0x0; 147 key <<= 2;
148 if (conv.useBounds()) {
149 key |= 0x2;
150 key |= GrConvolutionEffect::kY_Direction == conv.direction() ? 0x1 : 0x0 ;
151 }
145 key <<= GrGLEffectMatrix::kKeyBits; 152 key <<= GrGLEffectMatrix::kKeyBits;
146 EffectKey matrixKey = GrGLEffectMatrix::GenKey(conv.getMatrix(), 153 EffectKey matrixKey = GrGLEffectMatrix::GenKey(conv.getMatrix(),
147 drawEffect, 154 drawEffect,
148 conv.coordsType(), 155 conv.coordsType(),
149 conv.texture(0)); 156 conv.texture(0));
150 return key | matrixKey; 157 return key | matrixKey;
151 } 158 }
152 159
153 /////////////////////////////////////////////////////////////////////////////// 160 ///////////////////////////////////////////////////////////////////////////////
154 161
155 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 162 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
156 Direction direction, 163 Direction direction,
157 int radius, 164 int radius,
158 const float* kernel, 165 const float* kernel,
159 bool useCropRect, 166 bool useBounds,
160 float cropRect[4]) 167 float bounds[2])
161 : Gr1DKernelEffect(texture, direction, radius), fUseCropRect(useCropRect) { 168 : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) {
162 GrAssert(radius <= kMaxKernelRadius); 169 GrAssert(radius <= kMaxKernelRadius);
163 GrAssert(NULL != kernel); 170 GrAssert(NULL != kernel);
164 int width = this->width(); 171 int width = this->width();
165 for (int i = 0; i < width; i++) { 172 for (int i = 0; i < width; i++) {
166 fKernel[i] = kernel[i]; 173 fKernel[i] = kernel[i];
167 } 174 }
168 memcpy(fCropRect, cropRect, sizeof(fCropRect)); 175 memcpy(fBounds, bounds, sizeof(fBounds));
169 } 176 }
170 177
171 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, 178 GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture,
172 Direction direction, 179 Direction direction,
173 int radius, 180 int radius,
174 float gaussianSigma, 181 float gaussianSigma,
175 bool useCropRect, 182 bool useBounds,
176 float cropRect[4]) 183 float bounds[2])
177 : Gr1DKernelEffect(texture, direction, radius), fUseCropRect(useCropRect) { 184 : Gr1DKernelEffect(texture, direction, radius), fUseBounds(useBounds) {
178 GrAssert(radius <= kMaxKernelRadius); 185 GrAssert(radius <= kMaxKernelRadius);
179 int width = this->width(); 186 int width = this->width();
180 187
181 float sum = 0.0f; 188 float sum = 0.0f;
182 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); 189 float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma);
183 for (int i = 0; i < width; ++i) { 190 for (int i = 0; i < width; ++i) {
184 float x = static_cast<float>(i - this->radius()); 191 float x = static_cast<float>(i - this->radius());
185 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian 192 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
186 // is dropped here, since we renormalize the kernel below. 193 // is dropped here, since we renormalize the kernel below.
187 fKernel[i] = sk_float_exp(- x * x * denom); 194 fKernel[i] = sk_float_exp(- x * x * denom);
188 sum += fKernel[i]; 195 sum += fKernel[i];
189 } 196 }
190 // Normalize the kernel 197 // Normalize the kernel
191 float scale = 1.0f / sum; 198 float scale = 1.0f / sum;
192 for (int i = 0; i < width; ++i) { 199 for (int i = 0; i < width; ++i) {
193 fKernel[i] *= scale; 200 fKernel[i] *= scale;
194 } 201 }
195 memcpy(fCropRect, cropRect, sizeof(fCropRect)); 202 memcpy(fBounds, bounds, sizeof(fBounds));
196 } 203 }
197 204
198 GrConvolutionEffect::~GrConvolutionEffect() { 205 GrConvolutionEffect::~GrConvolutionEffect() {
199 } 206 }
200 207
201 const GrBackendEffectFactory& GrConvolutionEffect::getFactory() const { 208 const GrBackendEffectFactory& GrConvolutionEffect::getFactory() const {
202 return GrTBackendEffectFactory<GrConvolutionEffect>::getInstance(); 209 return GrTBackendEffectFactory<GrConvolutionEffect>::getInstance();
203 } 210 }
204 211
205 bool GrConvolutionEffect::onIsEqual(const GrEffect& sBase) const { 212 bool GrConvolutionEffect::onIsEqual(const GrEffect& sBase) const {
206 const GrConvolutionEffect& s = CastEffect<GrConvolutionEffect>(sBase); 213 const GrConvolutionEffect& s = CastEffect<GrConvolutionEffect>(sBase);
207 return (this->texture(0) == s.texture(0) && 214 return (this->texture(0) == s.texture(0) &&
208 this->radius() == s.radius() && 215 this->radius() == s.radius() &&
209 this->direction() == s.direction() && 216 this->direction() == s.direction() &&
210 0 == memcmp(fCropRect, s.fCropRect, sizeof(fCropRect)) && 217 this->useBounds() == s.useBounds() &&
218 0 == memcmp(fBounds, s.fBounds, sizeof(fBounds)) &&
211 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); 219 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
212 } 220 }
213 221
214 /////////////////////////////////////////////////////////////////////////////// 222 ///////////////////////////////////////////////////////////////////////////////
215 223
216 GR_DEFINE_EFFECT_TEST(GrConvolutionEffect); 224 GR_DEFINE_EFFECT_TEST(GrConvolutionEffect);
217 225
218 GrEffectRef* GrConvolutionEffect::TestCreate(SkMWCRandom* random, 226 GrEffectRef* GrConvolutionEffect::TestCreate(SkMWCRandom* random,
219 GrContext*, 227 GrContext*,
220 const GrDrawTargetCaps&, 228 const GrDrawTargetCaps&,
221 GrTexture* textures[]) { 229 GrTexture* textures[]) {
222 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 230 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
223 GrEffectUnitTest::kAlphaTextureIdx; 231 GrEffectUnitTest::kAlphaTextureIdx;
224 Direction dir = random->nextBool() ? kX_Direction : kY_Direction; 232 Direction dir = random->nextBool() ? kX_Direction : kY_Direction;
225 int radius = random->nextRangeU(1, kMaxKernelRadius); 233 int radius = random->nextRangeU(1, kMaxKernelRadius);
226 float kernel[kMaxKernelRadius]; 234 float kernel[kMaxKernelRadius];
227 float cropRect[4];
228 for (int i = 0; i < kMaxKernelRadius; ++i) { 235 for (int i = 0; i < kMaxKernelRadius; ++i) {
229 kernel[i] = random->nextSScalar1(); 236 kernel[i] = random->nextSScalar1();
230 } 237 }
231 for (int i = 0; i < 4; ++i) { 238 float bounds[2];
232 cropRect[i] = random->nextF(); 239 for (int i = 0; i < 2; ++i) {
240 bounds[i] = random->nextF();
233 } 241 }
234 242
235 bool useCropRect = random->nextBool(); 243 bool useBounds = random->nextBool();
236 return GrConvolutionEffect::Create(textures[texIdx], 244 return GrConvolutionEffect::Create(textures[texIdx],
237 dir, 245 dir,
238 radius, 246 radius,
239 kernel, 247 kernel,
240 useCropRect, 248 useBounds,
241 cropRect); 249 bounds);
242 } 250 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrConvolutionEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698