• 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/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