blob: b329b1d0e12007b721f8152dd9af5542bc4ba093 [file] [log] [blame]
Brian Salomonaee504b2017-01-24 12:29:36 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrCoordTransform.h"
12#include "src/gpu/GrFragmentProcessor.h"
13#include "src/gpu/effects/GrTextureDomain.h"
Brian Salomonaee504b2017-01-24 12:29:36 -050014
15/**
16 * A 1D Gaussian convolution effect. The kernel is computed as an array of 2 * half-width weights.
17 * Each texel is multiplied by it's weight and summed to determine the filtered color. The output
18 * color is set to a modulation of the filtered and input colors.
19 */
Brian Salomonb133ffe2017-07-27 11:53:21 -040020class GrGaussianConvolutionFragmentProcessor : public GrFragmentProcessor {
Brian Salomonaee504b2017-01-24 12:29:36 -050021public:
Brian Salomonb133ffe2017-07-27 11:53:21 -040022 enum class Direction { kX, kY };
23
Brian Salomonaee504b2017-01-24 12:29:36 -050024 /// Convolve with a Gaussian kernel
Brian Salomonaff329b2017-08-11 09:40:37 -040025 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
Brian Salomon7a538b12019-11-21 22:03:09 -050026 SkAlphaType alphaType,
Brian Salomonaff329b2017-08-11 09:40:37 -040027 Direction dir,
28 int halfWidth,
29 float gaussianSigma,
30 GrTextureDomain::Mode mode,
31 int* bounds) {
32 return std::unique_ptr<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
Brian Salomon7a538b12019-11-21 22:03:09 -050033 std::move(proxy), alphaType, dir, halfWidth, gaussianSigma, mode, bounds));
Robert Phillips40fd7c92017-01-30 08:06:27 -050034 }
35
Brian Salomonaee504b2017-01-24 12:29:36 -050036 const float* kernel() const { return fKernel; }
37
Robert Phillips08c5ec72017-01-30 12:26:47 -050038 const int* bounds() const { return fBounds; }
wutao039a7c72017-06-30 10:44:45 -070039 bool useBounds() const { return fMode != GrTextureDomain::kIgnore_Mode; }
Brian Salomonb133ffe2017-07-27 11:53:21 -040040 int radius() const { return fRadius; }
41 int width() const { return 2 * fRadius + 1; }
42 Direction direction() const { return fDirection; }
wutao039a7c72017-06-30 10:44:45 -070043
44 GrTextureDomain::Mode mode() const { return fMode; }
Brian Salomonaee504b2017-01-24 12:29:36 -050045
46 const char* name() const override { return "GaussianConvolution"; }
47
Brian Osman9a390ac2018-11-12 09:47:48 -050048#ifdef SK_DEBUG
Robert Phillipsce3c28f2018-07-18 13:52:40 -040049 SkString dumpInfo() const override {
50 SkString str;
51 str.appendf("dir: %s radius: %d bounds: [%d %d]",
52 Direction::kX == fDirection ? "X" : "Y",
53 fRadius,
54 fBounds[0], fBounds[1]);
55 return str;
56 }
Brian Osman9a390ac2018-11-12 09:47:48 -050057#endif
Robert Phillipsce3c28f2018-07-18 13:52:40 -040058
Brian Salomonaff329b2017-08-11 09:40:37 -040059 std::unique_ptr<GrFragmentProcessor> clone() const override {
60 return std::unique_ptr<GrFragmentProcessor>(
61 new GrGaussianConvolutionFragmentProcessor(*this));
Brian Salomon3f6f9652017-07-28 07:34:05 -040062 }
63
Brian Salomonaee504b2017-01-24 12:29:36 -050064 // This was decided based on the min allowed value for the max texture
65 // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
66 // on a blur filter gives a kernel width of 25 while a sigma of 5.0
67 // would exceed a 32 wide kernel.
68 static const int kMaxKernelRadius = 12;
69 // With a C++11 we could have a constexpr version of WidthFromRadius()
70 // and not have to duplicate this calculation.
71 static const int kMaxKernelWidth = 2 * kMaxKernelRadius + 1;
72
73private:
74 /// Convolve with a Gaussian kernel
Brian Salomon7a538b12019-11-21 22:03:09 -050075 GrGaussianConvolutionFragmentProcessor(sk_sp<GrTextureProxy>, SkAlphaType alphaType, Direction,
76 int halfWidth, float gaussianSigma,
wutao039a7c72017-06-30 10:44:45 -070077 GrTextureDomain::Mode mode, int bounds[2]);
Robert Phillips40fd7c92017-01-30 08:06:27 -050078
Brian Salomon3f6f9652017-07-28 07:34:05 -040079 explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&);
80
Brian Salomonaee504b2017-01-24 12:29:36 -050081 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
82
83 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
84
85 bool onIsEqual(const GrFragmentProcessor&) const override;
86
Brian Salomonf7dcd762018-07-30 14:48:15 -040087 const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
88
Brian Salomon0c26a9d2017-07-06 10:09:38 -040089 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
Brian Salomonaee504b2017-01-24 12:29:36 -050090
Robert Phillipsce3c28f2018-07-18 13:52:40 -040091 GrCoordTransform fCoordTransform;
92 TextureSampler fTextureSampler;
Brian Salomonaee504b2017-01-24 12:29:36 -050093 // TODO: Inline the kernel constants into the generated shader code. This may involve pulling
94 // some of the logic from SkGpuBlurUtils into this class related to radius/sigma calculations.
Robert Phillipsce3c28f2018-07-18 13:52:40 -040095 float fKernel[kMaxKernelWidth];
96 int fBounds[2];
97 int fRadius;
98 Direction fDirection;
wutao039a7c72017-06-30 10:44:45 -070099 GrTextureDomain::Mode fMode;
Brian Salomonaee504b2017-01-24 12:29:36 -0500100
Brian Salomonb133ffe2017-07-27 11:53:21 -0400101 typedef GrFragmentProcessor INHERITED;
Brian Salomonaee504b2017-01-24 12:29:36 -0500102};
103
104#endif