1/*
2 * Copyright 2013 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 GrBicubicTextureEffect_DEFINED
9#define GrBicubicTextureEffect_DEFINED
10
11#include "GrSingleTextureEffect.h"
12#include "GrTextureDomain.h"
13#include "gl/GrGLProcessor.h"
14
15class GrGLBicubicEffect;
16class GrInvariantOutput;
17
18class GrBicubicEffect : public GrSingleTextureEffect {
19public:
20    enum {
21        kFilterTexelPad = 2, // Given a src rect in texels to be filtered, this number of
22                             // surrounding texels are needed by the kernel in x and y.
23    };
24    virtual ~GrBicubicEffect();
25
26    const float* coefficients() const { return fCoefficients; }
27
28    const char* name() const override { return "Bicubic"; }
29
30    void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
31
32    GrGLFragmentProcessor* createGLInstance() const override;
33
34    const GrTextureDomain& domain() const { return fDomain; }
35
36    /**
37     * Create a simple filter effect with custom bicubic coefficients and optional domain.
38     */
39    static GrFragmentProcessor* Create(GrTexture* tex, const SkScalar coefficients[16],
40                            const SkRect* domain = NULL) {
41        if (NULL == domain) {
42            static const SkShader::TileMode kTileModes[] = { SkShader::kClamp_TileMode,
43                                                             SkShader::kClamp_TileMode };
44            return Create(tex, coefficients, GrCoordTransform::MakeDivByTextureWHMatrix(tex),
45                          kTileModes);
46        } else {
47            return SkNEW_ARGS(GrBicubicEffect, (tex, coefficients,
48                                                GrCoordTransform::MakeDivByTextureWHMatrix(tex),
49                                                *domain));
50        }
51    }
52
53    /**
54     * Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
55     */
56    static GrFragmentProcessor* Create(GrTexture* tex, const SkMatrix& matrix,
57                            SkShader::TileMode tileModes[2]) {
58        return Create(tex, gMitchellCoefficients, matrix, tileModes);
59    }
60
61    /**
62     * Create a filter effect with custom bicubic coefficients, the texture matrix, and the x/y
63     * tilemodes.
64     */
65    static GrFragmentProcessor* Create(GrTexture* tex, const SkScalar coefficients[16],
66                                       const SkMatrix& matrix,
67                                       const SkShader::TileMode tileModes[2]) {
68        return SkNEW_ARGS(GrBicubicEffect, (tex, coefficients, matrix, tileModes));
69    }
70
71    /**
72     * Create a Mitchell filter effect with a texture matrix and a domain.
73     */
74    static GrFragmentProcessor* Create(GrTexture* tex, const SkMatrix& matrix,
75                                       const SkRect& domain) {
76        return SkNEW_ARGS(GrBicubicEffect, (tex, gMitchellCoefficients, matrix, domain));
77    }
78
79    /**
80     * Determines whether the bicubic effect should be used based on the transformation from the
81     * local coords to the device. Returns true if the bicubic effect should be used. filterMode
82     * is set to appropriate filtering mode to use regardless of the return result (e.g. when this
83     * returns false it may indicate that the best fallback is to use kMipMap, kBilerp, or
84     * kNearest).
85     */
86    static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice,
87                                 GrTextureParams::FilterMode* filterMode);
88
89private:
90    GrBicubicEffect(GrTexture*, const SkScalar coefficients[16],
91                    const SkMatrix &matrix, const SkShader::TileMode tileModes[2]);
92    GrBicubicEffect(GrTexture*, const SkScalar coefficients[16],
93                    const SkMatrix &matrix, const SkRect& domain);
94    bool onIsEqual(const GrFragmentProcessor&) const override;
95
96    void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
97
98    float           fCoefficients[16];
99    GrTextureDomain fDomain;
100
101    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
102
103    static const SkScalar gMitchellCoefficients[16];
104
105    typedef GrSingleTextureEffect INHERITED;
106};
107
108#endif
109