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