xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrSamplerState.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2015 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 GrSamplerState_DEFINED
9 #define GrSamplerState_DEFINED
10 
11 #include "include/core/SkSamplingOptions.h"
12 #include "include/gpu/GpuTypes.h"
13 #include "include/private/base/SkTPin.h"
14 #include "include/private/base/SkTo.h"
15 #include "src/base/SkMathPriv.h"
16 
17 #include <limits>
18 
19 /**
20  * Represents the filtering and tile modes used to access a texture.
21  */
22 class GrSamplerState {
23 public:
24     using Filter = SkFilterMode;
25     using MipmapMode = SkMipmapMode;
26 
27     enum class WrapMode : uint8_t {
28         kClamp,
29         kRepeat,
30         kMirrorRepeat,
31         kClampToBorder,
32         kLast = kClampToBorder
33     };
34 
35     static constexpr int kFilterCount     = static_cast<int>(Filter::kLast)     + 1;
36     static constexpr int kWrapModeCount   = static_cast<int>(WrapMode::kLast)   + 1;
37     static constexpr int kMipmapModeCount = static_cast<int>(MipmapMode::kLast) + 1;
38 
39     constexpr GrSamplerState() = default;
40 
41     constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter, MipmapMode mm = MipmapMode::kNone)
42             : fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter), fMipmapMode(mm) {}
43 
44     constexpr GrSamplerState(WrapMode wrapX,
45                              WrapMode wrapY,
46                              Filter filter,
47                              MipmapMode mm = MipmapMode::kNone)
48             : fWrapModes{wrapX, wrapY}, fFilter(filter), fMipmapMode(mm) {}
49 
50     constexpr GrSamplerState(const WrapMode wrapModes[2],
51                              Filter filter,
52                              MipmapMode mm = MipmapMode::kNone)
53             : fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter), fMipmapMode(mm) {}
54 
GrSamplerState(Filter filter)55     constexpr /*explicit*/ GrSamplerState(Filter filter) : fFilter(filter) {}
GrSamplerState(Filter filter,MipmapMode mm)56     constexpr GrSamplerState(Filter filter, MipmapMode mm) : fFilter(filter), fMipmapMode(mm) {}
57 
58     // We require 'viewIsMipped' for APIs that allow MIP filtering to be specified orthogonally
59     // to aniso.
Aniso(WrapMode wrapX,WrapMode wrapY,int maxAniso,skgpu::Mipmapped viewIsMipped)60     static constexpr GrSamplerState Aniso(WrapMode wrapX,
61                                           WrapMode wrapY,
62                                           int maxAniso,
63                                           skgpu::Mipmapped viewIsMipped) {
64         GrSamplerState sampler;
65         sampler.fWrapModes[0] = wrapX;
66         sampler.fWrapModes[1] = wrapY;
67         sampler.fMaxAniso     = SkTPin(maxAniso, 1, kMaxMaxAniso);
68         sampler.fFilter       = Filter::kLinear;
69         sampler.fMipmapMode   = viewIsMipped == skgpu::Mipmapped::kYes ? MipmapMode::kLinear
70                                                                        : MipmapMode::kNone;
71         return sampler;
72     }
73 
74     constexpr GrSamplerState(const GrSamplerState&) = default;
75 
76     constexpr GrSamplerState& operator=(const GrSamplerState&) = default;
77 
wrapModeX()78     constexpr WrapMode wrapModeX() const { return fWrapModes[0]; }
79 
wrapModeY()80     constexpr WrapMode wrapModeY() const { return fWrapModes[1]; }
81 
isRepeatedX()82     constexpr bool isRepeatedX() const {
83         return fWrapModes[0] == WrapMode::kRepeat || fWrapModes[0] == WrapMode::kMirrorRepeat;
84     }
85 
isRepeatedY()86     constexpr bool isRepeatedY() const {
87         return fWrapModes[1] == WrapMode::kRepeat || fWrapModes[1] == WrapMode::kMirrorRepeat;
88     }
89 
isRepeated()90     constexpr bool isRepeated() const {
91         return this->isRepeatedX() || this->isRepeatedY();
92     }
93 
filter()94     constexpr Filter filter() const { return fFilter; }
95 
mipmapMode()96     constexpr MipmapMode mipmapMode() const { return fMipmapMode; }
97 
mipmapped()98     constexpr skgpu::Mipmapped mipmapped() const {
99         return skgpu::Mipmapped(fMipmapMode != MipmapMode::kNone);
100     }
101 
maxAniso()102     int maxAniso() const { return fMaxAniso; }
isAniso()103     bool isAniso() const { return fMaxAniso > 1; }
104 
105     constexpr bool operator==(GrSamplerState that) const {
106         return fWrapModes[0] == that.fWrapModes[0] && fWrapModes[1] == that.fWrapModes[1] &&
107                fFilter == that.fFilter && fMipmapMode == that.fMipmapMode;
108     }
109 
110     constexpr bool operator!=(const GrSamplerState& that) const { return !(*this == that); }
111 
112     /**
113      * Turn the sampler state into an integer for use as a key. How that works for aniso depends
114      * on whether the underlying API defines aniso as orthogonal to other filter settings or
115      * as a replacement for them.
116      */
asKey(bool anisoIsOrthogonal)117     uint32_t asKey(bool anisoIsOrthogonal) const {
118         constexpr int kNumWrapBits       = SkNextLog2_portable(kWrapModeCount);
119         constexpr int kNumMaxAnisoBits   = SkNextLog2_portable(kMaxMaxAniso);
120         constexpr int kNumFilterBits     = SkNextLog2_portable(kFilterCount);
121         constexpr int kNumMipmapModeBits = SkNextLog2_portable(kMipmapModeCount);
122 
123         constexpr int kWrapXShift      = 0;
124         constexpr int kWrapYShift      = kWrapXShift    + kNumWrapBits;
125         constexpr int kMaxAnisoShift   = kWrapYShift    + kNumWrapBits;
126         constexpr int kFilterShift     = kMaxAnisoShift + kNumMaxAnisoBits;
127         constexpr int kMipmapModeShift = kFilterShift   + kNumFilterBits;
128 
129         static_assert(kMipmapModeShift + kNumMipmapModeBits <= 32);
130 
131         uint32_t key = (static_cast<uint32_t>(fWrapModes[0]) << kWrapXShift)
132                      | (static_cast<uint32_t>(fWrapModes[1]) << kWrapYShift)
133                      | (static_cast<uint32_t>(fMaxAniso)     << kMaxAnisoShift);
134         if (fMaxAniso == 1 || anisoIsOrthogonal) {
135             key |= (static_cast<uint32_t>(fFilter)     << kFilterShift)
136                 |  (static_cast<uint32_t>(fMipmapMode) << kMipmapModeShift);
137         }
138         return key;
139     }
140 
141 private:
142     // This is here to support turning the sampler state into a key. Presumably this is way larger
143     // than any HW limits. Also, WebGPU accepts this as an unsigned short.
144     static constexpr int kMaxMaxAniso = 1024;
145 
146     WrapMode   fWrapModes[2] = {WrapMode::kClamp, WrapMode::kClamp};
147     Filter     fFilter       = GrSamplerState::Filter::kNearest;
148     MipmapMode fMipmapMode   = GrSamplerState::MipmapMode::kNone;
149     int        fMaxAniso     = 1;
150 };
151 
152 #endif
153