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
16class GrTextureEffect : public GrFragmentProcessor {
17public:
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
73private:
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