1/*
2 * Copyright 2017 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/GrMtlCaps.h"
9
10#include "include/core/SkRect.h"
11#include "include/gpu/GrBackendSurface.h"
12#include "src/gpu/GrRenderTarget.h"
13#include "src/gpu/GrRenderTargetProxy.h"
14#include "src/gpu/GrShaderCaps.h"
15#include "src/gpu/GrSurfaceProxy.h"
16#include "src/gpu/mtl/GrMtlUtil.h"
17
18#if !__has_feature(objc_arc)
19#error This file must be compiled with Arc. Use -fobjc-arc flag
20#endif
21
22GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device,
23                     MTLFeatureSet featureSet)
24        : INHERITED(contextOptions) {
25    fShaderCaps.reset(new GrShaderCaps(contextOptions));
26
27    this->initFeatureSet(featureSet);
28    this->initGrCaps(device);
29    this->initShaderCaps();
30    this->initFormatTable();
31    this->initStencilFormat(device);
32
33    this->applyOptionsOverrides(contextOptions);
34    fShaderCaps->applyOptionsOverrides(contextOptions);
35
36    // The following are disabled due to the unfinished Metal backend, not because Metal itself
37    // doesn't support it.
38    fCrossContextTextureSupport = false; // GrMtlGpu::prepareTextureForCrossContextUsage() not impl
39}
40
41void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
42    // Mac OSX
43#ifdef SK_BUILD_FOR_MAC
44    if (@available(macOS 10.12, *)) {
45        if (MTLFeatureSet_OSX_GPUFamily1_v2 == featureSet) {
46            fPlatform = Platform::kMac;
47            fFamilyGroup = 1;
48            fVersion = 2;
49            return;
50        }
51    }
52    if (MTLFeatureSet_OSX_GPUFamily1_v1 == featureSet) {
53        fPlatform = Platform::kMac;
54        fFamilyGroup = 1;
55        fVersion = 1;
56        return;
57    }
58#endif
59
60    // iOS Family group 3
61#ifdef SK_BUILD_FOR_IOS
62    if (@available(iOS 10.0, *)) {
63        if (MTLFeatureSet_iOS_GPUFamily3_v2 == featureSet) {
64            fPlatform = Platform::kIOS;
65            fFamilyGroup = 3;
66            fVersion = 2;
67            return;
68        }
69    }
70    if (@available(iOS 9.0, *)) {
71        if (MTLFeatureSet_iOS_GPUFamily3_v1 == featureSet) {
72            fPlatform = Platform::kIOS;
73            fFamilyGroup = 3;
74            fVersion = 1;
75            return;
76        }
77    }
78
79    // iOS Family group 2
80    if (@available(iOS 10.0, *)) {
81        if (MTLFeatureSet_iOS_GPUFamily2_v3 == featureSet) {
82            fPlatform = Platform::kIOS;
83            fFamilyGroup = 2;
84            fVersion = 3;
85            return;
86        }
87    }
88    if (@available(iOS 9.0, *)) {
89        if (MTLFeatureSet_iOS_GPUFamily2_v2 == featureSet) {
90            fPlatform = Platform::kIOS;
91            fFamilyGroup = 2;
92            fVersion = 2;
93            return;
94        }
95    }
96    if (MTLFeatureSet_iOS_GPUFamily2_v1 == featureSet) {
97        fPlatform = Platform::kIOS;
98        fFamilyGroup = 2;
99        fVersion = 1;
100        return;
101    }
102
103    // iOS Family group 1
104    if (@available(iOS 10.0, *)) {
105        if (MTLFeatureSet_iOS_GPUFamily1_v3 == featureSet) {
106            fPlatform = Platform::kIOS;
107            fFamilyGroup = 1;
108            fVersion = 3;
109            return;
110        }
111    }
112    if (@available(iOS 9.0, *)) {
113        if (MTLFeatureSet_iOS_GPUFamily1_v2 == featureSet) {
114            fPlatform = Platform::kIOS;
115            fFamilyGroup = 1;
116            fVersion = 2;
117            return;
118        }
119    }
120    if (MTLFeatureSet_iOS_GPUFamily1_v1 == featureSet) {
121        fPlatform = Platform::kIOS;
122        fFamilyGroup = 1;
123        fVersion = 1;
124        return;
125    }
126#endif
127    // No supported feature sets were found
128    SK_ABORT("Requested an unsupported feature set");
129}
130
131bool GrMtlCaps::canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
132                              MTLPixelFormat srcFormat, int srcSampleCount,
133                              const SkIRect& srcRect, const SkIPoint& dstPoint,
134                              bool areDstSrcSameObj) const {
135    if (!dstFormat || dstFormat != srcFormat) {
136        return false;
137    }
138    if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) {
139        return false;
140    }
141    if (areDstSrcSameObj) {
142        SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
143                                            srcRect.width(), srcRect.height());
144        if (dstRect.intersect(srcRect)) {
145            return false;
146        }
147    }
148    return true;
149}
150
151bool GrMtlCaps::canCopyAsResolve(GrSurface* dst, int dstSampleCount,
152                                 GrSurface* src, int srcSampleCount,
153                                 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
154    if (dst == src) {
155        return false;
156    }
157    if (dst->backendFormat() != src->backendFormat()) {
158        return false;
159    }
160    if (dstSampleCount > 1 || srcSampleCount == 1 || !src->asRenderTarget()) {
161        return false;
162    }
163
164    // TODO: Support copying subrectangles
165    if (dstPoint != SkIPoint::Make(0, 0)) {
166        return false;
167    }
168    if (srcRect != SkIRect::MakeXYWH(0, 0, src->width(), src->height())) {
169        return false;
170    }
171
172    return true;
173}
174
175bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
176                                 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
177    int dstSampleCnt = 0;
178    int srcSampleCnt = 0;
179    if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
180        dstSampleCnt = rtProxy->numSamples();
181    }
182    if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
183        srcSampleCnt = rtProxy->numSamples();
184    }
185    SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
186    SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
187
188    return this->canCopyAsBlit(GrBackendFormatAsMTLPixelFormat(dst->backendFormat()), dstSampleCnt,
189                               GrBackendFormatAsMTLPixelFormat(src->backendFormat()), srcSampleCnt,
190                               srcRect, dstPoint, dst == src);
191}
192
193void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
194    // Max vertex attribs is the same on all devices
195    fMaxVertexAttributes = 31;
196
197    // Metal does not support scissor + clear
198    fPerformPartialClearsAsDraws = true;
199
200    // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
201    fReadPixelsRowBytesSupport = true;
202    fWritePixelsRowBytesSupport = true;
203
204    // RenderTarget and Texture size
205    if (this->isMac()) {
206        fMaxRenderTargetSize = 16384;
207    } else {
208        if (3 == fFamilyGroup) {
209            fMaxRenderTargetSize = 16384;
210        } else {
211            // Family group 1 and 2 support 8192 for version 2 and above, 4096 for v1
212            if (1 == fVersion) {
213                fMaxRenderTargetSize = 4096;
214            } else {
215                fMaxRenderTargetSize = 8192;
216            }
217        }
218    }
219    fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
220    fMaxTextureSize = fMaxRenderTargetSize;
221
222    // Init sample counts. All devices support 1 (i.e. 0 in skia).
223    fSampleCounts.push_back(1);
224    if (@available(iOS 9.0, *)) {
225        for (auto sampleCnt : {2, 4, 8}) {
226            if ([device supportsTextureSampleCount:sampleCnt]) {
227                fSampleCounts.push_back(sampleCnt);
228            }
229        }
230    }
231
232    // Clamp to border is supported on Mac 10.12 and higher. It is not supported on iOS.
233    fClampToBorderSupport = false;
234#ifdef SK_BUILD_FOR_MAC
235    if (@available(macOS 10.12, *)) {
236        fClampToBorderSupport = true;
237    }
238#endif
239
240    // Starting with the assumption that there isn't a reason to not map small buffers.
241    fBufferMapThreshold = 0;
242
243    // Buffers are always fully mapped.
244    fMapBufferFlags =  kCanMap_MapFlag | kAsyncRead_MapFlag;
245
246    fOversizedStencilSupport = true;
247
248    fMipMapSupport = true;   // always available in Metal
249    fNPOTTextureTileSupport = true;  // always available in Metal
250
251    fReuseScratchTextures = true; // Assuming this okay
252
253    fTransferBufferSupport = true;
254
255    fTextureBarrierSupport = false; // Need to figure out if we can do this
256
257    fSampleLocationsSupport = false;
258    fMultisampleDisableSupport = false;
259
260    if (@available(macOS 10.11, iOS 9.0, *)) {
261        if (this->isMac() || 3 == fFamilyGroup) {
262            fInstanceAttribSupport = true;
263        }
264    }
265
266    fMixedSamplesSupport = false;
267    fGpuTracingSupport = false;
268
269    fFenceSyncSupport = true;
270    bool supportsMTLEvent = false;
271    if (@available(macOS 10.14, iOS 12.0, *)) {
272        supportsMTLEvent = true;
273    }
274    fSemaphoreSupport = supportsMTLEvent;
275
276    fCrossContextTextureSupport = false;
277    fHalfFloatVertexAttributeSupport = true;
278}
279
280static bool format_is_srgb(MTLPixelFormat format) {
281    switch (format) {
282        case MTLPixelFormatRGBA8Unorm_sRGB:
283        case MTLPixelFormatBGRA8Unorm_sRGB:
284            return true;
285        default:
286            return false;
287    }
288}
289
290bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const {
291    return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format));
292}
293
294bool GrMtlCaps::isFormatCompressed(const GrBackendFormat& format,
295                                  SkImage::CompressionType* compressionType) const {
296#ifdef SK_BUILD_FOR_MAC
297    return false;
298#else
299    SkImage::CompressionType dummyType;
300    SkImage::CompressionType* compressionTypePtr = compressionType ? compressionType : &dummyType;
301
302    switch (GrBackendFormatAsMTLPixelFormat(format)) {
303        case MTLPixelFormatETC2_RGB8:
304            // ETC2 uses the same compression layout as ETC1
305            *compressionTypePtr = SkImage::kETC1_CompressionType;
306            return true;
307        default:
308            return false;
309    }
310#endif
311}
312
313bool GrMtlCaps::isFormatTexturableAndUploadable(GrColorType ct,
314                                                const GrBackendFormat& format) const {
315    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
316
317    uint32_t ctFlags = this->getFormatInfo(mtlFormat).colorTypeFlags(ct);
318    return this->isFormatTexturable(mtlFormat) &&
319           SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag);
320}
321
322bool GrMtlCaps::isFormatTexturable(const GrBackendFormat& format) const {
323    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
324    return this->isFormatTexturable(mtlFormat);
325}
326
327bool GrMtlCaps::isFormatTexturable(MTLPixelFormat format) const {
328    const FormatInfo& formatInfo = this->getFormatInfo(format);
329    return SkToBool(FormatInfo::kTexturable_Flag && formatInfo.fFlags);
330}
331
332bool GrMtlCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
333                                              int sampleCount) const {
334    if (!this->isFormatRenderable(format, sampleCount)) {
335        return false;
336    }
337    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
338    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
339    const auto& info = this->getFormatInfo(mtlFormat);
340    if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
341        return false;
342    }
343    return true;
344}
345
346bool GrMtlCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
347    return this->isFormatRenderable(GrBackendFormatAsMTLPixelFormat(format), sampleCount);
348}
349
350bool GrMtlCaps::isFormatRenderable(MTLPixelFormat format, int sampleCount) const {
351    return sampleCount <= this->maxRenderTargetSampleCount(format);
352}
353
354int GrMtlCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
355    return this->maxRenderTargetSampleCount(GrBackendFormatAsMTLPixelFormat(format));
356}
357
358int GrMtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const {
359    const FormatInfo& formatInfo = this->getFormatInfo(format);
360    if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) {
361        return fSampleCounts[fSampleCounts.count() - 1];
362    } else if (formatInfo.fFlags & FormatInfo::kRenderable_Flag) {
363        return 1;
364    }
365    return 0;
366}
367
368int GrMtlCaps::getRenderTargetSampleCount(int requestedCount,
369                                          const GrBackendFormat& format) const {
370    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
371
372    return this->getRenderTargetSampleCount(requestedCount, mtlFormat);
373}
374
375int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, MTLPixelFormat format) const {
376    requestedCount = SkTMax(requestedCount, 1);
377    const FormatInfo& formatInfo = this->getFormatInfo(format);
378    if (!(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) {
379        return 0;
380    }
381    if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) {
382        int count = fSampleCounts.count();
383        for (int i = 0; i < count; ++i) {
384            if (fSampleCounts[i] >= requestedCount) {
385                return fSampleCounts[i];
386            }
387        }
388    }
389    return 1 == requestedCount ? 1 : 0;
390}
391
392size_t GrMtlCaps::bytesPerPixel(const GrBackendFormat& format) const {
393    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
394    return this->bytesPerPixel(mtlFormat);
395}
396
397size_t GrMtlCaps::bytesPerPixel(MTLPixelFormat format) const {
398    return this->getFormatInfo(format).fBytesPerPixel;
399}
400
401void GrMtlCaps::initShaderCaps() {
402    GrShaderCaps* shaderCaps = fShaderCaps.get();
403
404    // Setting this true with the assumption that this cap will eventually mean we support varying
405    // precisions and not just via modifiers.
406    shaderCaps->fUsesPrecisionModifiers = true;
407    shaderCaps->fFlatInterpolationSupport = true;
408    // We haven't yet tested that using flat attributes perform well.
409    shaderCaps->fPreferFlatInterpolation = true;
410
411    shaderCaps->fShaderDerivativeSupport = true;
412    shaderCaps->fGeometryShaderSupport = false;
413
414    if (@available(macOS 10.12, iOS 11.0, *)) {
415        shaderCaps->fDualSourceBlendingSupport = true;
416    } else {
417        shaderCaps->fDualSourceBlendingSupport = false;
418    }
419
420    // TODO: Re-enable this once skbug:8720 is fixed. Will also need to remove asserts in
421    // GrMtlPipelineStateBuilder which assert we aren't using this feature.
422#if 0
423    if (this->isIOS()) {
424        shaderCaps->fFBFetchSupport = true;
425        shaderCaps->fFBFetchNeedsCustomOutput = true; // ??
426        shaderCaps->fFBFetchColorName = ""; // Somehow add [[color(0)]] to arguments to frag shader
427    }
428#endif
429    shaderCaps->fDstReadInShaderSupport = shaderCaps->fFBFetchSupport;
430
431    shaderCaps->fIntegerSupport = true;
432    shaderCaps->fVertexIDSupport = false;
433
434    // Metal uses IEEE float and half floats so assuming those values here.
435    shaderCaps->fFloatIs32Bits = true;
436    shaderCaps->fHalfIs32Bits = false;
437
438    shaderCaps->fMaxFragmentSamplers = 16;
439}
440
441// These are all the valid MTLPixelFormats that we support in Skia.  They are roughly ordered from
442// most frequently used to least to improve look up times in arrays.
443static constexpr MTLPixelFormat kMtlFormats[] = {
444    MTLPixelFormatRGBA8Unorm,
445    MTLPixelFormatR8Unorm,
446    MTLPixelFormatA8Unorm,
447    MTLPixelFormatBGRA8Unorm,
448#ifdef SK_BUILD_FOR_IOS
449    MTLPixelFormatB5G6R5Unorm,
450#endif
451    MTLPixelFormatRGBA16Float,
452    MTLPixelFormatR16Float,
453    MTLPixelFormatRG8Unorm,
454    MTLPixelFormatRGB10A2Unorm,
455#ifdef SK_BUILD_FOR_IOS
456    MTLPixelFormatABGR4Unorm,
457#endif
458    MTLPixelFormatRGBA8Unorm_sRGB,
459    MTLPixelFormatR16Unorm,
460    MTLPixelFormatRG16Unorm,
461#ifdef SK_BUILD_FOR_IOS
462    MTLPixelFormatETC2_RGB8,
463#endif
464    MTLPixelFormatRGBA16Unorm,
465    MTLPixelFormatRG16Float,
466
467    MTLPixelFormatInvalid,
468};
469
470void GrMtlCaps::setColorType(GrColorType colorType, std::initializer_list<MTLPixelFormat> formats) {
471#ifdef SK_DEBUG
472    for (size_t i = 0; i < kNumMtlFormats; ++i) {
473        const auto& formatInfo = fFormatTable[i];
474        for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
475            const auto& ctInfo = formatInfo.fColorTypeInfos[j];
476            if (ctInfo.fColorType == colorType) {
477                bool found = false;
478                for (auto it = formats.begin(); it != formats.end(); ++it) {
479                    if (kMtlFormats[i] == *it) {
480                        found = true;
481                    }
482                }
483                SkASSERT(found);
484            }
485        }
486    }
487#endif
488    int idx = static_cast<int>(colorType);
489    for (auto it = formats.begin(); it != formats.end(); ++it) {
490        const auto& info = this->getFormatInfo(*it);
491        for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
492            if (info.fColorTypeInfos[i].fColorType == colorType) {
493                fColorTypeToFormatTable[idx] = *it;
494                return;
495            }
496        }
497    }
498}
499
500size_t GrMtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) {
501    static_assert(SK_ARRAY_COUNT(kMtlFormats) == GrMtlCaps::kNumMtlFormats,
502                  "Size of kMtlFormats array must match static value in header");
503    for (size_t i = 0; i < GrMtlCaps::kNumMtlFormats; ++i) {
504        if (kMtlFormats[i] == pixelFormat) {
505            return i;
506        }
507    }
508    SK_ABORT("Invalid MTLPixelFormat");
509}
510
511void GrMtlCaps::initFormatTable() {
512    FormatInfo* info;
513
514    // Format: R8Unorm
515    {
516        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR8Unorm)];
517        info->fFlags = FormatInfo::kAllFlags;
518        info->fBytesPerPixel = 1;
519        info->fColorTypeInfoCount = 2;
520        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
521        int ctIdx = 0;
522        // Format: R8Unorm, Surface: kAlpha_8
523        {
524            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
525            ctInfo.fColorType = GrColorType::kAlpha_8;
526            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
527            ctInfo.fTextureSwizzle = GrSwizzle::RRRR();
528            ctInfo.fOutputSwizzle = GrSwizzle::AAAA();
529        }
530        // Format: R8Unorm, Surface: kGray_8
531        {
532            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
533            ctInfo.fColorType = GrColorType::kGray_8;
534            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
535            ctInfo.fTextureSwizzle = GrSwizzle("rrr1");
536        }
537    }
538
539    // Format: A8Unorm
540    {
541        info = &fFormatTable[GetFormatIndex(MTLPixelFormatA8Unorm)];
542        info->fFlags = FormatInfo::kTexturable_Flag;
543        info->fBytesPerPixel = 1;
544        info->fColorTypeInfoCount = 1;
545        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
546        int ctIdx = 0;
547        // Format: A8Unorm, Surface: kAlpha_8
548        {
549            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
550            ctInfo.fColorType = GrColorType::kAlpha_8;
551            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
552            ctInfo.fTextureSwizzle = GrSwizzle::AAAA();
553        }
554    }
555
556#ifdef SK_BUILD_FOR_IOS
557    // Format: B5G6R5Unorm
558    {
559        info = &fFormatTable[GetFormatIndex(MTLPixelFormatB5G6R5Unorm)];
560        info->fFlags = FormatInfo::kAllFlags;
561        info->fBytesPerPixel = 2;
562        info->fColorTypeInfoCount = 1;
563        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
564        int ctIdx = 0;
565        // Format: B5G6R5Unorm, Surface: kBGR_565
566        {
567            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
568            ctInfo.fColorType = GrColorType::kBGR_565;
569            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
570        }
571    }
572
573    // Format: ABGR4Unorm
574    {
575        info = &fFormatTable[GetFormatIndex(MTLPixelFormatABGR4Unorm)];
576        info->fFlags = FormatInfo::kAllFlags;
577        info->fBytesPerPixel = 2;
578        info->fColorTypeInfoCount = 1;
579        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
580        int ctIdx = 0;
581        // Format: ABGR4Unorm, Surface: kABGR_4444
582        {
583            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
584            ctInfo.fColorType = GrColorType::kABGR_4444;
585            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
586        }
587    }
588#endif
589
590    // Format: RGBA8Unorm
591    {
592        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)];
593        info->fFlags = FormatInfo::kAllFlags;
594        info->fBytesPerPixel = 4;
595        info->fColorTypeInfoCount = 2;
596        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
597        int ctIdx = 0;
598        // Format: RGBA8Unorm, Surface: kRGBA_8888
599        {
600            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
601            ctInfo.fColorType = GrColorType::kRGBA_8888;
602            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
603        }
604        // Format: RGBA8Unorm, Surface: kRGB_888x
605        {
606            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
607            ctInfo.fColorType = GrColorType::kRGB_888x;
608            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
609            ctInfo.fTextureSwizzle = GrSwizzle::RGB1();
610        }
611    }
612
613    // Format: RG8Unorm
614    {
615        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG8Unorm)];
616        info->fFlags = FormatInfo::kTexturable_Flag;
617        info->fBytesPerPixel = 2;
618        info->fColorTypeInfoCount = 1;
619        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
620        int ctIdx = 0;
621        // Format: RG8Unorm, Surface: kRG_88
622        {
623            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
624            ctInfo.fColorType = GrColorType::kRG_88;
625            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
626        }
627    }
628
629    // Format: BGRA8Unorm
630    {
631        info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)];
632        info->fFlags = FormatInfo::kAllFlags;
633        info->fBytesPerPixel = 4;
634        info->fColorTypeInfoCount = 1;
635        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
636        int ctIdx = 0;
637        // Format: BGRA8Unorm, Surface: kBGRA_8888
638        {
639            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
640            ctInfo.fColorType = GrColorType::kBGRA_8888;
641            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
642        }
643    }
644
645    // Format: RGBA8Unorm_sRGB
646    {
647        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm_sRGB)];
648        info->fFlags = FormatInfo::kAllFlags;
649        info->fBytesPerPixel = 4;
650        info->fColorTypeInfoCount = 1;
651        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
652        int ctIdx = 0;
653        // Format: RGBA8Unorm_sRGB, Surface: kRGBA_8888_SRGB
654        {
655            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
656            ctInfo.fColorType = GrColorType::kRGBA_8888_SRGB;
657            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
658        }
659    }
660
661    // Format: RGB10A2Unorm
662    {
663        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGB10A2Unorm)];
664        if (this->isMac() || fFamilyGroup >= 3) {
665            info->fFlags = FormatInfo::kAllFlags;
666        } else {
667            info->fFlags = FormatInfo::kTexturable_Flag;
668        }
669        info->fBytesPerPixel = 4;
670        info->fColorTypeInfoCount = 1;
671        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
672        int ctIdx = 0;
673        // Format: RGB10A2Unorm, Surface: kRGBA_1010102
674        {
675            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
676            ctInfo.fColorType = GrColorType::kRGBA_1010102;
677            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
678        }
679    }
680
681    // Format: R16Float
682    {
683        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Float)];
684        info->fFlags = FormatInfo::kAllFlags;
685        info->fBytesPerPixel = 2;
686        info->fColorTypeInfoCount = 1;
687        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
688        int ctIdx = 0;
689        // Format: R16Float, Surface: kAlpha_F16
690        {
691            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
692            ctInfo.fColorType = GrColorType::kAlpha_F16;
693            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
694            ctInfo.fTextureSwizzle = GrSwizzle::RRRR();
695            ctInfo.fOutputSwizzle = GrSwizzle::AAAA();
696        }
697    }
698
699    // Format: RGBA16Float
700    {
701        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Float)];
702        info->fFlags = FormatInfo::kAllFlags;
703        info->fBytesPerPixel = 8;
704        info->fColorTypeInfoCount = 2;
705        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
706        int ctIdx = 0;
707        // Format: RGBA16Float, Surface: kRGBA_F16
708        {
709            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
710            ctInfo.fColorType = GrColorType::kRGBA_F16;
711            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
712        }
713        // Format: RGBA16Float, Surface: kRGBA_F16_Clamped
714        {
715            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
716            ctInfo.fColorType = GrColorType::kRGBA_F16_Clamped;
717            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
718        }
719    }
720
721    // Format: R16Unorm
722    {
723        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Unorm)];
724        if (this->isMac()) {
725            info->fFlags = FormatInfo::kAllFlags;
726        } else {
727            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
728        }
729        info->fBytesPerPixel = 2;
730        info->fColorTypeInfoCount = 1;
731        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
732        int ctIdx = 0;
733        // Format: R16Unorm, Surface: kAlpha_16
734        {
735            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
736            ctInfo.fColorType = GrColorType::kAlpha_16;
737            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
738            ctInfo.fTextureSwizzle = GrSwizzle::RRRR();
739            ctInfo.fOutputSwizzle = GrSwizzle::AAAA();
740        }
741    }
742
743    // Format: RG16Unorm
744    {
745        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Unorm)];
746        if (this->isMac()) {
747            info->fFlags = FormatInfo::kAllFlags;
748        } else {
749            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
750        }
751        info->fBytesPerPixel = 4;
752        info->fColorTypeInfoCount = 1;
753        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
754        int ctIdx = 0;
755        // Format: RG16Unorm, Surface: kRG_1616
756        {
757            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
758            ctInfo.fColorType = GrColorType::kRG_1616;
759            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
760        }
761    }
762
763#ifdef SK_BUILD_FOR_IOS
764    // ETC2_RGB8
765    info = &fFormatTable[GetFormatIndex(MTLPixelFormatETC2_RGB8)];
766    info->fFlags = FormatInfo::kTexturable_Flag;
767    // NO supported colorTypes
768#endif
769
770    // Format: RGBA16Unorm
771    {
772        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Unorm)];
773        if (this->isMac()) {
774            info->fFlags = FormatInfo::kAllFlags;
775        } else {
776            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
777        }
778        info->fBytesPerPixel = 8;
779        info->fColorTypeInfoCount = 1;
780        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
781        int ctIdx = 0;
782        // Format: RGBA16Unorm, Surface: kRGBA_16161616
783        {
784            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
785            ctInfo.fColorType = GrColorType::kRGBA_16161616;
786            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
787        }
788    }
789
790    // Format: RG16Float
791    {
792        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Float)];
793        info->fFlags = FormatInfo::kAllFlags;
794        info->fBytesPerPixel = 4;
795        info->fColorTypeInfoCount = 1;
796        info->fColorTypeInfos.reset(new ColorTypeInfo[info->fColorTypeInfoCount]());
797        int ctIdx = 0;
798        // Format: RG16Float, Surface: kRG_F16
799        {
800            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
801            ctInfo.fColorType = GrColorType::kRG_F16;
802            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
803        }
804    }
805
806    ////////////////////////////////////////////////////////////////////////////
807    // Map GrColorTypes (used for creating GrSurfaces) to MTLPixelFormats. The order in which the
808    // formats are passed into the setColorType function indicates the priority in selecting which
809    // format we use for a given GrcolorType.
810
811    std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, MTLPixelFormatInvalid);
812
813    this->setColorType(GrColorType::kAlpha_8,          { MTLPixelFormatR8Unorm,
814                                                         MTLPixelFormatA8Unorm });
815#ifdef SK_BUILD_FOR_IOS
816    this->setColorType(GrColorType::kBGR_565,          { MTLPixelFormatB5G6R5Unorm });
817    this->setColorType(GrColorType::kABGR_4444,        { MTLPixelFormatABGR4Unorm });
818#endif
819    this->setColorType(GrColorType::kRGBA_8888,        { MTLPixelFormatRGBA8Unorm });
820    this->setColorType(GrColorType::kRGBA_8888_SRGB,   { MTLPixelFormatRGBA8Unorm_sRGB });
821    this->setColorType(GrColorType::kRGB_888x,         { MTLPixelFormatRGBA8Unorm });
822    this->setColorType(GrColorType::kRG_88,            { MTLPixelFormatRG8Unorm });
823    this->setColorType(GrColorType::kBGRA_8888,        { MTLPixelFormatBGRA8Unorm });
824    this->setColorType(GrColorType::kRGBA_1010102,     { MTLPixelFormatRGB10A2Unorm });
825    this->setColorType(GrColorType::kGray_8,           { MTLPixelFormatR8Unorm });
826    this->setColorType(GrColorType::kAlpha_F16,        { MTLPixelFormatR16Float });
827    this->setColorType(GrColorType::kRGBA_F16,         { MTLPixelFormatRGBA16Float });
828    this->setColorType(GrColorType::kRGBA_F16_Clamped, { MTLPixelFormatRGBA16Float });
829    this->setColorType(GrColorType::kAlpha_16,         { MTLPixelFormatR16Unorm });
830    this->setColorType(GrColorType::kRG_1616,          { MTLPixelFormatRG16Unorm });
831    this->setColorType(GrColorType::kRGBA_16161616,    { MTLPixelFormatRGBA16Unorm });
832    this->setColorType(GrColorType::kRG_F16,           { MTLPixelFormatRG16Float });
833}
834
835void GrMtlCaps::initStencilFormat(id<MTLDevice> physDev) {
836    fPreferredStencilFormat = StencilFormat{ MTLPixelFormatStencil8, 8, 8, true };
837}
838
839bool GrMtlCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
840    if (auto rt = surface->asRenderTarget()) {
841        return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
842    }
843    return true;
844}
845
846static constexpr GrPixelConfig validate_sized_format(GrMTLPixelFormat grFormat, GrColorType ct) {
847    MTLPixelFormat format = static_cast<MTLPixelFormat>(grFormat);
848    switch (ct) {
849        case GrColorType::kUnknown:
850            return kUnknown_GrPixelConfig;
851        case GrColorType::kAlpha_8:
852            if (MTLPixelFormatA8Unorm == format) {
853                return kAlpha_8_as_Alpha_GrPixelConfig;
854            } else if (MTLPixelFormatR8Unorm == format) {
855                return kAlpha_8_as_Red_GrPixelConfig;
856            }
857            break;
858#ifdef SK_BUILD_FOR_MAC
859        case GrColorType::kBGR_565:
860        case GrColorType::kABGR_4444:
861            return kUnknown_GrPixelConfig;
862#else
863        case GrColorType::kBGR_565:
864            if (MTLPixelFormatB5G6R5Unorm == format) {
865                return kRGB_565_GrPixelConfig;
866            }
867            break;
868        case GrColorType::kABGR_4444:
869            if (MTLPixelFormatABGR4Unorm == format) {
870                return kRGBA_4444_GrPixelConfig;
871            }
872            break;
873#endif
874        case GrColorType::kRGBA_8888:
875            if (MTLPixelFormatRGBA8Unorm == format) {
876                return kRGBA_8888_GrPixelConfig;
877            }
878            break;
879        case GrColorType::kRGBA_8888_SRGB:
880            if (MTLPixelFormatRGBA8Unorm_sRGB == format) {
881                return kSRGBA_8888_GrPixelConfig;
882            }
883            break;
884        case GrColorType::kRGB_888x:
885            if (MTLPixelFormatRGBA8Unorm == format) {
886                return kRGB_888X_GrPixelConfig;
887            }
888#ifdef SK_BUILD_FOR_IOS
889            else if (MTLPixelFormatETC2_RGB8 == format) {
890                return kRGB_ETC1_GrPixelConfig;
891            }
892#endif
893            break;
894        case GrColorType::kRG_88:
895            if (MTLPixelFormatRG8Unorm == format) {
896                return kRG_88_GrPixelConfig;
897            }
898            break;
899        case GrColorType::kBGRA_8888:
900            if (MTLPixelFormatBGRA8Unorm == format) {
901                return kBGRA_8888_GrPixelConfig;
902            }
903            break;
904        case GrColorType::kRGBA_1010102:
905            if (MTLPixelFormatRGB10A2Unorm == format) {
906                return kRGBA_1010102_GrPixelConfig;
907            }
908            break;
909        case GrColorType::kGray_8:
910            if (MTLPixelFormatR8Unorm == format) {
911                return kGray_8_as_Red_GrPixelConfig;
912            }
913            break;
914        case GrColorType::kAlpha_F16:
915            if (MTLPixelFormatR16Float == format) {
916                return kAlpha_half_as_Red_GrPixelConfig;
917            }
918            break;
919        case GrColorType::kRGBA_F16:
920            if (MTLPixelFormatRGBA16Float == format) {
921                return kRGBA_half_GrPixelConfig;
922            }
923            break;
924        case GrColorType::kRGBA_F16_Clamped:
925            if (MTLPixelFormatRGBA16Float == format) {
926                return kRGBA_half_Clamped_GrPixelConfig;
927            }
928            break;
929        case GrColorType::kAlpha_16:
930            if (MTLPixelFormatR16Unorm == format) {
931                return kAlpha_16_GrPixelConfig;
932            }
933            break;
934        case GrColorType::kRG_1616:
935            if (MTLPixelFormatRG16Unorm == format) {
936                return kRG_1616_GrPixelConfig;
937            }
938            break;
939        case GrColorType::kRGBA_16161616:
940            if (MTLPixelFormatRGBA16Unorm == format) {
941                return kRGBA_16161616_GrPixelConfig;
942            }
943            break;
944        case GrColorType::kRG_F16:
945            if (MTLPixelFormatRG16Float == format) {
946                return kRG_half_GrPixelConfig;
947            }
948            break;
949        case GrColorType::kRGBA_F32:
950        case GrColorType::kAlpha_8xxx:
951        case GrColorType::kAlpha_F32xxx:
952        case GrColorType::kGray_8xxx:
953            return kUnknown_GrPixelConfig;
954    }
955    SkUNREACHABLE;
956}
957
958bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
959                                                  const GrBackendFormat& format) const {
960    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
961    const auto& info = this->getFormatInfo(mtlFormat);
962    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
963        if (info.fColorTypeInfos[i].fColorType == ct) {
964            return true;
965        }
966    }
967    return false;
968}
969
970GrPixelConfig GrMtlCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
971                                                      GrColorType ct) const {
972    return validate_sized_format(GrBackendFormatAsMTLPixelFormat(format), ct);
973}
974
975GrColorType GrMtlCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
976                                                         bool isAlphaChannel) const {
977    switch (GrBackendFormatAsMTLPixelFormat(format)) {
978        case MTLPixelFormatA8Unorm:           // fall through
979        case MTLPixelFormatR8Unorm:           return isAlphaChannel ? GrColorType::kAlpha_8
980                                                                    : GrColorType::kGray_8;
981        case MTLPixelFormatRG8Unorm:          return GrColorType::kRG_88;
982        case MTLPixelFormatRGBA8Unorm:        return GrColorType::kRGBA_8888;
983        case MTLPixelFormatBGRA8Unorm:        return GrColorType::kBGRA_8888;
984        case MTLPixelFormatRGB10A2Unorm:      return GrColorType::kRGBA_1010102;
985        case MTLPixelFormatR16Unorm:          return GrColorType::kAlpha_16;
986        case MTLPixelFormatR16Float:          return GrColorType::kAlpha_F16;
987        case MTLPixelFormatRG16Unorm:         return GrColorType::kRG_1616;
988        case MTLPixelFormatRGBA16Unorm:       return GrColorType::kRGBA_16161616;
989        case MTLPixelFormatRG16Float:         return GrColorType::kRG_F16;
990        default:                              return GrColorType::kUnknown;
991    }
992}
993
994GrBackendFormat GrMtlCaps::onGetDefaultBackendFormat(GrColorType ct,
995                                                     GrRenderable renderable) const {
996    MTLPixelFormat format = this->getFormatFromColorType(ct);
997    if (!format) {
998        return GrBackendFormat();
999    }
1000    return GrBackendFormat::MakeMtl(format);
1001}
1002
1003GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType(
1004        SkImage::CompressionType compressionType) const {
1005    switch (compressionType) {
1006        case SkImage::kETC1_CompressionType:
1007#ifdef SK_BUILD_FOR_MAC
1008            return {};
1009#else
1010            return GrBackendFormat::MakeMtl(MTLPixelFormatETC2_RGB8);
1011#endif
1012    }
1013    SK_ABORT("Invalid compression type");
1014}
1015
1016GrSwizzle GrMtlCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1017    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1018    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
1019    const auto& info = this->getFormatInfo(mtlFormat);
1020    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1021        const auto& ctInfo = info.fColorTypeInfos[i];
1022        if (ctInfo.fColorType == colorType) {
1023            return ctInfo.fTextureSwizzle;
1024        }
1025    }
1026    return GrSwizzle::RGBA();
1027}
1028GrSwizzle GrMtlCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1029    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1030    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
1031    const auto& info = this->getFormatInfo(mtlFormat);
1032    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1033        const auto& ctInfo = info.fColorTypeInfos[i];
1034        if (ctInfo.fColorType == colorType) {
1035            return ctInfo.fOutputSwizzle;
1036        }
1037    }
1038    return GrSwizzle::RGBA();
1039}
1040
1041GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType(
1042        GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat,
1043        GrColorType srcColorType) const {
1044    // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
1045    // pixels size.
1046    size_t offsetAlignment = GrColorTypeBytesPerPixel(surfaceColorType);
1047
1048    const auto& info = this->getFormatInfo(GrBackendFormatAsMTLPixelFormat(surfaceFormat));
1049    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1050        const auto& ctInfo = info.fColorTypeInfos[i];
1051        if (ctInfo.fColorType == surfaceColorType) {
1052            return {surfaceColorType, offsetAlignment};
1053        }
1054    }
1055    return {GrColorType::kUnknown, 0};
1056}
1057
1058GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType(
1059        GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1060        GrColorType dstColorType) const {
1061    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat);
1062
1063    // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
1064    // pixels size.
1065    size_t offsetAlignment = GrColorTypeBytesPerPixel(srcColorType);
1066
1067    const auto& info = this->getFormatInfo(mtlFormat);
1068    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1069        const auto& ctInfo = info.fColorTypeInfos[i];
1070        if (ctInfo.fColorType == srcColorType) {
1071            return {srcColorType, offsetAlignment};
1072        }
1073    }
1074    return {GrColorType::kUnknown, 0};
1075}
1076
1077#if GR_TEST_UTILS
1078std::vector<GrCaps::TestFormatColorTypeCombination> GrMtlCaps::getTestingCombinations() const {
1079    std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
1080        { GrColorType::kAlpha_8,          GrBackendFormat::MakeMtl(MTLPixelFormatA8Unorm)         },
1081        { GrColorType::kAlpha_8,          GrBackendFormat::MakeMtl(MTLPixelFormatR8Unorm)         },
1082#ifdef SK_BUILD_FOR_IOS
1083        { GrColorType::kBGR_565,          GrBackendFormat::MakeMtl(MTLPixelFormatB5G6R5Unorm)     },
1084        { GrColorType::kABGR_4444,        GrBackendFormat::MakeMtl(MTLPixelFormatABGR4Unorm)      },
1085#endif
1086        { GrColorType::kRGBA_8888,        GrBackendFormat::MakeMtl(MTLPixelFormatRGBA8Unorm)      },
1087        { GrColorType::kRGBA_8888_SRGB,   GrBackendFormat::MakeMtl(MTLPixelFormatRGBA8Unorm_sRGB) },
1088        { GrColorType::kRGB_888x,         GrBackendFormat::MakeMtl(MTLPixelFormatRGBA8Unorm)      },
1089#ifdef SK_BUILD_FOR_IOS
1090        { GrColorType::kRGB_888x,         GrBackendFormat::MakeMtl(MTLPixelFormatETC2_RGB8)       },
1091#endif
1092        { GrColorType::kRG_88,            GrBackendFormat::MakeMtl(MTLPixelFormatRG8Unorm)        },
1093        { GrColorType::kBGRA_8888,        GrBackendFormat::MakeMtl(MTLPixelFormatBGRA8Unorm)      },
1094        { GrColorType::kRGBA_1010102,     GrBackendFormat::MakeMtl(MTLPixelFormatRGB10A2Unorm)    },
1095        { GrColorType::kGray_8,           GrBackendFormat::MakeMtl(MTLPixelFormatR8Unorm)         },
1096        { GrColorType::kAlpha_F16,        GrBackendFormat::MakeMtl(MTLPixelFormatR16Float)        },
1097        { GrColorType::kRGBA_F16,         GrBackendFormat::MakeMtl(MTLPixelFormatRGBA16Float)     },
1098        { GrColorType::kRGBA_F16_Clamped, GrBackendFormat::MakeMtl(MTLPixelFormatRGBA16Float)     },
1099        { GrColorType::kAlpha_16,         GrBackendFormat::MakeMtl(MTLPixelFormatR16Unorm)        },
1100        { GrColorType::kRG_1616,          GrBackendFormat::MakeMtl(MTLPixelFormatRG16Unorm)       },
1101        { GrColorType::kRGBA_16161616,    GrBackendFormat::MakeMtl(MTLPixelFormatRGBA16Unorm)     },
1102        { GrColorType::kRG_F16,           GrBackendFormat::MakeMtl(MTLPixelFormatRG16Float)       },
1103    };
1104
1105    return combos;
1106}
1107#endif
1108