/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrSamplerState_DEFINED #define GrSamplerState_DEFINED #include "include/core/SkSamplingOptions.h" #include "include/gpu/GpuTypes.h" #include "include/private/base/SkTPin.h" #include "include/private/base/SkTo.h" #include "src/base/SkMathPriv.h" #include /** * Represents the filtering and tile modes used to access a texture. */ class GrSamplerState { public: using Filter = SkFilterMode; using MipmapMode = SkMipmapMode; enum class WrapMode : uint8_t { kClamp, kRepeat, kMirrorRepeat, kClampToBorder, kLast = kClampToBorder }; static constexpr int kFilterCount = static_cast(Filter::kLast) + 1; static constexpr int kWrapModeCount = static_cast(WrapMode::kLast) + 1; static constexpr int kMipmapModeCount = static_cast(MipmapMode::kLast) + 1; constexpr GrSamplerState() = default; constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter, MipmapMode mm = MipmapMode::kNone) : fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter), fMipmapMode(mm) {} constexpr GrSamplerState(WrapMode wrapX, WrapMode wrapY, Filter filter, MipmapMode mm = MipmapMode::kNone) : fWrapModes{wrapX, wrapY}, fFilter(filter), fMipmapMode(mm) {} constexpr GrSamplerState(const WrapMode wrapModes[2], Filter filter, MipmapMode mm = MipmapMode::kNone) : fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter), fMipmapMode(mm) {} constexpr /*explicit*/ GrSamplerState(Filter filter) : fFilter(filter) {} constexpr GrSamplerState(Filter filter, MipmapMode mm) : fFilter(filter), fMipmapMode(mm) {} // We require 'viewIsMipped' for APIs that allow MIP filtering to be specified orthogonally // to aniso. static constexpr GrSamplerState Aniso(WrapMode wrapX, WrapMode wrapY, int maxAniso, skgpu::Mipmapped viewIsMipped) { GrSamplerState sampler; sampler.fWrapModes[0] = wrapX; sampler.fWrapModes[1] = wrapY; sampler.fMaxAniso = SkTPin(maxAniso, 1, kMaxMaxAniso); sampler.fFilter = Filter::kLinear; sampler.fMipmapMode = viewIsMipped == skgpu::Mipmapped::kYes ? MipmapMode::kLinear : MipmapMode::kNone; return sampler; } constexpr GrSamplerState(const GrSamplerState&) = default; constexpr GrSamplerState& operator=(const GrSamplerState&) = default; constexpr WrapMode wrapModeX() const { return fWrapModes[0]; } constexpr WrapMode wrapModeY() const { return fWrapModes[1]; } constexpr bool isRepeatedX() const { return fWrapModes[0] == WrapMode::kRepeat || fWrapModes[0] == WrapMode::kMirrorRepeat; } constexpr bool isRepeatedY() const { return fWrapModes[1] == WrapMode::kRepeat || fWrapModes[1] == WrapMode::kMirrorRepeat; } constexpr bool isRepeated() const { return this->isRepeatedX() || this->isRepeatedY(); } constexpr Filter filter() const { return fFilter; } constexpr MipmapMode mipmapMode() const { return fMipmapMode; } constexpr skgpu::Mipmapped mipmapped() const { return skgpu::Mipmapped(fMipmapMode != MipmapMode::kNone); } int maxAniso() const { return fMaxAniso; } bool isAniso() const { return fMaxAniso > 1; } constexpr bool operator==(GrSamplerState that) const { return fWrapModes[0] == that.fWrapModes[0] && fWrapModes[1] == that.fWrapModes[1] && fFilter == that.fFilter && fMipmapMode == that.fMipmapMode; } constexpr bool operator!=(const GrSamplerState& that) const { return !(*this == that); } /** * Turn the sampler state into an integer for use as a key. How that works for aniso depends * on whether the underlying API defines aniso as orthogonal to other filter settings or * as a replacement for them. */ uint32_t asKey(bool anisoIsOrthogonal) const { constexpr int kNumWrapBits = SkNextLog2_portable(kWrapModeCount); constexpr int kNumMaxAnisoBits = SkNextLog2_portable(kMaxMaxAniso); constexpr int kNumFilterBits = SkNextLog2_portable(kFilterCount); constexpr int kNumMipmapModeBits = SkNextLog2_portable(kMipmapModeCount); constexpr int kWrapXShift = 0; constexpr int kWrapYShift = kWrapXShift + kNumWrapBits; constexpr int kMaxAnisoShift = kWrapYShift + kNumWrapBits; constexpr int kFilterShift = kMaxAnisoShift + kNumMaxAnisoBits; constexpr int kMipmapModeShift = kFilterShift + kNumFilterBits; static_assert(kMipmapModeShift + kNumMipmapModeBits <= 32); uint32_t key = (static_cast(fWrapModes[0]) << kWrapXShift) | (static_cast(fWrapModes[1]) << kWrapYShift) | (static_cast(fMaxAniso) << kMaxAnisoShift); if (fMaxAniso == 1 || anisoIsOrthogonal) { key |= (static_cast(fFilter) << kFilterShift) | (static_cast(fMipmapMode) << kMipmapModeShift); } return key; } private: // This is here to support turning the sampler state into a key. Presumably this is way larger // than any HW limits. Also, WebGPU accepts this as an unsigned short. static constexpr int kMaxMaxAniso = 1024; WrapMode fWrapModes[2] = {WrapMode::kClamp, WrapMode::kClamp}; Filter fFilter = GrSamplerState::Filter::kNearest; MipmapMode fMipmapMode = GrSamplerState::MipmapMode::kNone; int fMaxAniso = 1; }; #endif