1d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com/*
2d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com * Copyright 2012 Google Inc.
3d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com *
4d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
5d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com * found in the LICENSE file.
6d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com */
7d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
8d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com#ifndef GrConvolutionEffect_DEFINED
9d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com#define GrConvolutionEffect_DEFINED
10d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
11b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "Gr1DKernelEffect.h"
12d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
13ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.comclass GrGLConvolutionEffect;
14ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com
15b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com/**
16fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * A convolution effect. The kernel is specified as an array of 2 * half-width
17b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com * + 1 weights. Each texel is multiplied by it's weight and summed to determine
18b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com * the output color. The output color is modulated by the input color.
19b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com */
20b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comclass GrConvolutionEffect : public Gr1DKernelEffect {
21d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
22d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.compublic:
23d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
24fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com    /// Convolve with an arbitrary user-specified kernel
25b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrTexture* tex,
26b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       Direction dir,
27b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       int halfWidth,
28b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const float* kernel,
29b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       bool useBounds,
30b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       float bounds[2]) {
3155fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrConvolutionEffect, (tex,
3255fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                dir,
3355fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                halfWidth,
3455fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                kernel,
3555fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                useBounds,
3655fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                bounds));
370ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
38b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
39b4a55b7b68bf6b8ba8cb12927e5a627fab95ea5cbsalomon@google.com    /// Convolve with a Gaussian kernel
40b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* CreateGaussian(GrTexture* tex,
41b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               Direction dir,
42b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               int halfWidth,
43b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               float gaussianSigma,
44b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               bool useBounds,
45b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               float bounds[2]) {
4655fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrConvolutionEffect, (tex,
4755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                dir,
4855fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                halfWidth,
4955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                gaussianSigma,
5055fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                useBounds,
5155fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                bounds));
520ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
530ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
54fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com    virtual ~GrConvolutionEffect();
55b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
56ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com    const float* kernel() const { return fKernel; }
57289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com
58e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org    const float* bounds() const { return fBounds; }
59e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org    bool useBounds() const { return fUseBounds; }
60194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
61ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com    static const char* Name() { return "Convolution"; }
62ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com
63b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLConvolutionEffect GLProcessor;
64289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com
65b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
6668b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
67e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com    virtual void getConstantColorComponents(GrColor*, uint32_t* validFlags) const {
6868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        // If the texture was opaque we could know that the output color if we knew the sum of the
6968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        // kernel values.
7068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        *validFlags = 0;
7168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    }
72b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
73b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    enum {
74b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // This was decided based on the min allowed value for the max texture
75b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
76b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // on a blur filter gives a kernel width of 25 while a sigma of 5.0
77b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // would exceed a 32 wide kernel.
78b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        kMaxKernelRadius = 12,
79b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // With a C++11 we could have a constexpr version of WidthFromRadius()
80b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        // and not have to duplicate this calculation.
81b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com        kMaxKernelWidth = 2 * kMaxKernelRadius + 1,
82b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    };
83d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
84d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.comprotected:
85d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
86b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    float fKernel[kMaxKernelWidth];
87e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org    bool fUseBounds;
88e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org    float fBounds[2];
89d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
90d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.comprivate:
910ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    GrConvolutionEffect(GrTexture*, Direction,
92194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                        int halfWidth,
93194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                        const float* kernel,
94e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org                        bool useBounds,
95e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org                        float bounds[2]);
960ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
970ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    /// Convolve with a Gaussian kernel
980ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    GrConvolutionEffect(GrTexture*, Direction,
990ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                        int halfWidth,
100194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org                        float gaussianSigma,
101e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org                        bool useBounds,
102e8232bc6f0719f381d437483271ce3c78af3c819senorblanco@chromium.org                        float bounds[2]);
1030ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
104b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
10568b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
106b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
107d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
108b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com    typedef Gr1DKernelEffect INHERITED;
109d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com};
110d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
111d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com#endif
112