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