• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
clone()43     std::unique_ptr<GrFragmentProcessor> clone() const override {
44         return std::unique_ptr<GrFragmentProcessor>(
45                 new GrGaussianConvolutionFragmentProcessor(*this));
46     }
47 
48     // This was decided based on the min allowed value for the max texture
49     // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
50     // on a blur filter gives a kernel width of 25 while a sigma of 5.0
51     // would exceed a 32 wide kernel.
52     inline static constexpr int kMaxKernelRadius = 12;
53 
54 private:
55     class Impl;
56 
57     GrGaussianConvolutionFragmentProcessor(std::unique_ptr<GrFragmentProcessor>,
58                                            Direction,
59                                            int halfWidth,
60                                            float gaussianSigma);
61 
62     explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&);
63 
64 #if GR_TEST_UTILS
onDumpInfo()65     SkString onDumpInfo() const override {
66         return SkStringPrintf("(dir=%s, radius=%d)",
67                               Direction::kX == fDirection ? "X" : "Y", fRadius);
68     }
69 #endif
70 
71     std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
72 
73     void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
74 
75     bool onIsEqual(const GrFragmentProcessor&) const override;
76 
77     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
78 
79     inline static constexpr int kMaxKernelWidth = kMaxKernelRadius + 1;
80 
81     // The array size must be a multiple of 4 because we pass it as an array of float4 uniform
82     // values.
83     float                 fKernel[SkAlign4(kMaxKernelWidth)];
84     float                 fOffsets[SkAlign4(kMaxKernelWidth)];
85     int                   fRadius;
86     Direction             fDirection;
87 
88     using INHERITED = GrFragmentProcessor;
89 };
90 
91 #endif
92