blob: 74e9a94c2d684fd50b9c301df441e325c95e6089 [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
Brian Salomonb133ffe2017-07-27 11:53:21 -040011#include "GrCoordTransform.h"
12#include "GrFragmentProcessor.h"
wutao039a7c72017-06-30 10:44:45 -070013#include "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
Robert Phillipsfbcef6e2017-06-15 12:07:18 -040025 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
Robert Phillips40fd7c92017-01-30 08:06:27 -050026 Direction dir,
27 int halfWidth,
28 float gaussianSigma,
wutao039a7c72017-06-30 10:44:45 -070029 GrTextureDomain::Mode mode,
Robert Phillips08c5ec72017-01-30 12:26:47 -050030 int* bounds) {
Robert Phillips40fd7c92017-01-30 08:06:27 -050031 return sk_sp<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
wutao039a7c72017-06-30 10:44:45 -070032 std::move(proxy), dir, halfWidth, gaussianSigma, mode, bounds));
Robert Phillips40fd7c92017-01-30 08:06:27 -050033 }
34
Brian Salomonaee504b2017-01-24 12:29:36 -050035 const float* kernel() const { return fKernel; }
36
Robert Phillips08c5ec72017-01-30 12:26:47 -050037 const int* bounds() const { return fBounds; }
wutao039a7c72017-06-30 10:44:45 -070038 bool useBounds() const { return fMode != GrTextureDomain::kIgnore_Mode; }
Brian Salomonb133ffe2017-07-27 11:53:21 -040039 int radius() const { return fRadius; }
40 int width() const { return 2 * fRadius + 1; }
41 Direction direction() const { return fDirection; }
wutao039a7c72017-06-30 10:44:45 -070042
43 GrTextureDomain::Mode mode() const { return fMode; }
Brian Salomonaee504b2017-01-24 12:29:36 -050044
45 const char* name() const override { return "GaussianConvolution"; }
46
Brian Salomon3f6f9652017-07-28 07:34:05 -040047 sk_sp<GrFragmentProcessor> clone() const override {
48 return sk_sp<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(*this));
49 }
50
Brian Salomonaee504b2017-01-24 12:29:36 -050051 // This was decided based on the min allowed value for the max texture
52 // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
53 // on a blur filter gives a kernel width of 25 while a sigma of 5.0
54 // would exceed a 32 wide kernel.
55 static const int kMaxKernelRadius = 12;
56 // With a C++11 we could have a constexpr version of WidthFromRadius()
57 // and not have to duplicate this calculation.
58 static const int kMaxKernelWidth = 2 * kMaxKernelRadius + 1;
59
60private:
61 /// Convolve with a Gaussian kernel
Robert Phillipsfbcef6e2017-06-15 12:07:18 -040062 GrGaussianConvolutionFragmentProcessor(sk_sp<GrTextureProxy>, Direction,
wutao039a7c72017-06-30 10:44:45 -070063 int halfWidth, float gaussianSigma,
64 GrTextureDomain::Mode mode, int bounds[2]);
Robert Phillips40fd7c92017-01-30 08:06:27 -050065
Brian Salomon3f6f9652017-07-28 07:34:05 -040066 explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&);
67
Brian Salomonaee504b2017-01-24 12:29:36 -050068 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
69
70 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
71
72 bool onIsEqual(const GrFragmentProcessor&) const override;
73
Brian Salomon0c26a9d2017-07-06 10:09:38 -040074 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
Brian Salomonaee504b2017-01-24 12:29:36 -050075
Brian Salomonb133ffe2017-07-27 11:53:21 -040076 GrCoordTransform fCoordTransform;
77 TextureSampler fTextureSampler;
Brian Salomonaee504b2017-01-24 12:29:36 -050078 // TODO: Inline the kernel constants into the generated shader code. This may involve pulling
79 // some of the logic from SkGpuBlurUtils into this class related to radius/sigma calculations.
80 float fKernel[kMaxKernelWidth];
Robert Phillips08c5ec72017-01-30 12:26:47 -050081 int fBounds[2];
Brian Salomonb133ffe2017-07-27 11:53:21 -040082 int fRadius;
83 Direction fDirection;
wutao039a7c72017-06-30 10:44:45 -070084 GrTextureDomain::Mode fMode;
Brian Salomonaee504b2017-01-24 12:29:36 -050085
Brian Salomonb133ffe2017-07-27 11:53:21 -040086 typedef GrFragmentProcessor INHERITED;
Brian Salomonaee504b2017-01-24 12:29:36 -050087};
88
89#endif