• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 GrMatrixConvolutionEffect_DEFINED
9 #define GrMatrixConvolutionEffect_DEFINED
10 
11 #include "src/gpu/GrFragmentProcessor.h"
12 #include <array>
13 #include <new>
14 
15 class GrMatrixConvolutionEffect : public GrFragmentProcessor {
16 public:
17     // A little bit less than the minimum # uniforms required by DX9SM2 (32).
18     // Allows for a 5x5 kernel (or 28x1, for that matter).
19     // Must be a multiple of 4, since we upload these in vec4s.
20     inline static constexpr int kMaxUniformSize = 28;
21 
22     static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext*,
23                                                      GrSurfaceProxyView srcView,
24                                                      const SkIRect& srcBounds,
25                                                      const SkISize& kernelSize,
26                                                      const SkScalar* kernel,
27                                                      SkScalar gain,
28                                                      SkScalar bias,
29                                                      const SkIPoint& kernelOffset,
30                                                      GrSamplerState::WrapMode,
31                                                      bool convolveAlpha,
32                                                      const GrCaps&);
33 
name()34     const char* name() const override { return "MatrixConvolution"; }
35 
36     std::unique_ptr<GrFragmentProcessor> clone() const override;
37 
38 private:
39     class Impl;
40 
41     /**
42      * Small kernels are represented as float-arrays and uploaded as uniforms.
43      * Large kernels go over the uniform limit and are uploaded as textures and sampled.
44      * If Float16 textures are supported, we use those. Otherwise we use A8.
45      */
46     class KernelWrapper {
47     public:
48         struct BiasAndGain {
49             // Only used in A8 mode. Applied before any other math.
50             float fBias;
51             // Only used in A8 mode. Premultiplied in with user gain to save time.
52             float fGain;
53             bool operator==(const BiasAndGain&) const;
54         };
55         using MakeResult = std::tuple<KernelWrapper, std::unique_ptr<GrFragmentProcessor>>;
56         static MakeResult Make(GrRecordingContext*, SkISize, const GrCaps&, const float* values);
57 
58         KernelWrapper() = default;
KernelWrapper(const KernelWrapper & that)59         KernelWrapper(const KernelWrapper& that) : fSize(that.fSize) {
60             if (that.isSampled()) {
61                 fBiasAndGain = that.fBiasAndGain;
62             } else {
63                 new (&fArray) std::array<float, kMaxUniformSize>(that.fArray);
64             }
65         }
66 
isValid()67         bool isValid() const { return !fSize.isEmpty(); }
size()68         SkISize size() const { return fSize; }
isSampled()69         bool isSampled() const { return fSize.area() > kMaxUniformSize; }
array()70         const std::array<float, kMaxUniformSize>& array() const {
71             SkASSERT(!this->isSampled());
72             return fArray;
73         }
biasAndGain()74         const BiasAndGain& biasAndGain() const {
75             SkASSERT(this->isSampled());
76             return fBiasAndGain;
77         }
78         bool operator==(const KernelWrapper&) const;
79 
80     private:
KernelWrapper(SkISize size)81         KernelWrapper(SkISize size) : fSize(size) {
82             if (this->isSampled()) {
83                 fBiasAndGain = {0.f , 1.f};
84             }
85         }
86 
87         SkISize fSize = {};
88         union {
89             std::array<float, kMaxUniformSize> fArray;
90             BiasAndGain fBiasAndGain;
91         };
92     };
93 
94     GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child,
95                               const KernelWrapper& kernel,
96                               std::unique_ptr<GrFragmentProcessor> kernelFP,
97                               SkScalar gain,
98                               SkScalar bias,
99                               const SkIPoint& kernelOffset,
100                               bool convolveAlpha);
101 
102     explicit GrMatrixConvolutionEffect(const GrMatrixConvolutionEffect&);
103 
104     std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
105 
106     void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
107 
108     bool onIsEqual(const GrFragmentProcessor&) const override;
109 
110     KernelWrapper    fKernel;
111     float            fGain;
112     float            fBias;
113     SkVector         fKernelOffset;
114     bool             fConvolveAlpha;
115 
116     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
117 
118     using INHERITED = GrFragmentProcessor;
119 };
120 
121 #endif
122