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