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/mtl/GrMtlSampler.h" 9 10#include "src/gpu/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 16static inline MTLSamplerAddressMode wrap_mode_to_mtl_sampler_address( 17 GrSamplerState::WrapMode wrapMode, const GrCaps& caps) { 18 switch (wrapMode) { 19 case GrSamplerState::WrapMode::kClamp: 20 return MTLSamplerAddressModeClampToEdge; 21 case GrSamplerState::WrapMode::kRepeat: 22 return MTLSamplerAddressModeRepeat; 23 case GrSamplerState::WrapMode::kMirrorRepeat: 24 return MTLSamplerAddressModeMirrorRepeat; 25 case GrSamplerState::WrapMode::kClampToBorder: 26 // Must guard the reference to the clamp to border address mode by macro since iOS 27 // builds will fail if it's referenced, even if other code makes sure it's never used. 28#ifdef SK_BUILD_FOR_IOS 29 SkASSERT(false); 30 return MTLSamplerAddressModeClampToEdge; 31#else 32 SkASSERT(caps.clampToBorderSupport()); 33 return MTLSamplerAddressModeClampToBorderColor; 34#endif 35 } 36 SK_ABORT("Unknown wrap mode."); 37} 38 39GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, const GrSamplerState& samplerState, 40 uint32_t maxMipLevel) { 41 static MTLSamplerMinMagFilter mtlMinMagFilterModes[] = { 42 MTLSamplerMinMagFilterNearest, 43 MTLSamplerMinMagFilterLinear, 44 MTLSamplerMinMagFilterLinear 45 }; 46 47 GR_STATIC_ASSERT((int)GrSamplerState::Filter::kNearest == 0); 48 GR_STATIC_ASSERT((int)GrSamplerState::Filter::kBilerp == 1); 49 GR_STATIC_ASSERT((int)GrSamplerState::Filter::kMipMap == 2); 50 51 auto samplerDesc = [[MTLSamplerDescriptor alloc] init]; 52 samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge; 53 samplerDesc.sAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeX(), 54 gpu->mtlCaps()); 55 samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(), 56 gpu->mtlCaps()); 57 samplerDesc.magFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())]; 58 samplerDesc.minFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())]; 59 samplerDesc.mipFilter = MTLSamplerMipFilterLinear; 60 samplerDesc.lodMinClamp = 0.0f; 61 bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter() && maxMipLevel > 0; 62 samplerDesc.lodMaxClamp = !useMipMaps ? 0.0f : (float)(maxMipLevel); 63 samplerDesc.maxAnisotropy = 1.0f; 64 samplerDesc.normalizedCoordinates = true; 65 samplerDesc.compareFunction = MTLCompareFunctionNever; 66 67 return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc], 68 GenerateKey(samplerState, maxMipLevel)); 69} 70 71GrMtlSampler::Key GrMtlSampler::GenerateKey(const GrSamplerState& samplerState, 72 uint32_t maxMipLevel) { 73 const int kTileModeXShift = 2; 74 const int kTileModeYShift = 4; 75 const int kMipLevelShift = 6; 76 77 SkASSERT(static_cast<int>(samplerState.filter()) <= 3); 78 Key samplerKey = static_cast<uint16_t>(samplerState.filter()); 79 80 SkASSERT(static_cast<int>(samplerState.wrapModeX()) <= 3); 81 samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeX()) << kTileModeXShift); 82 83 SkASSERT(static_cast<int>(samplerState.wrapModeY()) <= 3); 84 samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeY()) << kTileModeYShift); 85 86 bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter() && maxMipLevel > 0; 87 samplerKey |= (!useMipMaps ? 0 : (uint16_t) maxMipLevel) << kMipLevelShift; 88 89 return samplerKey; 90} 91