• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/gpu/effects/GrTextureDomain.h"
12 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
13 
14 class GrInvariantOutput;
15 
16 class GrBicubicEffect : public GrFragmentProcessor {
17 public:
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     enum class Direction {
24         /** Apply bicubic kernel in local coord x, nearest neighbor in y. */
25         kX,
26         /** Apply bicubic kernel in local coord y, nearest neighbor in x. */
27         kY,
28         /** Apply bicubic in both x and y. */
29         kXY
30     };
31 
name()32     const char* name() const override { return "Bicubic"; }
33 
clone()34     std::unique_ptr<GrFragmentProcessor> clone() const override {
35         return std::unique_ptr<GrFragmentProcessor>(new GrBicubicEffect(*this));
36     }
37 
domain()38     const GrTextureDomain& domain() const { return fDomain; }
39 
direction()40     Direction direction() const { return fDirection; }
41 
alphaType()42     SkAlphaType alphaType() const { return fAlphaType; }
43 
44     /**
45      * Create a Mitchell filter effect with specified texture matrix with clamp wrap mode.
46      */
Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,Direction direction,SkAlphaType alphaType)47     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
48                                                      const SkMatrix& matrix,
49                                                      Direction direction,
50                                                      SkAlphaType alphaType) {
51         static constexpr GrSamplerState::WrapMode kClampClamp[] = {
52                 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
53         return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kIgnore_Mode,
54                     GrTextureDomain::kIgnore_Mode, direction, alphaType);
55     }
56 
57     /**
58      * Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
59      */
Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const GrSamplerState::WrapMode wrapModes[2],Direction direction,SkAlphaType alphaType)60     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
61                                                      const SkMatrix& matrix,
62                                                      const GrSamplerState::WrapMode wrapModes[2],
63                                                      Direction direction,
64                                                      SkAlphaType alphaType) {
65         // Ignore the domain on x and y, since this factory relies solely on the wrap mode of the
66         // sampler to constrain texture coordinates
67         return Make(std::move(proxy), matrix, wrapModes, GrTextureDomain::kIgnore_Mode,
68                     GrTextureDomain::kIgnore_Mode, direction, alphaType);
69     }
70 
71     /**
72      * Create a Mitchell filter effect with specified texture matrix and x/y tile modes. This
73      * supports providing modes for the texture domain explicitly, in the event that it should
74      * override the behavior of the sampler's tile mode (e.g. clamp to border unsupported).
75      */
76     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
77                                                      const SkMatrix& matrix,
78                                                      const GrSamplerState::WrapMode wrapModes[2],
79                                                      GrTextureDomain::Mode modeX,
80                                                      GrTextureDomain::Mode modeY,
81                                                      Direction direction,
82                                                      SkAlphaType alphaType,
83                                                      const SkRect* domain = nullptr) {
84         SkRect resolvedDomain = domain ? *domain : GrTextureDomain::MakeTexelDomain(
85                 SkIRect::MakeWH(proxy->width(), proxy->height()), modeX, modeY);
86         return std::unique_ptr<GrFragmentProcessor>(
87                 new GrBicubicEffect(std::move(proxy), matrix, resolvedDomain, wrapModes, modeX,
88                                     modeY, direction, alphaType));
89     }
90 
91     /**
92      * Create a Mitchell filter effect with a texture matrix and a domain.
93      */
Make(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkRect & domain,Direction direction,SkAlphaType alphaType)94     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
95                                                      const SkMatrix& matrix,
96                                                      const SkRect& domain,
97                                                      Direction direction,
98                                                      SkAlphaType alphaType) {
99         static const GrSamplerState::WrapMode kClampClamp[] = {
100                 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
101         return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kClamp_Mode,
102                     GrTextureDomain::kClamp_Mode, direction, alphaType, &domain);
103     }
104 
105     /**
106      * Determines whether the bicubic effect should be used based on the transformation from the
107      * local coords to the device. Returns true if the bicubic effect should be used. filterMode
108      * is set to appropriate filtering mode to use regardless of the return result (e.g. when this
109      * returns false it may indicate that the best fallback is to use kMipMap, kBilerp, or
110      * kNearest).
111      */
112     static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice,
113                                  GrSamplerState::Filter* filterMode);
114 
115 private:
116     GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix& matrix, const SkRect& domain,
117                     const GrSamplerState::WrapMode wrapModes[2], GrTextureDomain::Mode modeX,
118                     GrTextureDomain::Mode modeY, Direction direction, SkAlphaType alphaType);
119     explicit GrBicubicEffect(const GrBicubicEffect&);
120 
121     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
122 
123     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
124 
125     bool onIsEqual(const GrFragmentProcessor&) const override;
126 
onTextureSampler(int)127     const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
128 
129     GrCoordTransform fCoordTransform;
130     GrTextureDomain fDomain;
131     TextureSampler fTextureSampler;
132     SkAlphaType fAlphaType;
133     Direction fDirection;
134 
135     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
136 
137     typedef GrFragmentProcessor INHERITED;
138 };
139 
140 #endif
141