• 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 
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