Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include "GrMatrixConvolutionEffect.h" | 7 #include "GrMatrixConvolutionEffect.h" |
| 8 #include "gl/GrGLShaderBuilder.h" | 8 #include "gl/GrGLShaderBuilder.h" |
| 9 #include "gl/GrGLEffect.h" | 9 #include "gl/GrGLEffect.h" |
| 10 #include "gl/GrGLSL.h" | 10 #include "gl/GrGLSL.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB uilder*); | 26 static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyB uilder*); |
| 27 | 27 |
| 28 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | 28 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; |
| 29 | 29 |
| 30 private: | 30 private: |
| 31 typedef GrGLUniformManager::UniformHandle UniformHandle; | 31 typedef GrGLUniformManager::UniformHandle UniformHandle; |
| 32 typedef GrMatrixConvolutionEffect::TileMode TileMode; | 32 typedef GrMatrixConvolutionEffect::TileMode TileMode; |
| 33 SkISize fKernelSize; | 33 SkISize fKernelSize; |
| 34 TileMode fTileMode; | 34 TileMode fTileMode; |
| 35 bool fConvolveAlpha; | 35 bool fConvolveAlpha; |
| 36 bool fUseBounds; | |
| 36 | 37 |
| 37 UniformHandle fBoundsUni; | 38 UniformHandle fBoundsUni; |
| 38 UniformHandle fKernelUni; | 39 UniformHandle fKernelUni; |
| 39 UniformHandle fImageIncrementUni; | 40 UniformHandle fImageIncrementUni; |
| 40 UniformHandle fKernelOffsetUni; | 41 UniformHandle fKernelOffsetUni; |
| 41 UniformHandle fGainUni; | 42 UniformHandle fGainUni; |
| 42 UniformHandle fBiasUni; | 43 UniformHandle fBiasUni; |
| 43 | 44 |
| 44 typedef GrGLEffect INHERITED; | 45 typedef GrGLEffect INHERITED; |
| 45 }; | 46 }; |
| 46 | 47 |
| 47 GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa ctory& factory, | 48 GrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendEffectFa ctory& factory, |
| 48 const GrDrawEffect& dra wEffect) | 49 const GrDrawEffect& dra wEffect) |
| 49 : INHERITED(factory) { | 50 : INHERITED(factory) { |
| 50 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti onEffect>(); | 51 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti onEffect>(); |
| 51 fKernelSize = m.kernelSize(); | 52 fKernelSize = m.kernelSize(); |
| 52 fTileMode = m.tileMode(); | 53 fTileMode = m.tileMode(); |
| 53 fConvolveAlpha = m.convolveAlpha(); | 54 fConvolveAlpha = m.convolveAlpha(); |
| 55 fUseBounds = m.useBounds(); | |
| 54 } | 56 } |
| 55 | 57 |
| 56 static void appendTextureLookup(GrGLShaderBuilder* builder, | 58 static void appendTextureLookup(GrGLShaderBuilder* builder, |
| 57 const GrGLShaderBuilder::TextureSampler& sampler , | 59 const GrGLShaderBuilder::TextureSampler& sampler , |
| 58 const char* coord, | 60 const char* coord, |
| 59 const char* bounds, | 61 const char* bounds, |
| 60 GrMatrixConvolutionEffect::TileMode tileMode) { | 62 GrMatrixConvolutionEffect::TileMode tileMode) { |
| 61 SkString clampedCoord; | 63 SkString clampedCoord; |
| 62 switch (tileMode) { | 64 if (bounds != NULL) { |
| 63 case GrMatrixConvolutionEffect::kClamp_TileMode: | 65 switch (tileMode) { |
| 64 clampedCoord.printf("clamp(%s, %s.xy, %s.zw)", coord, bounds, bounds ); | 66 case GrMatrixConvolutionEffect::kClamp_TileMode: |
| 65 coord = clampedCoord.c_str(); | 67 clampedCoord.printf("clamp(%s, %s.xy, %s.zw)", coord, bounds, bo unds); |
| 66 break; | 68 coord = clampedCoord.c_str(); |
| 67 case GrMatrixConvolutionEffect::kRepeat_TileMode: | 69 break; |
| 68 clampedCoord.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy", coord, bounds, bounds, bounds, bounds); | 70 case GrMatrixConvolutionEffect::kRepeat_TileMode: |
| 69 coord = clampedCoord.c_str(); | 71 clampedCoord.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy", co ord, bounds, bounds, |
| 70 break; | 72 bounds, bounds); |
| 71 case GrMatrixConvolutionEffect::kClampToBlack_TileMode: | 73 coord = clampedCoord.c_str(); |
| 72 builder->fsCodeAppendf("clamp(%s, %s.xy, %s.zw) != %s ? vec4(0, 0, 0 , 0) : ", coord, bounds, bounds, coord); | 74 break; |
| 73 break; | 75 case GrMatrixConvolutionEffect::kClampToBlack_TileMode: |
| 76 builder->fsCodeAppendf("clamp(%s, %s.xy, %s.zw) != %s ? vec4(0, 0, 0, 0) : ", coord, | |
| 77 bounds, bounds, coord); | |
| 78 break; | |
| 79 } | |
| 74 } | 80 } |
| 75 builder->fsAppendTextureLookup(sampler, coord); | 81 builder->fsAppendTextureLookup(sampler, coord); |
| 76 } | 82 } |
| 77 | 83 |
| 78 void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, | 84 void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder, |
| 79 const GrDrawEffect&, | 85 const GrDrawEffect&, |
| 80 const GrEffectKey& key, | 86 const GrEffectKey& key, |
| 81 const char* outputColor, | 87 const char* outputColor, |
| 82 const char* inputColor, | 88 const char* inputColor, |
| 83 const TransformedCoordsArray& coords, | 89 const TransformedCoordsArray& coords, |
| 84 const TextureSamplerArray& samplers) { | 90 const TextureSamplerArray& samplers) { |
| 85 sk_ignore_unused_variable(inputColor); | 91 sk_ignore_unused_variable(inputColor); |
| 86 SkString coords2D = builder->ensureFSCoords2D(coords, 0); | 92 SkString coords2D = builder->ensureFSCoords2D(coords, 0); |
| 87 fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 93 if (fUseBounds) { |
| 88 kVec4f_GrSLType, "Bounds"); | 94 fBoundsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility , |
| 95 kVec4f_GrSLType, "Bounds"); | |
| 96 } | |
| 89 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi lity, | 97 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi lity, |
| 90 kVec2f_GrSLType, "ImageIncrement"); | 98 kVec2f_GrSLType, "ImageIncrement"); |
| 91 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibilit y, | 99 fKernelUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibilit y, |
| 92 kFloat_GrSLType, | 100 kFloat_GrSLType, |
| 93 "Kernel", | 101 "Kernel", |
| 94 fKernelSize.width() * fKernelSize.h eight()); | 102 fKernelSize.width() * fKernelSize.h eight()); |
| 95 fKernelOffsetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty, | 103 fKernelOffsetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty, |
| 96 kVec2f_GrSLType, "KernelOffset"); | 104 kVec2f_GrSLType, "KernelOffset"); |
| 97 fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 105 fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
| 98 kFloat_GrSLType, "Gain"); | 106 kFloat_GrSLType, "Gain"); |
| 99 fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 107 fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
| 100 kFloat_GrSLType, "Bias"); | 108 kFloat_GrSLType, "Bias"); |
| 101 | 109 |
| 102 const char* bounds = builder->getUniformCStr(fBoundsUni); | 110 const char* bounds = NULL; |
| 111 if (fUseBounds) { | |
| 112 bounds = builder->getUniformCStr(fBoundsUni); | |
| 113 } | |
| 103 const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni); | 114 const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni); |
| 104 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); | 115 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); |
| 105 const char* kernel = builder->getUniformCStr(fKernelUni); | 116 const char* kernel = builder->getUniformCStr(fKernelUni); |
| 106 const char* gain = builder->getUniformCStr(fGainUni); | 117 const char* gain = builder->getUniformCStr(fGainUni); |
| 107 const char* bias = builder->getUniformCStr(fBiasUni); | 118 const char* bias = builder->getUniformCStr(fBiasUni); |
| 108 int kWidth = fKernelSize.width(); | 119 int kWidth = fKernelSize.width(); |
| 109 int kHeight = fKernelSize.height(); | 120 int kHeight = fKernelSize.height(); |
| 110 | 121 |
| 111 builder->fsCodeAppend("\t\tvec4 sum = vec4(0, 0, 0, 0);\n"); | 122 builder->fsCodeAppend("\t\tvec4 sum = vec4(0, 0, 0, 0);\n"); |
| 112 builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(), kernelOffset, imgInc); | 123 builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(), kernelOffset, |
| 113 builder->fsCodeAppendf("\t\tfor (int y = 0; y < %d; y++) {\n", kHeight); | 124 imgInc); |
| 114 builder->fsCodeAppendf("\t\t\tfor (int x = 0; x < %d; x++) {\n", kWidth); | 125 builder->fsCodeAppend("\t\tfloat k;\n"); |
| 115 builder->fsCodeAppendf("\t\t\t\tfloat k = %s[y * %d + x];\n", kernel, kWidth ); | 126 builder->fsCodeAppend("\t\tvec2 coord2;\n"); |
| 116 builder->fsCodeAppendf("\t\t\t\tvec2 coord2 = coord + vec2(x, y) * %s;\n", i mgInc); | 127 builder->fsCodeAppend("\t\tvec4 c;\n"); |
| 117 builder->fsCodeAppend("\t\t\t\tvec4 c = "); | 128 |
| 118 appendTextureLookup(builder, samplers[0], "coord2", bounds, fTileMode); | 129 for (int y = 0; y < kHeight; y++) { |
| 119 builder->fsCodeAppend(";\n"); | 130 for (int x = 0; x < kWidth; x++) { |
| 120 if (!fConvolveAlpha) { | 131 builder->fsCodeAppendf("\t\tk = %s[%d * %d + %d];\n", kernel, y, kWi dth, x); |
| 121 builder->fsCodeAppend("\t\t\t\tc.rgb /= c.a;\n"); | 132 builder->fsCodeAppendf("\t\tcoord2 = coord + vec2(%d, %d) * %s;\n", x, y, imgInc); |
| 133 builder->fsCodeAppend("\t\tc = "); | |
| 134 appendTextureLookup(builder, samplers[0], "coord2", bounds, fTileMod e); | |
| 135 builder->fsCodeAppend(";\n"); | |
| 136 if (!fConvolveAlpha) { | |
| 137 builder->fsCodeAppend("\t\tc.rgb /= c.a;\n"); | |
| 138 } | |
| 139 builder->fsCodeAppend("\t\tsum += c * k;\n"); | |
| 140 } | |
| 122 } | 141 } |
| 123 builder->fsCodeAppend("\t\t\t\tsum += c * k;\n"); | |
| 124 builder->fsCodeAppend("\t\t\t}\n"); | |
| 125 builder->fsCodeAppend("\t\t}\n"); | |
| 126 if (fConvolveAlpha) { | 142 if (fConvolveAlpha) { |
| 127 builder->fsCodeAppendf("\t\t%s = sum * %s + %s;\n", outputColor, gain, b ias); | 143 builder->fsCodeAppendf("\t\t%s = sum * %s + %s;\n", outputColor, gain, b ias); |
| 128 builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", | 144 builder->fsCodeAppendf("\t\t%s.rgb = clamp(%s.rgb, 0.0, %s.a);\n", |
| 129 outputColor, outputColor, outputColor); | 145 outputColor, outputColor, outputColor); |
| 130 } else { | 146 } else { |
| 131 builder->fsCodeAppend("\t\tvec4 c = "); | 147 builder->fsCodeAppend("\t\tc = "); |
| 132 appendTextureLookup(builder, samplers[0], coords2D.c_str(), bounds, fTil eMode); | 148 appendTextureLookup(builder, samplers[0], coords2D.c_str(), bounds, fTil eMode); |
| 133 builder->fsCodeAppend(";\n"); | 149 builder->fsCodeAppend(";\n"); |
| 134 builder->fsCodeAppendf("\t\t%s.a = c.a;\n", outputColor); | 150 builder->fsCodeAppendf("\t\t%s.a = c.a;\n", outputColor); |
| 135 builder->fsCodeAppendf("\t\t%s.rgb = sum.rgb * %s + %s;\n", outputColor, gain, bias); | 151 builder->fsCodeAppendf("\t\t%s.rgb = sum.rgb * %s + %s;\n", outputColor, gain, bias); |
| 136 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor ); | 152 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor ); |
| 137 } | 153 } |
| 138 } | 154 } |
| 139 | 155 |
| 140 namespace { | 156 namespace { |
| 141 | 157 |
| 142 int encodeXY(int x, int y) { | 158 int encodeXY(int x, int y) { |
| 143 SkASSERT(x >= 1 && y >= 1 && x * y <= 32); | 159 SkASSERT(x >= 1 && y >= 1 && x * y <= 32); |
| 144 if (y < x) | 160 if (y < x) |
| 145 return 0x40 | encodeXY(y, x); | 161 return 0x40 | encodeXY(y, x); |
| 146 else | 162 else |
| 147 return (0x40 >> x) | (y - x); | 163 return (0x40 >> x) | (y - x); |
| 148 } | 164 } |
| 149 | 165 |
| 150 }; | 166 }; |
| 151 | 167 |
| 152 void GrGLMatrixConvolutionEffect::GenKey(const GrDrawEffect& drawEffect, | 168 void GrGLMatrixConvolutionEffect::GenKey(const GrDrawEffect& drawEffect, |
| 153 const GrGLCaps&, GrEffectKeyBuilder* b) { | 169 const GrGLCaps&, GrEffectKeyBuilder* b) { |
| 154 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti onEffect>(); | 170 const GrMatrixConvolutionEffect& m = drawEffect.castEffect<GrMatrixConvoluti onEffect>(); |
| 155 uint32_t key = encodeXY(m.kernelSize().width(), m.kernelSize().height()); | 171 uint32_t key = encodeXY(m.kernelSize().width(), m.kernelSize().height()); |
|
bsalomon
2014/07/28 15:20:41
When this was originally written we had a really r
| |
| 156 key |= m.tileMode() << 7; | 172 key |= m.tileMode() << 7; |
| 157 key |= m.convolveAlpha() ? 1 << 9 : 0; | 173 key |= m.convolveAlpha() ? 1 << 9 : 0; |
| 174 key |= m.useBounds() ? 1 << 10 : 0; | |
| 158 b->add32(key); | 175 b->add32(key); |
| 159 } | 176 } |
| 160 | 177 |
| 161 void GrGLMatrixConvolutionEffect::setData(const GrGLUniformManager& uman, | 178 void GrGLMatrixConvolutionEffect::setData(const GrGLUniformManager& uman, |
| 162 const GrDrawEffect& drawEffect) { | 179 const GrDrawEffect& drawEffect) { |
| 163 const GrMatrixConvolutionEffect& conv = drawEffect.castEffect<GrMatrixConvol utionEffect>(); | 180 const GrMatrixConvolutionEffect& conv = drawEffect.castEffect<GrMatrixConvol utionEffect>(); |
| 164 GrTexture& texture = *conv.texture(0); | 181 GrTexture& texture = *conv.texture(0); |
| 165 // the code we generated was for a specific kernel size | 182 // the code we generated was for a specific kernel size |
| 166 SkASSERT(conv.kernelSize() == fKernelSize); | 183 SkASSERT(conv.kernelSize() == fKernelSize); |
| 167 SkASSERT(conv.tileMode() == fTileMode); | 184 SkASSERT(conv.tileMode() == fTileMode); |
| 168 float imageIncrement[2]; | 185 float imageIncrement[2]; |
| 169 float ySign = texture.origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; | 186 float ySign = texture.origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; |
| 170 imageIncrement[0] = 1.0f / texture.width(); | 187 imageIncrement[0] = 1.0f / texture.width(); |
| 171 imageIncrement[1] = ySign / texture.height(); | 188 imageIncrement[1] = ySign / texture.height(); |
| 172 uman.set2fv(fImageIncrementUni, 1, imageIncrement); | 189 uman.set2fv(fImageIncrementUni, 1, imageIncrement); |
| 173 uman.set2fv(fKernelOffsetUni, 1, conv.kernelOffset()); | 190 uman.set2fv(fKernelOffsetUni, 1, conv.kernelOffset()); |
| 174 uman.set1fv(fKernelUni, fKernelSize.width() * fKernelSize.height(), conv.ker nel()); | 191 uman.set1fv(fKernelUni, fKernelSize.width() * fKernelSize.height(), conv.ker nel()); |
| 175 uman.set1f(fGainUni, conv.gain()); | 192 uman.set1f(fGainUni, conv.gain()); |
| 176 uman.set1f(fBiasUni, conv.bias()); | 193 uman.set1f(fBiasUni, conv.bias()); |
| 177 const SkIRect& bounds = conv.bounds(); | 194 if (fUseBounds) { |
| 178 float left = (float) bounds.left() / texture.width(); | 195 const SkIRect& bounds = conv.bounds(); |
| 179 float top = (float) bounds.top() / texture.height(); | 196 float left = (float) bounds.left() / texture.width(); |
| 180 float right = (float) bounds.right() / texture.width(); | 197 float top = (float) bounds.top() / texture.height(); |
| 181 float bottom = (float) bounds.bottom() / texture.height(); | 198 float right = (float) bounds.right() / texture.width(); |
| 182 if (texture.origin() == kBottomLeft_GrSurfaceOrigin) { | 199 float bottom = (float) bounds.bottom() / texture.height(); |
| 183 uman.set4f(fBoundsUni, left, 1.0f - bottom, right, 1.0f - top); | 200 if (texture.origin() == kBottomLeft_GrSurfaceOrigin) { |
| 184 } else { | 201 uman.set4f(fBoundsUni, left, 1.0f - bottom, right, 1.0f - top); |
| 185 uman.set4f(fBoundsUni, left, top, right, bottom); | 202 } else { |
| 203 uman.set4f(fBoundsUni, left, top, right, bottom); | |
| 204 } | |
| 186 } | 205 } |
| 187 } | 206 } |
| 188 | 207 |
| 189 GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, | 208 GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, |
| 190 const SkIRect& bounds, | 209 const SkIRect& bounds, |
| 191 const SkISize& kernelSize, | 210 const SkISize& kernelSize, |
| 192 const SkScalar* kernel, | 211 const SkScalar* kernel, |
| 193 SkScalar gain, | 212 SkScalar gain, |
| 194 SkScalar bias, | 213 SkScalar bias, |
| 195 const SkIPoint& kernelOffse t, | 214 const SkIPoint& kernelOffse t, |
| 196 TileMode tileMode, | 215 TileMode tileMode, |
| 197 bool convolveAlpha) | 216 bool convolveAlpha, |
| 217 bool useBounds) | |
| 198 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)), | 218 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)), |
| 199 fBounds(bounds), | 219 fBounds(bounds), |
| 200 fKernelSize(kernelSize), | 220 fKernelSize(kernelSize), |
| 201 fGain(SkScalarToFloat(gain)), | 221 fGain(SkScalarToFloat(gain)), |
| 202 fBias(SkScalarToFloat(bias) / 255.0f), | 222 fBias(SkScalarToFloat(bias) / 255.0f), |
| 203 fTileMode(tileMode), | 223 fTileMode(tileMode), |
| 204 fConvolveAlpha(convolveAlpha) { | 224 fConvolveAlpha(convolveAlpha), |
| 205 fKernel = new float[kernelSize.width() * kernelSize.height()]; | 225 fUseBounds(useBounds) { |
| 206 for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) { | 226 for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) { |
| 207 fKernel[i] = SkScalarToFloat(kernel[i]); | 227 fKernel[i] = SkScalarToFloat(kernel[i]); |
| 208 } | 228 } |
| 209 fKernelOffset[0] = static_cast<float>(kernelOffset.x()); | 229 fKernelOffset[0] = static_cast<float>(kernelOffset.x()); |
| 210 fKernelOffset[1] = static_cast<float>(kernelOffset.y()); | 230 fKernelOffset[1] = static_cast<float>(kernelOffset.y()); |
| 211 this->setWillNotUseInputColor(); | 231 this->setWillNotUseInputColor(); |
|
bsalomon
2014/07/28 15:20:41
I think if we're using this for mask filter blur t
| |
| 212 } | 232 } |
| 213 | 233 |
| 214 GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() { | 234 GrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() { |
| 215 delete[] fKernel; | |
| 216 } | 235 } |
| 217 | 236 |
| 218 const GrBackendEffectFactory& GrMatrixConvolutionEffect::getFactory() const { | 237 const GrBackendEffectFactory& GrMatrixConvolutionEffect::getFactory() const { |
| 219 return GrTBackendEffectFactory<GrMatrixConvolutionEffect>::getInstance(); | 238 return GrTBackendEffectFactory<GrMatrixConvolutionEffect>::getInstance(); |
| 220 } | 239 } |
| 221 | 240 |
| 222 bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const { | 241 bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const { |
| 223 const GrMatrixConvolutionEffect& s = CastEffect<GrMatrixConvolutionEffect>(s Base); | 242 const GrMatrixConvolutionEffect& s = CastEffect<GrMatrixConvolutionEffect>(s Base); |
| 224 return this->texture(0) == s.texture(0) && | 243 return this->texture(0) == s.texture(0) && |
| 225 fKernelSize == s.kernelSize() && | 244 fKernelSize == s.kernelSize() && |
| 226 !memcmp(fKernel, s.kernel(), | 245 !memcmp(fKernel, s.kernel(), |
| 227 fKernelSize.width() * fKernelSize.height() * sizeof(float)) & & | 246 fKernelSize.width() * fKernelSize.height() * sizeof(float)) & & |
| 228 fGain == s.gain() && | 247 fGain == s.gain() && |
| 229 fBias == s.bias() && | 248 fBias == s.bias() && |
| 230 fKernelOffset == s.kernelOffset() && | 249 fKernelOffset == s.kernelOffset() && |
| 231 fTileMode == s.tileMode() && | 250 fTileMode == s.tileMode() && |
| 232 fConvolveAlpha == s.convolveAlpha(); | 251 fConvolveAlpha == s.convolveAlpha(); |
| 233 } | 252 } |
| 234 | 253 |
| 254 // Static function to create a 2D convolution | |
| 255 GrEffect* GrMatrixConvolutionEffect::CreateGaussian(GrTexture* texture, | |
| 256 const SkIRect& bounds, | |
| 257 const SkISize& kernelSize, | |
| 258 SkScalar gain, | |
| 259 SkScalar bias, | |
| 260 const SkIPoint& kernelOffset , | |
| 261 TileMode tileMode, | |
| 262 bool convolveAlpha, | |
| 263 bool useBounds, | |
| 264 SkScalar sigmaX, | |
| 265 SkScalar sigmaY) { | |
| 266 float kernel[MAX_KERNEL_SIZE]; | |
| 267 int width = kernelSize.width(); | |
| 268 int height = kernelSize.height(); | |
| 269 SkASSERT(width * height <= MAX_KERNEL_SIZE); | |
| 270 float sum = 0.0f; | |
| 271 float sigmaXDenom = 1.0 / (2.0 * sigmaX * sigmaX); | |
| 272 float sigmaYDenom = 1.0 / (2.0 * sigmaY * sigmaY); | |
| 273 int xRadius = width / 2; | |
| 274 int yRadius = height / 2; | |
| 275 for (int x = 0; x < width; x++) { | |
| 276 float xTerm = static_cast<float>(x - xRadius); | |
| 277 xTerm = SkScalarSquare(xTerm) * sigmaXDenom; | |
| 278 for (int y = 0; y < height; y++) { | |
| 279 float yTerm = static_cast<float>(y - yRadius); | |
| 280 | |
| 281 float xyTerm = sk_float_exp(-(xTerm + SkScalarSquare(yTerm) * sigmaYDeno m)); | |
| 282 // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian | |
| 283 // is dropped here, since we renormalize the kernel below. | |
| 284 kernel[y * width + x] = xyTerm; | |
| 285 sum += xyTerm; | |
| 286 } | |
| 287 } | |
| 288 // Normalize the kernel | |
| 289 float scale = 1.0f / sum; | |
| 290 for (int i = 0; i < width * height; ++i) { | |
| 291 kernel[i] *= scale; | |
| 292 } | |
| 293 return SkNEW_ARGS(GrMatrixConvolutionEffect, (texture, | |
| 294 bounds, | |
| 295 kernelSize, | |
| 296 kernel, | |
| 297 gain, | |
| 298 bias, | |
| 299 kernelOffset, | |
| 300 tileMode, | |
| 301 convolveAlpha, | |
| 302 useBounds)); | |
| 303 } | |
| 304 | |
| 235 GR_DEFINE_EFFECT_TEST(GrMatrixConvolutionEffect); | 305 GR_DEFINE_EFFECT_TEST(GrMatrixConvolutionEffect); |
| 236 | 306 |
| 237 GrEffect* GrMatrixConvolutionEffect::TestCreate(SkRandom* random, | 307 GrEffect* GrMatrixConvolutionEffect::TestCreate(SkRandom* random, |
| 238 GrContext* context, | 308 GrContext* context, |
| 239 const GrDrawTargetCaps&, | 309 const GrDrawTargetCaps&, |
| 240 GrTexture* textures[]) { | 310 GrTexture* textures[]) { |
| 241 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : | 311 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : |
| 242 GrEffectUnitTest::kAlphaTextureIdx; | 312 GrEffectUnitTest::kAlphaTextureIdx; |
| 243 int width = random->nextRangeU(1, MAX_KERNEL_SIZE); | 313 int width = random->nextRangeU(1, MAX_KERNEL_SIZE); |
| 244 int height = random->nextRangeU(1, MAX_KERNEL_SIZE / width); | 314 int height = random->nextRangeU(1, MAX_KERNEL_SIZE / width); |
| 245 SkISize kernelSize = SkISize::Make(width, height); | 315 SkISize kernelSize = SkISize::Make(width, height); |
| 246 SkAutoTDeleteArray<SkScalar> kernel(new SkScalar[width * height]); | 316 SkAutoTDeleteArray<SkScalar> kernel(new SkScalar[width * height]); |
| 247 for (int i = 0; i < width * height; i++) { | 317 for (int i = 0; i < width * height; i++) { |
| 248 kernel.get()[i] = random->nextSScalar1(); | 318 kernel.get()[i] = random->nextSScalar1(); |
| 249 } | 319 } |
| 250 SkScalar gain = random->nextSScalar1(); | 320 SkScalar gain = random->nextSScalar1(); |
| 251 SkScalar bias = random->nextSScalar1(); | 321 SkScalar bias = random->nextSScalar1(); |
| 252 SkIPoint kernelOffset = SkIPoint::Make(random->nextRangeU(0, kernelSize.widt h()), | 322 SkIPoint kernelOffset = SkIPoint::Make(random->nextRangeU(0, kernelSize.widt h()), |
| 253 random->nextRangeU(0, kernelSize.heig ht())); | 323 random->nextRangeU(0, kernelSize.heig ht())); |
| 254 SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->w idth()), | 324 SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->w idth()), |
| 255 random->nextRangeU(0, textures[texIdx]->h eight()), | 325 random->nextRangeU(0, textures[texIdx]->h eight()), |
| 256 random->nextRangeU(0, textures[texIdx]->w idth()), | 326 random->nextRangeU(0, textures[texIdx]->w idth()), |
| 257 random->nextRangeU(0, textures[texIdx]->h eight())); | 327 random->nextRangeU(0, textures[texIdx]->h eight())); |
| 258 TileMode tileMode = static_cast<TileMode>(random->nextRangeU(0, 2)); | 328 TileMode tileMode = static_cast<TileMode>(random->nextRangeU(0, 2)); |
| 259 bool convolveAlpha = random->nextBool(); | 329 bool convolveAlpha = random->nextBool(); |
| 330 bool useBounds = random->nextBool(); | |
| 260 return GrMatrixConvolutionEffect::Create(textures[texIdx], | 331 return GrMatrixConvolutionEffect::Create(textures[texIdx], |
| 261 bounds, | 332 bounds, |
| 262 kernelSize, | 333 kernelSize, |
| 263 kernel.get(), | 334 kernel.get(), |
| 264 gain, | 335 gain, |
| 265 bias, | 336 bias, |
| 266 kernelOffset, | 337 kernelOffset, |
| 267 tileMode, | 338 tileMode, |
| 268 convolveAlpha); | 339 convolveAlpha, |
| 340 useBounds); | |
| 269 } | 341 } |
| OLD | NEW |