1/* 2 * Copyright 2018 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#include "src/gpu/ganesh/mtl/GrMtlSampler.h" 9 10#include "src/gpu/ganesh/mtl/GrMtlGpu.h" 11 12#if !__has_feature(objc_arc) 13#error This file must be compiled with Arc. Use -fobjc-arc flag 14#endif 15 16GR_NORETAIN_BEGIN 17 18static inline MTLSamplerAddressMode wrap_mode_to_mtl_sampler_address( 19 GrSamplerState::WrapMode wrapMode, const GrCaps& caps) { 20 switch (wrapMode) { 21 case GrSamplerState::WrapMode::kClamp: 22 return MTLSamplerAddressModeClampToEdge; 23 case GrSamplerState::WrapMode::kRepeat: 24 return MTLSamplerAddressModeRepeat; 25 case GrSamplerState::WrapMode::kMirrorRepeat: 26 return MTLSamplerAddressModeMirrorRepeat; 27 case GrSamplerState::WrapMode::kClampToBorder: 28 // Must guard the reference to the clamp to border address mode by macro since iOS or 29 // older MacOS builds will fail if it's referenced, even if other code makes sure it's 30 // never used. 31#ifdef SK_BUILD_FOR_MAC 32 if (@available(macOS 10.12, *)) { 33 SkASSERT(caps.clampToBorderSupport()); 34 return MTLSamplerAddressModeClampToBorderColor; 35 } else 36#endif 37 { 38 SkASSERT(false); 39 return MTLSamplerAddressModeClampToEdge; 40 } 41 } 42 SK_ABORT("Unknown wrap mode."); 43} 44 45GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, GrSamplerState samplerState) { 46 MTLSamplerMinMagFilter minMagFilter = [&] { 47 switch (samplerState.filter()) { 48 case GrSamplerState::Filter::kNearest: return MTLSamplerMinMagFilterNearest; 49 case GrSamplerState::Filter::kLinear: return MTLSamplerMinMagFilterLinear; 50 } 51 SkUNREACHABLE; 52 }(); 53 54 MTLSamplerMipFilter mipFilter = [&] { 55 switch (samplerState.mipmapMode()) { 56 case GrSamplerState::MipmapMode::kNone: return MTLSamplerMipFilterNotMipmapped; 57 case GrSamplerState::MipmapMode::kNearest: return MTLSamplerMipFilterNearest; 58 case GrSamplerState::MipmapMode::kLinear: return MTLSamplerMipFilterLinear; 59 } 60 SkUNREACHABLE; 61 }(); 62 63 auto samplerDesc = [[MTLSamplerDescriptor alloc] init]; 64 samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge; 65 samplerDesc.sAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeX(), 66 gpu->mtlCaps()); 67 samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(), 68 gpu->mtlCaps()); 69 samplerDesc.magFilter = minMagFilter; 70 samplerDesc.minFilter = minMagFilter; 71 samplerDesc.mipFilter = mipFilter; 72 samplerDesc.lodMinClamp = 0.0f; 73 samplerDesc.lodMaxClamp = FLT_MAX; // default value according to docs. 74 // Metal documents that maxAnisotropy must be between 1 and 16 inclusive. 75 samplerDesc.maxAnisotropy = std::min(samplerState.maxAniso(), 16); 76 samplerDesc.normalizedCoordinates = true; 77 if (@available(macOS 10.11, iOS 9.0, *)) { 78 samplerDesc.compareFunction = MTLCompareFunctionNever; 79 } 80 81 return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc], 82 GenerateKey(samplerState)); 83} 84 85GrMtlSampler::Key GrMtlSampler::GenerateKey(GrSamplerState samplerState) { 86 // We haven't found any documentation on how anisotropy interacts with other filter settings 87 // so assume they are all considered. 88 return samplerState.asKey(/*anisoIsOrthogonal=*/true); 89} 90 91GR_NORETAIN_END 92