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 
     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 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
     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 
     58     const float* kernel() const { return fKernel; }
     59 
     60     const float* bounds() const { return fBounds; }
     61     bool useBounds() const { return fUseBounds; }
     62 
     63     static const char* Name() { return "Convolution"; }
     64 
     65     typedef GrGLConvolutionEffect GLEffect;
     66 
     67     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
     68 
     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