blob: fdfda3092cf4a2c344d58504b0712fcbaceeaef1 [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/mtl/GrMtlSampler.h"
#include "src/gpu/mtl/GrMtlGpu.h"
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
static inline MTLSamplerAddressMode wrap_mode_to_mtl_sampler_address(
GrSamplerState::WrapMode wrapMode, const GrCaps& caps) {
switch (wrapMode) {
case GrSamplerState::WrapMode::kClamp:
return MTLSamplerAddressModeClampToEdge;
case GrSamplerState::WrapMode::kRepeat:
return MTLSamplerAddressModeRepeat;
case GrSamplerState::WrapMode::kMirrorRepeat:
return MTLSamplerAddressModeMirrorRepeat;
case GrSamplerState::WrapMode::kClampToBorder:
// Must guard the reference to the clamp to border address mode by macro since iOS
// builds will fail if it's referenced, even if other code makes sure it's never used.
#ifdef SK_BUILD_FOR_IOS
SkASSERT(false);
return MTLSamplerAddressModeClampToEdge;
#else
SkASSERT(caps.clampToBorderSupport());
return MTLSamplerAddressModeClampToBorderColor;
#endif
}
SK_ABORT("Unknown wrap mode.");
return MTLSamplerAddressModeClampToEdge;
}
GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, const GrSamplerState& samplerState,
uint32_t maxMipLevel) {
static MTLSamplerMinMagFilter mtlMinMagFilterModes[] = {
MTLSamplerMinMagFilterNearest,
MTLSamplerMinMagFilterLinear,
MTLSamplerMinMagFilterLinear
};
GR_STATIC_ASSERT((int)GrSamplerState::Filter::kNearest == 0);
GR_STATIC_ASSERT((int)GrSamplerState::Filter::kBilerp == 1);
GR_STATIC_ASSERT((int)GrSamplerState::Filter::kMipMap == 2);
auto samplerDesc = [[MTLSamplerDescriptor alloc] init];
samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
samplerDesc.sAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeX(),
gpu->mtlCaps());
samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(),
gpu->mtlCaps());
samplerDesc.magFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
samplerDesc.minFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
samplerDesc.mipFilter = MTLSamplerMipFilterLinear;
samplerDesc.lodMinClamp = 0.0f;
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter() && maxMipLevel > 0;
samplerDesc.lodMaxClamp = !useMipMaps ? 0.0f : (float)(maxMipLevel);
samplerDesc.maxAnisotropy = 1.0f;
samplerDesc.normalizedCoordinates = true;
samplerDesc.compareFunction = MTLCompareFunctionNever;
return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc],
GenerateKey(samplerState, maxMipLevel));
}
GrMtlSampler::Key GrMtlSampler::GenerateKey(const GrSamplerState& samplerState,
uint32_t maxMipLevel) {
const int kTileModeXShift = 2;
const int kTileModeYShift = 4;
const int kMipLevelShift = 6;
SkASSERT(static_cast<int>(samplerState.filter()) <= 3);
Key samplerKey = static_cast<uint16_t>(samplerState.filter());
SkASSERT(static_cast<int>(samplerState.wrapModeX()) <= 3);
samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeX()) << kTileModeXShift);
SkASSERT(static_cast<int>(samplerState.wrapModeY()) <= 3);
samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeY()) << kTileModeYShift);
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter() && maxMipLevel > 0;
samplerKey |= (!useMipMaps ? 0 : (uint16_t) maxMipLevel) << kMipLevelShift;
return samplerKey;
}