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