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