diff --git a/gn/gpu.gni b/gn/gpu.gni index 4139c4c6b6..1d4177359e 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -645,6 +645,8 @@ skia_metal_sources = [ "$_src/gpu/mtl/GrMtlRenderTarget.mm", "$_src/gpu/mtl/GrMtlResourceProvider.h", "$_src/gpu/mtl/GrMtlResourceProvider.mm", + "$_src/gpu/mtl/GrMtlSampler.h", + "$_src/gpu/mtl/GrMtlSampler.mm", "$_src/gpu/mtl/GrMtlTexture.h", "$_src/gpu/mtl/GrMtlTexture.mm", "$_src/gpu/mtl/GrMtlTextureRenderTarget.h", diff --git a/src/gpu/mtl/GrMtlSampler.h b/src/gpu/mtl/GrMtlSampler.h new file mode 100644 index 0000000000..8a24b9aba0 --- /dev/null +++ b/src/gpu/mtl/GrMtlSampler.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrMtlSampler_DEFINED +#define GrMtlSampler_DEFINED + +#import + +class GrSamplerState; +class GrMtlGpu; + +// This class only acts as a wrapper for a MTLSamplerState object for now, but will be more useful +// once we start caching sampler states. +class GrMtlSampler { +public: + static GrMtlSampler* Create(const GrMtlGpu* gpu, const GrSamplerState&, uint32_t maxMipLevel); + + id mtlSamplerState() const { return fMtlSamplerState; } + +private: + GrMtlSampler(id mtlSamplerState) : fMtlSamplerState(mtlSamplerState) {} + + id fMtlSamplerState; +}; + +#endif diff --git a/src/gpu/mtl/GrMtlSampler.mm b/src/gpu/mtl/GrMtlSampler.mm new file mode 100644 index 0000000000..54145fcb94 --- /dev/null +++ b/src/gpu/mtl/GrMtlSampler.mm @@ -0,0 +1,54 @@ +/* + * 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 "GrMtlSampler.h" + +#include "GrMtlGpu.h" + +static inline MTLSamplerAddressMode wrap_mode_to_mtl_sampler_address( + GrSamplerState::WrapMode wrapMode) { + switch (wrapMode) { + case GrSamplerState::WrapMode::kClamp: + return MTLSamplerAddressModeClampToEdge; + case GrSamplerState::WrapMode::kRepeat: + return MTLSamplerAddressModeRepeat; + case GrSamplerState::WrapMode::kMirrorRepeat: + return MTLSamplerAddressModeMirrorRepeat; + } + 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()); + samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY()); + samplerDesc.magFilter = mtlMinMagFilterModes[static_cast(samplerState.filter())]; + samplerDesc.minFilter = mtlMinMagFilterModes[static_cast(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; + samplerDesc.borderColor = MTLSamplerBorderColorTransparentBlack; + + return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc]); +}