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