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