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 "GrTextureDomain.h"
12#include "glsl/GrGLSLFragmentProcessor.h"
13
14class GrInvariantOutput;
15
16class GrBicubicEffect : public GrFragmentProcessor {
17public:
18    enum {
19        kFilterTexelPad = 2, // Given a src rect in texels to be filtered, this number of
20                             // surrounding texels are needed by the kernel in x and y.
21    };
22
23    const char* name() const override { return "Bicubic"; }
24
25    std::unique_ptr<GrFragmentProcessor> clone() const override {
26        return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(*this));
27    }
28
29    const GrTextureDomain& domain() const { return fDomain; }
30
31    /**
32     * Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
33     */
34    static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
35                                                     const SkMatrix& matrix,
36                                                     const GrSamplerState::WrapMode wrapModes[2]) {
37        return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(std::move(proxy), matrix,
38                                                                        wrapModes));
39    }
40
41    /**
42     * Create a Mitchell filter effect with a texture matrix and a domain.
43     */
44    static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
45                                                     const SkMatrix& matrix,
46                                                     const SkRect& domain) {
47        return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(std::move(proxy), matrix,
48                                                                        domain));
49    }
50
51    /**
52     * Determines whether the bicubic effect should be used based on the transformation from the
53     * local coords to the device. Returns true if the bicubic effect should be used. filterMode
54     * is set to appropriate filtering mode to use regardless of the return result (e.g. when this
55     * returns false it may indicate that the best fallback is to use kMipMap, kBilerp, or
56     * kNearest).
57     */
58    static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice,
59                                 GrSamplerState::Filter* filterMode);
60
61private:
62    GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix& matrix,
63                    const GrSamplerState::WrapMode wrapModes[2]);
64    GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix &matrix, const SkRect& domain);
65    explicit GrBicubicEffect(const GrBicubicEffect&);
66
67    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
68
69    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
70
71    bool onIsEqual(const GrFragmentProcessor&) const override;
72
73    GrCoordTransform fCoordTransform;
74    GrTextureDomain fDomain;
75    TextureSampler fTextureSampler;
76
77    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
78
79    typedef GrFragmentProcessor INHERITED;
80};
81
82#endif
83