1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrConvolutionEffect_DEFINED 9 #define GrConvolutionEffect_DEFINED 10 11 #include "Gr1DKernelEffect.h" 12 #include "GrInvariantOutput.h" 13 14 /** 15 * A convolution effect. The kernel is specified as an array of 2 * half-width 16 * + 1 weights. Each texel is multiplied by it's weight and summed to determine 17 * the output color. The output color is modulated by the input color. 18 */ 19 class GrConvolutionEffect : public Gr1DKernelEffect { 20 21 public: 22 23 /// Convolve with an arbitrary user-specified kernel Create(GrTexture * tex,Direction dir,int halfWidth,const float * kernel,bool useBounds,float bounds[2])24 static GrFragmentProcessor* Create(GrTexture* tex, 25 Direction dir, 26 int halfWidth, 27 const float* kernel, 28 bool useBounds, 29 float bounds[2]) { 30 return SkNEW_ARGS(GrConvolutionEffect, (tex, 31 dir, 32 halfWidth, 33 kernel, 34 useBounds, 35 bounds)); 36 } 37 38 /// Convolve with a Gaussian kernel CreateGaussian(GrTexture * tex,Direction dir,int halfWidth,float gaussianSigma,bool useBounds,float bounds[2])39 static GrFragmentProcessor* CreateGaussian(GrTexture* tex, 40 Direction dir, 41 int halfWidth, 42 float gaussianSigma, 43 bool useBounds, 44 float bounds[2]) { 45 return SkNEW_ARGS(GrConvolutionEffect, (tex, 46 dir, 47 halfWidth, 48 gaussianSigma, 49 useBounds, 50 bounds)); 51 } 52 53 virtual ~GrConvolutionEffect(); 54 kernel()55 const float* kernel() const { return fKernel; } 56 bounds()57 const float* bounds() const { return fBounds; } useBounds()58 bool useBounds() const { return fUseBounds; } 59 name()60 const char* name() const override { return "Convolution"; } 61 62 void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 63 64 GrGLFragmentProcessor* createGLInstance() const override; 65 66 enum { 67 // This was decided based on the min allowed value for the max texture 68 // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0 69 // on a blur filter gives a kernel width of 25 while a sigma of 5.0 70 // would exceed a 32 wide kernel. 71 kMaxKernelRadius = 12, 72 // With a C++11 we could have a constexpr version of WidthFromRadius() 73 // and not have to duplicate this calculation. 74 kMaxKernelWidth = 2 * kMaxKernelRadius + 1, 75 }; 76 77 protected: 78 79 float fKernel[kMaxKernelWidth]; 80 bool fUseBounds; 81 float fBounds[2]; 82 83 private: 84 GrConvolutionEffect(GrTexture*, Direction, 85 int halfWidth, 86 const float* kernel, 87 bool useBounds, 88 float bounds[2]); 89 90 /// Convolve with a Gaussian kernel 91 GrConvolutionEffect(GrTexture*, Direction, 92 int halfWidth, 93 float gaussianSigma, 94 bool useBounds, 95 float bounds[2]); 96 97 bool onIsEqual(const GrFragmentProcessor&) const override; 98 onComputeInvariantOutput(GrInvariantOutput * inout)99 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 100 // If the texture was opaque we could know that the output color if we knew the sum of the 101 // kernel values. 102 inout->mulByUnknownFourComponents(); 103 } 104 105 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 106 107 typedef Gr1DKernelEffect INHERITED; 108 }; 109 110 #endif 111