1 | /* |
2 | * Copyright 2017 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 GrTextureEffect_DEFINED |
9 | #define GrTextureEffect_DEFINED |
10 | |
11 | #include "include/core/SkImageInfo.h" |
12 | #include "include/core/SkMatrix.h" |
13 | #include "src/gpu/GrCoordTransform.h" |
14 | #include "src/gpu/GrFragmentProcessor.h" |
15 | |
16 | class GrTextureEffect : public GrFragmentProcessor { |
17 | public: |
18 | static constexpr float kDefaultBorder[4] = {0}; |
19 | |
20 | /** Make from a filter. The sampler will be configured with clamp mode. */ |
21 | static std::unique_ptr<GrFragmentProcessor> Make( |
22 | GrSurfaceProxyView, |
23 | SkAlphaType, |
24 | const SkMatrix& = SkMatrix::I(), |
25 | GrSamplerState::Filter = GrSamplerState::Filter::kNearest); |
26 | |
27 | /** |
28 | * Make from a full GrSamplerState. Caps are required to determine support for kClampToBorder. |
29 | * This will be emulated in the shader if there is no hardware support. |
30 | */ |
31 | static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView, SkAlphaType, |
32 | const SkMatrix&, GrSamplerState, |
33 | const GrCaps& caps, |
34 | const float border[4] = kDefaultBorder); |
35 | |
36 | /** |
37 | * Makes a texture effect that samples a subset of a texture. The wrap modes of the |
38 | * GrSampleState are applied to the subset in the shader rather than using HW samplers. |
39 | * The 'subset' parameter specifies the texels in the base level. The shader code will |
40 | * avoid allowing bilerp filtering to read outside the texel window. However, if MIP |
41 | * filtering is used and a shader invocation reads from a level other than the base |
42 | * then it may read texel values that were computed from in part from base level texels |
43 | * outside the window. More specifically, we treat the MIP map case exactly like the |
44 | * bilerp case in terms of how the final texture coords are computed. |
45 | */ |
46 | static std::unique_ptr<GrFragmentProcessor> MakeSubset(GrSurfaceProxyView, |
47 | SkAlphaType, |
48 | const SkMatrix&, |
49 | GrSamplerState, |
50 | const SkRect& subset, |
51 | const GrCaps& caps, |
52 | const float border[4] = kDefaultBorder); |
53 | |
54 | /** |
55 | * The same as above but also takes a 'domain' that specifies any known limit on the post- |
56 | * matrix texture coords that will be used to sample the texture. Specifying this requires |
57 | * knowledge of how this effect will be nested into a paint, the local coords used with the |
58 | * draw, etc. It is only used to attempt to optimize away the shader subset calculations. |
59 | */ |
60 | static std::unique_ptr<GrFragmentProcessor> MakeSubset(GrSurfaceProxyView, |
61 | SkAlphaType, |
62 | const SkMatrix&, |
63 | GrSamplerState, |
64 | const SkRect& subset, |
65 | const SkRect& domain, |
66 | const GrCaps& caps, |
67 | const float border[4] = kDefaultBorder); |
68 | |
69 | std::unique_ptr<GrFragmentProcessor> clone() const override; |
70 | |
71 | const char* name() const override { return "TextureEffect" ; } |
72 | |
73 | private: |
74 | enum class ShaderMode : uint16_t { |
75 | kClamp = static_cast<int>(GrSamplerState::WrapMode::kClamp), |
76 | kRepeat = static_cast<int>(GrSamplerState::WrapMode::kRepeat), |
77 | kMirrorRepeat = static_cast<int>(GrSamplerState::WrapMode::kMirrorRepeat), |
78 | kClampToBorder = static_cast<int>(GrSamplerState::WrapMode::kClampToBorder), |
79 | kNone, |
80 | }; |
81 | |
82 | struct Sampling; |
83 | |
84 | /** |
85 | * Sometimes the implementation of a ShaderMode depends on which GrSamplerState::Filter is |
86 | * used. |
87 | */ |
88 | enum class FilterLogic { |
89 | kNone, // The shader isn't specialized for the filter. |
90 | kRepeatBilerp, // Filter across the subset boundary for kRepeat mode |
91 | kRepeatMipMap, // Logic for LOD selection with kRepeat mode. |
92 | kClampToBorderFilter, // Logic for fading to border color when filtering. |
93 | kClampToBorderNearest, // Logic for hard transition to border color when not filtering. |
94 | }; |
95 | static FilterLogic GetFilterLogic(ShaderMode mode, GrSamplerState::Filter filter); |
96 | |
97 | GrCoordTransform fCoordTransform; |
98 | TextureSampler fSampler; |
99 | float fBorder[4]; |
100 | SkRect fSubset; |
101 | SkRect fClamp; |
102 | ShaderMode fShaderModes[2]; |
103 | |
104 | inline GrTextureEffect(GrSurfaceProxyView, SkAlphaType, const SkMatrix&, const Sampling&); |
105 | |
106 | explicit GrTextureEffect(const GrTextureEffect& src); |
107 | |
108 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
109 | |
110 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
111 | |
112 | bool onIsEqual(const GrFragmentProcessor&) const override; |
113 | |
114 | const TextureSampler& onTextureSampler(int) const override; |
115 | |
116 | GR_DECLARE_FRAGMENT_PROCESSOR_TEST |
117 | |
118 | typedef GrFragmentProcessor INHERITED; |
119 | }; |
120 | #endif |
121 | |