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