1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef GrGaussianConvolutionFragmentProcessor_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrGaussianConvolutionFragmentProcessor_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrCoordTransform.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrFragmentProcessor.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextureDomain.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * A 1D Gaussian convolution effect. The kernel is computed as an array of 2 * half-width weights.
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Each texel is multiplied by it's weight and summed to determine the filtered color. The output
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * color is set to a modulation of the filtered and input colors.
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrGaussianConvolutionFragmentProcessor : public GrFragmentProcessor {
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum class Direction { kX, kY };
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /// Convolve with a Gaussian kernel
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     Direction dir,
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     int halfWidth,
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     float gaussianSigma,
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     GrTextureDomain::Mode mode,
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     int* bounds) {
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return std::unique_ptr<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::move(proxy), dir, halfWidth, gaussianSigma, mode, bounds));
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const float* kernel() const { return fKernel; }
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int* bounds() const { return fBounds; }
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool useBounds() const { return fMode != GrTextureDomain::kIgnore_Mode; }
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int radius() const { return fRadius; }
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int width() const { return 2 * fRadius + 1; }
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Direction direction() const { return fDirection; }
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTextureDomain::Mode mode() const { return fMode; }
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name() const override { return "GaussianConvolution"; }
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<GrFragmentProcessor> clone() const override {
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return std::unique_ptr<GrFragmentProcessor>(
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                new GrGaussianConvolutionFragmentProcessor(*this));
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This was decided based on the min allowed value for the max texture
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // on a blur filter gives a kernel width of 25 while a sigma of 5.0
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // would exceed a 32 wide kernel.
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kMaxKernelRadius = 12;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // With a C++11 we could have a constexpr version of WidthFromRadius()
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // and not have to duplicate this calculation.
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kMaxKernelWidth = 2 * kMaxKernelRadius + 1;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /// Convolve with a Gaussian kernel
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGaussianConvolutionFragmentProcessor(sk_sp<GrTextureProxy>, Direction,
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           int halfWidth, float gaussianSigma,
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           GrTextureDomain::Mode mode, int bounds[2]);
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&);
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onIsEqual(const GrFragmentProcessor&) const override;
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrCoordTransform fCoordTransform;
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextureSampler fTextureSampler;
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // TODO: Inline the kernel constants into the generated shader code. This may involve pulling
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // some of the logic from SkGpuBlurUtils into this class related to radius/sigma calculations.
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    float fKernel[kMaxKernelWidth];
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int   fBounds[2];
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fRadius;
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Direction fDirection;
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrTextureDomain::Mode fMode;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GrFragmentProcessor INHERITED;
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
91