• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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