Home | History | Annotate | Download | only in effects
      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
     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 new GrConvolutionEffect(tex, dir, halfWidth, kernel, useBounds, bounds);
     31     }
     32 
     33     /// Convolve with a Gaussian kernel
     34     static GrFragmentProcessor* CreateGaussian(GrTexture* tex,
     35                                                Direction dir,
     36                                                int halfWidth,
     37                                                float gaussianSigma,
     38                                                bool useBounds,
     39                                                float bounds[2]) {
     40         return new GrConvolutionEffect(tex, dir, halfWidth, gaussianSigma, useBounds, bounds);
     41     }
     42 
     43     virtual ~GrConvolutionEffect();
     44 
     45     const float* kernel() const { return fKernel; }
     46 
     47     const float* bounds() const { return fBounds; }
     48     bool useBounds() const { return fUseBounds; }
     49 
     50     const char* name() const override { return "Convolution"; }
     51 
     52     enum {
     53         // This was decided based on the min allowed value for the max texture
     54         // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
     55         // on a blur filter gives a kernel width of 25 while a sigma of 5.0
     56         // would exceed a 32 wide kernel.
     57         kMaxKernelRadius = 12,
     58         // With a C++11 we could have a constexpr version of WidthFromRadius()
     59         // and not have to duplicate this calculation.
     60         kMaxKernelWidth = 2 * kMaxKernelRadius + 1,
     61     };
     62 
     63 protected:
     64 
     65     float fKernel[kMaxKernelWidth];
     66     bool fUseBounds;
     67     float fBounds[2];
     68 
     69 private:
     70     GrConvolutionEffect(GrTexture*, Direction,
     71                         int halfWidth,
     72                         const float* kernel,
     73                         bool useBounds,
     74                         float bounds[2]);
     75 
     76     /// Convolve with a Gaussian kernel
     77     GrConvolutionEffect(GrTexture*, Direction,
     78                         int halfWidth,
     79                         float gaussianSigma,
     80                         bool useBounds,
     81                         float bounds[2]);
     82 
     83     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     84 
     85     void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
     86 
     87     bool onIsEqual(const GrFragmentProcessor&) const override;
     88 
     89     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
     90         // If the texture was opaque we could know that the output color if we knew the sum of the
     91         // kernel values.
     92         inout->mulByUnknownFourComponents();
     93     }
     94 
     95     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     96 
     97     typedef Gr1DKernelEffect INHERITED;
     98 };
     99 
    100 #endif
    101