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 or
27            // older MacOS builds will fail if it's referenced, even if other code makes sure it's
28            // never used.
29#ifdef SK_BUILD_FOR_MAC
30            if (@available(macOS 10.12, *)) {
31                SkASSERT(caps.clampToBorderSupport());
32                return MTLSamplerAddressModeClampToBorderColor;
33            } else
34#endif
35            {
36                SkASSERT(false);
37                return MTLSamplerAddressModeClampToEdge;
38            }
39    }
40    SK_ABORT("Unknown wrap mode.");
41}
42
43GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, const GrSamplerState& samplerState) {
44    static MTLSamplerMinMagFilter mtlMinMagFilterModes[] = {
45        MTLSamplerMinMagFilterNearest,
46        MTLSamplerMinMagFilterLinear,
47        MTLSamplerMinMagFilterLinear
48    };
49
50    GR_STATIC_ASSERT((int)GrSamplerState::Filter::kNearest == 0);
51    GR_STATIC_ASSERT((int)GrSamplerState::Filter::kBilerp == 1);
52    GR_STATIC_ASSERT((int)GrSamplerState::Filter::kMipMap == 2);
53
54    auto samplerDesc = [[MTLSamplerDescriptor alloc] init];
55    samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
56    samplerDesc.sAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeX(),
57                                                                gpu->mtlCaps());
58    samplerDesc.tAddressMode = wrap_mode_to_mtl_sampler_address(samplerState.wrapModeY(),
59                                                                gpu->mtlCaps());
60    samplerDesc.magFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
61    samplerDesc.minFilter = mtlMinMagFilterModes[static_cast<int>(samplerState.filter())];
62    samplerDesc.mipFilter = MTLSamplerMipFilterLinear;
63    samplerDesc.lodMinClamp = 0.0f;
64    bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter();
65    samplerDesc.lodMaxClamp = !useMipMaps ? 0.0f : 10000.0f;
66    samplerDesc.maxAnisotropy = 1.0f;
67    samplerDesc.normalizedCoordinates = true;
68    if (@available(macOS 10.11, iOS 9.0, *)) {
69        samplerDesc.compareFunction = MTLCompareFunctionNever;
70    }
71
72    return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc],
73                            GenerateKey(samplerState));
74}
75
76GrMtlSampler::Key GrMtlSampler::GenerateKey(const GrSamplerState& samplerState) {
77    return GrSamplerState::GenerateKey(samplerState);
78}
79