1ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt/* 2ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt * Copyright 2014 Google Inc. 3ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt * 4ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt * Use of this source code is governed by a BSD-style license that can be 5ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt * found in the LICENSE file. 6ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt */ 730ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 8ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt#include "GrMatrixConvolutionEffect.h" 9b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 10ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt#include "gl/GrGLSL.h" 11ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt#include "gl/GrGLTexture.h" 12b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 13ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 14b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLMatrixConvolutionEffect : public GrGLFragmentProcessor { 15ac9779234ef7a8cf3d791ab7690ef8c388662836joshualittpublic: 16b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGLMatrixConvolutionEffect(const GrBackendProcessorFactory& factory, 17b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor&); 1830ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder*, 19b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 20b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey&, 21ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* outputColor, 22ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* inputColor, 23ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const TransformedCoordsArray&, 24ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const TextureSamplerArray&) SK_OVERRIDE; 25ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 26b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*); 27ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 28b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 29ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 30ac9779234ef7a8cf3d791ab7690ef8c388662836joshualittprivate: 317510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen typedef GrGLProgramDataManager::UniformHandle UniformHandle; 325ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt SkISize fKernelSize; 335ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt bool fConvolveAlpha; 34ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 355ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fBoundsUni; 365ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fKernelUni; 375ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fImageIncrementUni; 385ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fKernelOffsetUni; 395ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fGainUni; 405ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt UniformHandle fBiasUni; 415ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt GrTextureDomain::GLDomain fDomain; 42ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 43b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLFragmentProcessor INHERITED; 44ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt}; 45ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 46b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLMatrixConvolutionEffect::GrGLMatrixConvolutionEffect(const GrBackendProcessorFactory& factory, 47b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& processor) 48ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt : INHERITED(factory) { 49b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrMatrixConvolutionEffect& m = processor.cast<GrMatrixConvolutionEffect>(); 50ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelSize = m.kernelSize(); 51ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fConvolveAlpha = m.convolveAlpha(); 52ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 53ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 5430ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLMatrixConvolutionEffect::emitCode(GrGLProgramBuilder* builder, 55b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor& fp, 56b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 57ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* outputColor, 58ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* inputColor, 59ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const TransformedCoordsArray& coords, 60ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const TextureSamplerArray& samplers) { 61ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt sk_ignore_unused_variable(inputColor); 62b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrTextureDomain& domain = fp.cast<GrMatrixConvolutionEffect>().domain(); 6330ba436f04e61d4505fb854d5fc56079636e0788joshualitt 6430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 65ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kVec4f_GrSLType, "Bounds"); 6630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 67ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kVec2f_GrSLType, "ImageIncrement"); 6830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, 695ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt kFloat_GrSLType, 705ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt "Kernel", 715ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt fKernelSize.width() * fKernelSize.height()); 7230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fKernelOffsetUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 735ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt kVec2f_GrSLType, "KernelOffset"); 7430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fGainUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 75ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kFloat_GrSLType, "Gain"); 7630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fBiasUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 77ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kFloat_GrSLType, "Bias"); 78ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 79ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni); 80ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 81ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* kernel = builder->getUniformCStr(fKernelUni); 82ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* gain = builder->getUniformCStr(fGainUni); 83ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const char* bias = builder->getUniformCStr(fBiasUni); 84ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt int kWidth = fKernelSize.width(); 85ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt int kHeight = fKernelSize.height(); 86ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 8730ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 8830ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); 8930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);"); 9030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, 915ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt imgInc); 9230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("vec4 c;"); 935ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt 945ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt for (int y = 0; y < kHeight; y++) { 955ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt for (int x = 0; x < kWidth; x++) { 9630ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLShaderBuilder::ShaderBlock block(fsBuilder); 9730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x); 985ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt SkString coord; 995ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt coord.printf("coord + vec2(%d, %d) * %s", x, y, imgInc); 10030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fDomain.sampleTexture(fsBuilder, domain, "c", coord, samplers[0]); 1015ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt if (!fConvolveAlpha) { 10230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("c.rgb /= c.a;"); 1035ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt } 10430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("sum += c * k;"); 1055ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt } 106ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt } 107ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt if (fConvolveAlpha) { 10830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("%s = sum * %s + %s;", outputColor, gain, bias); 10930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);", 1105ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt outputColor, outputColor, outputColor); 111ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt } else { 11230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fDomain.sampleTexture(fsBuilder, domain, "c", coords2D, samplers[0]); 11330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("%s.a = c.a;", outputColor); 11430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", outputColor, gain, bias); 11530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("%s.rgb *= %s.a;", outputColor, outputColor); 116ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt } 1175acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt 1185acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt SkString modulate; 1195acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 12030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(modulate.c_str()); 121ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 122ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 123b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLMatrixConvolutionEffect::GenKey(const GrProcessor& processor, 124b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGLCaps&, GrProcessorKeyBuilder* b) { 125b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrMatrixConvolutionEffect& m = processor.cast<GrMatrixConvolutionEffect>(); 1265ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt SkASSERT(m.kernelSize().width() <= 0x7FFF && m.kernelSize().height() <= 0xFFFF); 1275ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt uint32_t key = m.kernelSize().width() << 16 | m.kernelSize().height(); 1285ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt key |= m.convolveAlpha() ? 1 << 31 : 0; 129ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt b->add32(key); 1305ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt b->add32(GrTextureDomain::GLDomain::DomainKey(m.domain())); 131ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 132ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 1337510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLMatrixConvolutionEffect::setData(const GrGLProgramDataManager& pdman, 134b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& processor) { 135b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrMatrixConvolutionEffect& conv = processor.cast<GrMatrixConvolutionEffect>(); 136ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt GrTexture& texture = *conv.texture(0); 137ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt // the code we generated was for a specific kernel size 138ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkASSERT(conv.kernelSize() == fKernelSize); 139ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt float imageIncrement[2]; 140ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt float ySign = texture.origin() == kTopLeft_GrSurfaceOrigin ? 1.0f : -1.0f; 141ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt imageIncrement[0] = 1.0f / texture.width(); 142ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt imageIncrement[1] = ySign / texture.height(); 1437510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2fv(fImageIncrementUni, 1, imageIncrement); 1447510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2fv(fKernelOffsetUni, 1, conv.kernelOffset()); 1457510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1fv(fKernelUni, fKernelSize.width() * fKernelSize.height(), conv.kernel()); 1467510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fGainUni, conv.gain()); 1477510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fBiasUni, conv.bias()); 1487510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen fDomain.setData(pdman, conv.domain(), texture.origin()); 149ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 150ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 151ac9779234ef7a8cf3d791ab7690ef8c388662836joshualittGrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture, 152ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const SkIRect& bounds, 153ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const SkISize& kernelSize, 154ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const SkScalar* kernel, 155ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkScalar gain, 156ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkScalar bias, 157ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt const SkIPoint& kernelOffset, 1585ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt GrTextureDomain::Mode tileMode, 159ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt bool convolveAlpha) 1606267f81f3d60ce144ab2b09ea369420984d5c9d9bsalomon : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)), 161ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelSize(kernelSize), 162ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fGain(SkScalarToFloat(gain)), 163ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fBias(SkScalarToFloat(bias) / 255.0f), 1645ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt fConvolveAlpha(convolveAlpha), 1655ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt fDomain(GrTextureDomain::MakeTexelDomain(texture, bounds), tileMode) { 166ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) { 167ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernel[i] = SkScalarToFloat(kernel[i]); 168ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt } 169ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelOffset[0] = static_cast<float>(kernelOffset.x()); 170ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelOffset[1] = static_cast<float>(kernelOffset.y()); 171ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 172ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 173ac9779234ef7a8cf3d791ab7690ef8c388662836joshualittGrMatrixConvolutionEffect::~GrMatrixConvolutionEffect() { 174ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 175ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 176b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrMatrixConvolutionEffect::getFactory() const { 177b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<GrMatrixConvolutionEffect>::getInstance(); 178ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 179ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 180b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrMatrixConvolutionEffect::onIsEqual(const GrProcessor& sBase) const { 18149586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMatrixConvolutionEffect& s = sBase.cast<GrMatrixConvolutionEffect>(); 182ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt return this->texture(0) == s.texture(0) && 183ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelSize == s.kernelSize() && 184ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt !memcmp(fKernel, s.kernel(), 185ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelSize.width() * fKernelSize.height() * sizeof(float)) && 186ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fGain == s.gain() && 187ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fBias == s.bias() && 188ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt fKernelOffset == s.kernelOffset() && 1895ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt fConvolveAlpha == s.convolveAlpha() && 1905ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt fDomain == s.domain(); 191ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 192ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 1935acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt// Static function to create a 2D convolution 194b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* 195b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrMatrixConvolutionEffect::CreateGaussian(GrTexture* texture, 196b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkIRect& bounds, 197b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkISize& kernelSize, 198b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkScalar gain, 199b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkScalar bias, 200b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkIPoint& kernelOffset, 201b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTextureDomain::Mode tileMode, 202b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt bool convolveAlpha, 203b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkScalar sigmaX, 204b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkScalar sigmaY) { 2055acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float kernel[MAX_KERNEL_SIZE]; 2065acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt int width = kernelSize.width(); 2075acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt int height = kernelSize.height(); 2085acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt SkASSERT(width * height <= MAX_KERNEL_SIZE); 2095acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float sum = 0.0f; 2105acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float sigmaXDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaX))); 2115acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float sigmaYDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaY))); 2125acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt int xRadius = width / 2; 2135acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt int yRadius = height / 2; 2145acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt for (int x = 0; x < width; x++) { 2155acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float xTerm = static_cast<float>(x - xRadius); 2165acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt xTerm = xTerm * xTerm * sigmaXDenom; 2175acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt for (int y = 0; y < height; y++) { 2185acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float yTerm = static_cast<float>(y - yRadius); 2195acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float xyTerm = sk_float_exp(-(xTerm + yTerm * yTerm * sigmaYDenom)); 2205acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian 2215acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt // is dropped here, since we renormalize the kernel below. 2225acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt kernel[y * width + x] = xyTerm; 2235acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt sum += xyTerm; 2245acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt } 2255acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt } 2265acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt // Normalize the kernel 2275acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt float scale = 1.0f / sum; 2285acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt for (int i = 0; i < width * height; ++i) { 2295acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt kernel[i] *= scale; 2305acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt } 2315acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt return SkNEW_ARGS(GrMatrixConvolutionEffect, (texture, 2325acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt bounds, 2335acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt kernelSize, 2345acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt kernel, 2355acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt gain, 2365acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt bias, 2375acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt kernelOffset, 2385acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt tileMode, 2395acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt convolveAlpha)); 2405acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt} 2415acfea789d39106dbc706c6ee85cd8f027fce3edjoshualitt 242b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMatrixConvolutionEffect); 243ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt 244b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrMatrixConvolutionEffect::TestCreate(SkRandom* random, 245b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 246b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 247b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* textures[]) { 248b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 249b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 250ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt int width = random->nextRangeU(1, MAX_KERNEL_SIZE); 251ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt int height = random->nextRangeU(1, MAX_KERNEL_SIZE / width); 252ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkISize kernelSize = SkISize::Make(width, height); 253ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkAutoTDeleteArray<SkScalar> kernel(new SkScalar[width * height]); 254ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt for (int i = 0; i < width * height; i++) { 255ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kernel.get()[i] = random->nextSScalar1(); 256ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt } 257ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkScalar gain = random->nextSScalar1(); 258ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkScalar bias = random->nextSScalar1(); 259ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkIPoint kernelOffset = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()), 260ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt random->nextRangeU(0, kernelSize.height())); 261ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->width()), 262ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt random->nextRangeU(0, textures[texIdx]->height()), 263ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt random->nextRangeU(0, textures[texIdx]->width()), 264ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt random->nextRangeU(0, textures[texIdx]->height())); 2655ae5fc59b27a48711e514b3ede548b228e393e9bjoshualitt GrTextureDomain::Mode tileMode = static_cast<GrTextureDomain::Mode>(random->nextRangeU(0, 2)); 266ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt bool convolveAlpha = random->nextBool(); 267ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt return GrMatrixConvolutionEffect::Create(textures[texIdx], 268ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt bounds, 269ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kernelSize, 270ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kernel.get(), 271ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt gain, 272ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt bias, 273ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt kernelOffset, 274ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt tileMode, 275ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt convolveAlpha); 276ac9779234ef7a8cf3d791ab7690ef8c388662836joshualitt} 277