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 GrGaussianConvolutionFragmentProcessor_DEFINED 9 #define GrGaussianConvolutionFragmentProcessor_DEFINED 10 11 #include "src/gpu/GrFragmentProcessor.h" 12 13 /** 14 * A 1D Gaussian convolution effect. The kernel is computed as an array of 2 * half-width weights. 15 * Each texel is multiplied by it's weight and summed to determine the filtered color. The output 16 * color is set to a modulation of the filtered and input colors. 17 */ 18 class GrGaussianConvolutionFragmentProcessor : public GrFragmentProcessor { 19 public: 20 enum class Direction { kX, kY }; 21 22 /** 23 * Convolve with a Gaussian kernel. Bounds limits the coords sampled by the effect along the 24 * axis indicated by Direction. The WrapMode is applied to the subset. If present, the 25 * pixelDomain indicates the domain of pixels that this effect will be called with. It should 26 * not account for outsetting due to the filter radius, this effect will handle that. It is 27 * assumed that the effect is only invoked at pixel centers within the pixelDomain, the 28 * effect will optimize for that, and may produce incorrect results if it is not the case. If 29 * pixelDomain is null then the effect will work correctly with any sample coordinates. 30 */ 31 static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView, 32 SkAlphaType, 33 Direction, 34 int halfWidth, 35 float gaussianSigma, 36 GrSamplerState::WrapMode, 37 const SkIRect& subset, 38 const SkIRect* pixelDomain, 39 const GrCaps&); 40 name()41 const char* name() const override { return "GaussianConvolution"; } 42 43 SkString getShaderDfxInfo() const override; 44 clone()45 std::unique_ptr<GrFragmentProcessor> clone() const override { 46 return std::unique_ptr<GrFragmentProcessor>( 47 new GrGaussianConvolutionFragmentProcessor(*this)); 48 } 49 50 // This was decided based on the min allowed value for the max texture 51 // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0 52 // on a blur filter gives a kernel width of 25 while a sigma of 5.0 53 // would exceed a 32 wide kernel. 54 inline static constexpr int kMaxKernelRadius = 12; 55 56 private: 57 class Impl; 58 59 GrGaussianConvolutionFragmentProcessor(std::unique_ptr<GrFragmentProcessor>, 60 Direction, 61 int halfWidth, 62 float gaussianSigma); 63 64 explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&); 65 66 #if GR_TEST_UTILS onDumpInfo()67 SkString onDumpInfo() const override { 68 return SkStringPrintf("(dir=%s, radius=%d)", 69 Direction::kX == fDirection ? "X" : "Y", fRadius); 70 } 71 #endif 72 73 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override; 74 75 void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 76 77 bool onIsEqual(const GrFragmentProcessor&) const override; 78 79 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 80 81 inline static constexpr int kMaxKernelWidth = kMaxKernelRadius + 1; 82 83 // The array size must be a multiple of 4 because we pass it as an array of float4 uniform 84 // values. 85 float fKernel[SkAlign4(kMaxKernelWidth)]; 86 float fOffsets[SkAlign4(kMaxKernelWidth)]; 87 int fRadius; 88 Direction fDirection; 89 90 using INHERITED = GrFragmentProcessor; 91 }; 92 93 #endif 94