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