Rework how backend-specific formats are retrieved from GrBackendFormat.


Change-Id: If1047c477ff3f2cc4aaf19d2e2e838f2dbcb0126
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/233160
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index e39448e..cf2ac53 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -115,9 +115,9 @@
     if (context->backend() == GrBackendApi::kOpenGL) {
         textureType = GrTextureType::kExternal;
     } else if (context->backend() == GrBackendApi::kVulkan) {
-        const VkFormat* format = backendFormat.getVkFormat();
-        SkASSERT(format);
-        if (*format == VK_FORMAT_UNDEFINED) {
+        VkFormat format;
+        SkAssertResult(backendFormat.asVkFormat(&format));
+        if (format == VK_FORMAT_UNDEFINED) {
             textureType = GrTextureType::kExternal;
         }
     }
diff --git a/src/gpu/GrAHardwareBufferUtils.cpp b/src/gpu/GrAHardwareBufferUtils.cpp
index 365d214..47899e8 100644
--- a/src/gpu/GrAHardwareBufferUtils.cpp
+++ b/src/gpu/GrAHardwareBufferUtils.cpp
@@ -14,22 +14,22 @@
 #include "src/gpu/GrAHardwareBufferUtils.h"
 
 #include <android/hardware_buffer.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
 
 #include "include/gpu/GrContext.h"
 #include "include/gpu/gl/GrGLTypes.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/gl/GrGLDefines.h"
+#include "src/gpu/gl/GrGLUtil.h"
 
 #ifdef SK_VULKAN
 #include "src/gpu/vk/GrVkCaps.h"
 #include "src/gpu/vk/GrVkGpu.h"
 #endif
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
 
@@ -259,7 +259,7 @@
     textureInfo.fID = texID;
     SkASSERT(backendFormat.isValid());
     textureInfo.fTarget = target;
-    textureInfo.fFormat = *backendFormat.getGLFormat();
+    textureInfo.fFormat = GrGLFormatToEnum(backendFormat.asGLFormat());
 
     *deleteProc = delete_gl_texture;
     *updateProc = update_gl_texture;
@@ -319,8 +319,8 @@
         return GrBackendTexture();
     }
 
-    SkASSERT(backendFormat.getVkFormat());
-    VkFormat format = *backendFormat.getVkFormat();
+    VkFormat format;
+    SkAssertResult(backendFormat.asVkFormat(&format));
 
     VkResult err;
 
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 5859f4d..412d8da 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -84,31 +84,11 @@
     }
 }
 
-const GrGLenum* GrBackendFormat::getGLFormat() const {
+GrGLFormat GrBackendFormat::asGLFormat() const {
     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
-        return &fGLFormat;
+        return GrGLFormatFromGLEnum(fGLFormat);
     }
-    return nullptr;
-}
-
-const GrGLenum* GrBackendFormat::getGLTarget() const {
-    if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
-        static constexpr GrGLenum kNone = GR_GL_TEXTURE_NONE;
-        static constexpr GrGLenum k2D = GR_GL_TEXTURE_2D;
-        static constexpr GrGLenum kRect = GR_GL_TEXTURE_RECTANGLE;
-        static constexpr GrGLenum kExternal = GR_GL_TEXTURE_EXTERNAL;
-        switch (fTextureType) {
-            case GrTextureType::kNone:
-                return &kNone;
-            case GrTextureType::k2D:
-                return &k2D;
-            case GrTextureType::kRectangle:
-                return &kRect;
-            case GrTextureType::kExternal:
-                return &kExternal;
-        }
-    }
-    return nullptr;
+    return GrGLFormat::kUnknown;
 }
 
 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
@@ -134,11 +114,13 @@
     }
 }
 
-const VkFormat* GrBackendFormat::getVkFormat() const {
+bool GrBackendFormat::asVkFormat(VkFormat* format) const {
+    SkASSERT(format);
     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
-        return &fVk.fFormat;
+        *format = fVk.fFormat;
+        return true;
     }
-    return nullptr;
+    return false;
 }
 
 const GrVkYcbcrConversionInfo* GrBackendFormat::getVkYcbcrConversionInfo() const {
@@ -156,11 +138,13 @@
         , fTextureType(GrTextureType::k2D) {
 }
 
-const dawn::TextureFormat* GrBackendFormat::getDawnFormat() const {
+bool GrBackendFormat::asDawnFormat(dawn::TextureFormat* format) const {
+    SkASSERT(format);
     if (this->isValid() && GrBackendApi::kDawn == fBackend) {
-        return &fDawnFormat;
+        *format = fDawnFormat;
+        return true;
     }
-    return nullptr;
+    return false;
 }
 #endif
 
@@ -172,11 +156,12 @@
         , fTextureType(GrTextureType::k2D) {
 }
 
-const GrMTLPixelFormat* GrBackendFormat::getMtlFormat() const {
+GrMTLPixelFormat GrBackendFormat::asMtlFormat() const {
     if (this->isValid() && GrBackendApi::kMetal == fBackend) {
-        return &fMtlFormat;
+        return fMtlFormat;
     }
-    return nullptr;
+    // MTLPixelFormatInvalid == 0
+    return GrMTLPixelFormat(0);
 }
 #endif
 
@@ -187,11 +172,11 @@
     fMockColorType = colorType;
 }
 
-const GrColorType* GrBackendFormat::getMockColorType() const {
+GrColorType GrBackendFormat::asMockColorType() const {
     if (this->isValid() && GrBackendApi::kMock == fBackend) {
-        return &fMockColorType;
+        return fMockColorType;
     }
-    return nullptr;
+    return GrColorType::kUnknown;
 }
 
 GrBackendFormat GrBackendFormat::makeTexture2D() const {
diff --git a/src/gpu/dawn/GrDawnCaps.cpp b/src/gpu/dawn/GrDawnCaps.cpp
index 0205023..8964d61 100644
--- a/src/gpu/dawn/GrDawnCaps.cpp
+++ b/src/gpu/dawn/GrDawnCaps.cpp
@@ -35,27 +35,27 @@
 
 GrPixelConfig GrDawnCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
                                                        GrColorType colorType) const {
-    const dawn::TextureFormat* dawnFormat = format.getDawnFormat();
-    if (!dawnFormat) {
+    dawn::TextureFormat dawnFormat;
+    if (!format.asDawnFormat(&dawnFormat)) {
         return kUnknown_GrPixelConfig;
     }
     switch (colorType) {
         case GrColorType::kUnknown:
             return kUnknown_GrPixelConfig;
         case GrColorType::kAlpha_8:
-            if (dawn::TextureFormat::R8Unorm == *dawnFormat) {
+            if (dawn::TextureFormat::R8Unorm == dawnFormat) {
                 return kAlpha_8_as_Red_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_8888:
-            if (dawn::TextureFormat::RGBA8Unorm == *dawnFormat) {
+            if (dawn::TextureFormat::RGBA8Unorm == dawnFormat) {
                 return kRGBA_8888_GrPixelConfig;
             }
             break;
         case GrColorType::kRGB_888x:
             break;
         case GrColorType::kBGRA_8888:
-            if (dawn::TextureFormat::BGRA8Unorm == *dawnFormat) {
+            if (dawn::TextureFormat::BGRA8Unorm == dawnFormat) {
                 return kBGRA_8888_GrPixelConfig;
             }
             break;
@@ -67,7 +67,8 @@
 
 static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
                              bool forOutput) {
-    SkASSERT(format.getDawnFormat());
+    SkDEBUGCODE(dawn::TextureFormat format;)
+    SkASSERT(format.asDawnFormat(&format));
 
     switch (colorType) {
         case GrColorType::kAlpha_8: // fall through
@@ -103,19 +104,21 @@
 
 bool GrDawnCaps::isFormatRenderable(GrColorType ct, const GrBackendFormat& format,
                                     int sampleCount) const {
-    if (!format.isValid() || sampleCount > 1) {
+    dawn::TextureFormat dawnFormat;
+    if (!format.isValid() || sampleCount > 1 || !format.asDawnFormat(&dawnFormat)) {
         return false;
     }
 
-    return GrDawnFormatIsRenderable(*format.getDawnFormat()) ? 1 : 0;
+    return GrDawnFormatIsRenderable(dawnFormat);
 }
 
 int GrDawnCaps::getRenderTargetSampleCount(int requestedCount, GrColorType ct,
                                            const GrBackendFormat& backendFormat) const {
-    if (!backendFormat.getDawnFormat()) {
+    dawn::TextureFormat dawnFormat;
+    if (!format.asDawnFormat(&dawnFormat)) {
         return 0;
     }
-    return GrDawnFormatIsRenderable(*backendFormat.getDawnFormat()) ? 1 : 0;
+    return GrDawnFormatIsRenderable(dawnFormat) ? 1 : 0;
 }
 
 int GrDawnCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 8c8bc55..f34cfaf 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -3072,10 +3072,8 @@
         return {};
     }
 
-    {
-        const GrGLenum* srcTextureTarget = src->backendFormat().getGLTarget();
-        SkASSERT(srcTextureTarget);
-        if (*srcTextureTarget == GR_GL_TEXTURE_EXTERNAL) {
+    if (const auto* texProxy = src->asTextureProxy()) {
+        if (texProxy->textureType() == GrTextureType::kExternal) {
             // Not supported for FBO blit or CopyTexSubImage. Caller will have to fall back to a
             // draw (if the source is also a texture).
             return {};
@@ -3689,18 +3687,10 @@
 GrCaps::SupportedRead GrGLCaps::onSupportedReadPixelsColorType(
         GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
         GrColorType dstColorType) const {
-    // For now, we mostly report the read back format that is required by the ES spec without
-    // checking for implementation allowed formats or consider laxer rules in non-ES GL. TODO: Relax
-    // this as makes sense to increase performance and correctness.
-    GrGLFormat srcFormat = GrGLBackendFormatToGLFormat(srcBackendFormat);
-    if (srcFormat == GrGLFormat::kUnknown) {
-        return {GrColorType::kUnknown, 0};
-    }
-
     // We first try to find a supported read pixels GrColorType that matches the requested
     // dstColorType. If that doesn't exists we will use any valid read pixels GrColorType.
     GrCaps::SupportedRead fallbackRead = {GrColorType::kUnknown, 0};
-    const auto& formatInfo = this->getFormatInfo(srcFormat);
+    const auto& formatInfo = this->getFormatInfo(srcBackendFormat.asGLFormat());
     bool foundSrcCT = false;
     for (int i = 0; !foundSrcCT && i < formatInfo.fColorTypeInfoCount; ++i) {
         if (formatInfo.fColorTypeInfos[i].fColorType == srcColorType) {
@@ -3732,12 +3722,7 @@
     // We first try to find a supported write pixels GrColorType that matches the data's
     // srcColorType. If that doesn't exists we will use any supported GrColorType.
     GrColorType fallbackCT = GrColorType::kUnknown;
-    const GrGLenum* glEnum = surfaceFormat.getGLFormat();
-    if (!glEnum) {
-        return {GrColorType::kUnknown, 0};
-    }
-    auto glFormat = GrGLFormatFromGLEnum(*glEnum);
-    const auto& formatInfo = this->getFormatInfo(glFormat);
+    const auto& formatInfo = this->getFormatInfo(surfaceFormat.asGLFormat());
     bool foundSurfaceCT = false;
     for (int i = 0; !foundSurfaceCT && i < formatInfo.fColorTypeInfoCount; ++i) {
         if (formatInfo.fColorTypeInfos[i].fColorType == surfaceColorType) {
@@ -3769,14 +3754,12 @@
 }
 
 bool GrGLCaps::isFormatSRGB(const GrBackendFormat& format) const {
-    return GrGLBackendFormatToGLFormat(format) == GrGLFormat::kSRGB8_ALPHA8;
+    return format.asGLFormat() == GrGLFormat::kSRGB8_ALPHA8;
 }
 
 bool GrGLCaps::isFormatCompressed(const GrBackendFormat& format) const {
-    GrGLFormat grGLFormat = GrGLBackendFormatToGLFormat(format);
-
-    return grGLFormat == GrGLFormat::kCOMPRESSED_RGB8_ETC2 ||
-           grGLFormat == GrGLFormat::kCOMPRESSED_ETC1_RGB8;
+    auto fmt = format.asGLFormat();
+    return fmt == GrGLFormat::kCOMPRESSED_RGB8_ETC2 || fmt == GrGLFormat::kCOMPRESSED_ETC1_RGB8;
 }
 
 bool GrGLCaps::isFormatTexturable(GrColorType ct, GrGLFormat format) const {
@@ -3788,23 +3771,22 @@
 }
 
 bool GrGLCaps::isFormatTexturable(GrColorType ct, const GrBackendFormat& format) const {
-    return this->isFormatTexturable(ct, GrGLBackendFormatToGLFormat(format));
+    return this->isFormatTexturable(ct, format.asGLFormat());
 }
 
 bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
                                              int sampleCount) const {
-    auto glFormat = GrGLBackendFormatToGLFormat(format);
-    const FormatInfo& info = this->getFormatInfo(glFormat);
+    auto f = format.asGLFormat();
+    const FormatInfo& info = this->getFormatInfo(f);
     if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
         return false;
     }
 
-    return this->isFormatRenderable(glFormat, sampleCount);
+    return this->isFormatRenderable(f, sampleCount);
 }
 
 bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
-    auto glFormat = GrGLBackendFormatToGLFormat(format);
-    return this->isFormatRenderable(glFormat, sampleCount);
+    return this->isFormatRenderable(format.asGLFormat(), sampleCount);
 }
 
 int GrGLCaps::getRenderTargetSampleCount(int requestedCount, GrGLFormat format) const {
@@ -3854,7 +3836,7 @@
     // requires the src to be an FBO attachment, blit requires both src and dst to be FBO
     // attachments, and draw requires the dst to be an FBO attachment. Thus to copy from and to
     // the same config, we need that config to be bindable to an FBO.
-    return this->canFormatBeFBOColorAttachment(GrGLBackendFormatToGLFormat(format));
+    return this->canFormatBeFBOColorAttachment(format.asGLFormat());
 }
 
 bool GrGLCaps::formatSupportsTexStorage(GrGLFormat format) const {
@@ -3908,114 +3890,116 @@
     return GrGLFormat::kUnknown;
 }
 
-static GrPixelConfig validate_sized_format(GrGLenum format, GrColorType ct, GrGLStandard standard) {
+static GrPixelConfig validate_sized_format(GrGLFormat format,
+                                           GrColorType ct,
+                                           GrGLStandard standard) {
     switch (ct) {
         case GrColorType::kUnknown:
             return kUnknown_GrPixelConfig;
         case GrColorType::kAlpha_8:
-            if (GR_GL_ALPHA8 == format) {
+            if (format == GrGLFormat::kALPHA8) {
                 return kAlpha_8_as_Alpha_GrPixelConfig;
-            } else if (GR_GL_R8 == format) {
+            } else if (format == GrGLFormat::kR8) {
                 return kAlpha_8_as_Red_GrPixelConfig;
             }
             break;
         case GrColorType::kBGR_565:
-            if (GR_GL_RGB565 == format) {
+            if (format == GrGLFormat::kRGB565) {
                 return kRGB_565_GrPixelConfig;
             }
             break;
         case GrColorType::kABGR_4444:
-            if (GR_GL_RGBA4 == format) {
+            if (format == GrGLFormat::kRGBA4) {
                 return kRGBA_4444_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_8888:
-            if (GR_GL_RGBA8 == format) {
+            if (format == GrGLFormat::kRGBA8) {
                 return kRGBA_8888_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_8888_SRGB:
-            if (GR_GL_SRGB8_ALPHA8 == format) {
+            if (format == GrGLFormat::kSRGB8_ALPHA8) {
                 return kSRGBA_8888_GrPixelConfig;
             }
             break;
         case GrColorType::kRGB_888x:
-            if (GR_GL_RGB8 == format) {
+            if (format == GrGLFormat::kRGB8) {
                 return kRGB_888_GrPixelConfig;
-            } else if (GR_GL_RGBA8 == format) {
+            } else if (format == GrGLFormat::kRGBA8) {
                 return kRGB_888X_GrPixelConfig;
-            } else if (GR_GL_COMPRESSED_RGB8_ETC2 == format ||
-                       GR_GL_COMPRESSED_ETC1_RGB8 == format) {
+            } else if (format == GrGLFormat::kCOMPRESSED_RGB8_ETC2 ||
+                       format == GrGLFormat::kCOMPRESSED_ETC1_RGB8) {
                 return kRGB_ETC1_GrPixelConfig;
             }
             break;
         case GrColorType::kRG_88:
-            if (GR_GL_RG8 == format) {
+            if (format == GrGLFormat::kRG8) {
                 return kRG_88_GrPixelConfig;
             }
             break;
         case GrColorType::kBGRA_8888:
-            if (GR_GL_RGBA8 == format) {
+            if (format == GrGLFormat::kRGBA8) {
                 if (GR_IS_GR_GL(standard)) {
                     return kBGRA_8888_GrPixelConfig;
                 }
-            } else if (GR_GL_BGRA8 == format) {
+            } else if (format == GrGLFormat::kBGRA8) {
                 if (GR_IS_GR_GL_ES(standard) || GR_IS_GR_WEBGL(standard)) {
                     return kBGRA_8888_GrPixelConfig;
                 }
             }
             break;
         case GrColorType::kRGBA_1010102:
-            if (GR_GL_RGB10_A2 == format) {
+            if (format == GrGLFormat::kRGB10_A2) {
                 return kRGBA_1010102_GrPixelConfig;
             }
             break;
         case GrColorType::kGray_8:
-            if (GR_GL_LUMINANCE8 == format) {
+            if (format == GrGLFormat::kLUMINANCE8) {
                 return kGray_8_as_Lum_GrPixelConfig;
-            } else if (GR_GL_R8 == format) {
+            } else if (format == GrGLFormat::kR8) {
                 return kGray_8_as_Red_GrPixelConfig;
             }
             break;
         case GrColorType::kAlpha_F16:
-            if (GR_GL_LUMINANCE16F == format) {
+            if (format == GrGLFormat::kLUMINANCE16F) {
                 return kAlpha_half_as_Lum_GrPixelConfig;
-            } else if (GR_GL_R16F == format) {
+            } else if (format == GrGLFormat::kR16F) {
                 return kAlpha_half_as_Red_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_F16:
-            if (GR_GL_RGBA16F == format) {
+            if (format == GrGLFormat::kRGBA16F) {
                 return kRGBA_half_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_F16_Clamped:
-            if (GR_GL_RGBA16F == format) {
+            if (format == GrGLFormat::kRGBA16F) {
                 return kRGBA_half_Clamped_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_F32:
-            if (GR_GL_RGBA32F == format) {
+            if (format == GrGLFormat::kRGBA32F) {
                 return kRGBA_float_GrPixelConfig;
             }
             break;
         case GrColorType::kR_16:
-            if (GR_GL_R16 == format) {
+            if (format == GrGLFormat::kR16) {
                 return kR_16_GrPixelConfig;
             }
             break;
         case GrColorType::kRG_1616:
-            if (GR_GL_RG16 == format) {
+            if (format == GrGLFormat::kRG16) {
                 return kRG_1616_GrPixelConfig;
             }
             break;
         case GrColorType::kRGBA_16161616:
-            if (GR_GL_RGBA16 == format) {
+            if (format == GrGLFormat::kRGBA16) {
                 return kRGBA_16161616_GrPixelConfig;
             }
             break;
         case GrColorType::kRG_F16:
-            if (GR_GL_RG16F == format) {
+            if (format == GrGLFormat::kRG16F) {
                 return kRG_half_GrPixelConfig;
             }
             break;
@@ -4033,28 +4017,17 @@
 
 bool GrGLCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
                                                  const GrBackendFormat& format) const {
-    const GrGLenum* glFormat = format.getGLFormat();
-    if (!glFormat) {
-        return false;
-    }
-
-    return kUnknown_GrPixelConfig != validate_sized_format(*glFormat, ct, fStandard);
+    return kUnknown_GrPixelConfig != validate_sized_format(format.asGLFormat(), ct, fStandard);
 }
 
 GrPixelConfig GrGLCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
                                                      GrColorType ct) const {
-    const GrGLenum* glFormat = format.getGLFormat();
-    if (!glFormat) {
-        return kUnknown_GrPixelConfig;
-    }
-    return validate_sized_format(*glFormat, ct, fStandard);
+    return validate_sized_format(format.asGLFormat(), ct, fStandard);
 }
 
 GrColorType GrGLCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
                                                         bool isAlphaChannel) const {
-    GrGLFormat grGLFormat = GrGLBackendFormatToGLFormat(format);
-
-    switch (grGLFormat) {
+    switch (format.asGLFormat()) {
         case GrGLFormat::kLUMINANCE8: // <missing kAlpha_8_as_Lum>/kGray_8_as_Lum_GrPixelConfig
         case GrGLFormat::kR8:         // kAlpha_8_as_Red_GrPixelConfig/kGray_8_as_Red_GrPixelConfig
         case GrGLFormat::kALPHA8:     // kAlpha_8_as_Alpha_GrPixelConfig/<missing kGray_8_as_Alpha>
@@ -4101,9 +4074,7 @@
 bool GrGLCaps::canClearTextureOnCreation() const { return fClearTextureSupport; }
 
 GrSwizzle GrGLCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getGLFormat());
-    GrGLFormat glFormat = GrGLBackendFormatToGLFormat(format);
-    const auto& info = this->getFormatInfo(glFormat);
+    const auto& info = this->getFormatInfo(format.asGLFormat());
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
         if (ctInfo.fColorType == colorType) {
@@ -4113,9 +4084,7 @@
     return GrSwizzle::RGBA();
 }
 GrSwizzle GrGLCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getGLFormat());
-    GrGLFormat glFormat = GrGLBackendFormatToGLFormat(format);
-    const auto& info = this->getFormatInfo(glFormat);
+    const auto& info = this->getFormatInfo(format.asGLFormat());
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
         if (ctInfo.fColorType == colorType) {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 5dc04c8..72fbfb9 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -129,13 +129,12 @@
 
     int getRenderTargetSampleCount(int requestedCount,
                                    const GrBackendFormat& format) const override {
-        return this->getRenderTargetSampleCount(requestedCount,
-                                                GrGLBackendFormatToGLFormat(format));
+        return this->getRenderTargetSampleCount(requestedCount, format.asGLFormat());
     }
     int getRenderTargetSampleCount(int requestedCount, GrGLFormat) const;
 
     int maxRenderTargetSampleCount(const GrBackendFormat& format) const override {
-        return this->maxRenderTargetSampleCount(GrGLBackendFormatToGLFormat(format));
+        return this->maxRenderTargetSampleCount(format.asGLFormat());
     }
     int maxRenderTargetSampleCount(GrGLFormat) const;
 
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 6e586ab..aa7c609 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -778,7 +778,7 @@
         return nullptr;
     }
 
-    GrGLFormat format = GrGLFormatFromGLEnum(info.fFormat);
+    const auto format = backendRT.getBackendFormat().asGLFormat();
     if (!this->glCaps().isFormatRenderable(format, backendRT.sampleCnt())) {
         return nullptr;
     }
@@ -791,6 +791,7 @@
 
     GrPixelConfig config = this->caps()->getConfigFromBackendFormat(backendRT.getBackendFormat(),
                                                                     grColorType);
+    SkASSERT(kUnknown_GrPixelConfig != config);
 
     const auto size = SkISize::Make(backendRT.width(), backendRT.height());
     int sampleCount = this->glCaps().getRenderTargetSampleCount(backendRT.sampleCnt(), format);
@@ -1450,6 +1451,10 @@
     texDesc.fFormat = GrGLFormatFromGLEnum(glFormat);
     texDesc.fConfig = desc.fConfig;
     texDesc.fOwnership = GrBackendObjectOwnership::kOwned;
+    if (texDesc.fFormat == GrGLFormat::kUnknown) {
+        return nullptr;
+    }
+
     // TODO: Take these as parameters.
     auto textureColorType = GrPixelConfigToColorType(desc.fConfig);
     auto srcColorType = GrPixelConfigToColorType(desc.fConfig);
@@ -1738,8 +1743,7 @@
 
     GrGLStencilAttachment::IDDesc sbDesc;
 
-    auto rtFormat = GrGLBackendFormatToGLFormat(rt->backendFormat());
-    int sIdx = this->getCompatibleStencilIndex(rtFormat);
+    int sIdx = this->getCompatibleStencilIndex(rt->backendFormat().asGLFormat());
     if (sIdx < 0) {
         return nullptr;
     }
@@ -2172,11 +2176,13 @@
         return false;
     }
 
-    GrGLFormat surfaceFormat = GrGLBackendFormatToGLFormat(surface->backendFormat());
     GrGLenum externalFormat = 0;
     GrGLenum externalType = 0;
-    this->glCaps().getReadPixelsFormat(surfaceFormat, surfaceColorType, dstColorType,
-                                       &externalFormat, &externalType);
+    this->glCaps().getReadPixelsFormat(surface->backendFormat().asGLFormat(),
+                                       surfaceColorType,
+                                       dstColorType,
+                                       &externalFormat,
+                                       &externalType);
     if (!externalFormat || !externalType) {
         return false;
     }
@@ -3763,7 +3769,7 @@
                                                GrProtected isProtected) {
     this->handleDirtyContext();
 
-    GrGLFormat glFormat = GrGLBackendFormatToGLFormat(format);
+    GrGLFormat glFormat = format.asGLFormat();
     if (glFormat == GrGLFormat::kUnknown) {
         return GrBackendTexture();  // invalid
     }
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 677a848..dc7c616 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -361,13 +361,6 @@
 }
 #endif
 
-static inline GrGLFormat GrGLBackendFormatToGLFormat(const GrBackendFormat& format) {
-    if (const GrGLenum* glFormat = format.getGLFormat()) {
-        return GrGLFormatFromGLEnum(*glFormat);
-    }
-    return GrGLFormat::kUnknown;
-}
-
 GrGLenum GrToGLStencilFunc(GrStencilTest test);
 
 /**
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index a34cdb4..ceb1317 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -40,10 +40,8 @@
     }
 
     bool isFormatSRGB(const GrBackendFormat& format) const override {
-        if (!format.getMockColorType()) {
-            return false;
-        }
-        return *format.getMockColorType() == GrColorType::kRGBA_8888_SRGB;
+        auto ct = format.asMockColorType();
+        return GrGetColorTypeDesc(ct).encoding() == GrColorTypeEncoding::kSRGBUnorm;
     }
 
     // Mock caps doesn't support any compressed formats right now
@@ -52,10 +50,8 @@
     }
 
     bool isFormatTexturable(GrColorType, const GrBackendFormat& format) const override {
-        if (!format.getMockColorType()) {
-            return false;
-        }
-        return fOptions.fConfigOptions[(int)*format.getMockColorType()].fTexturable;
+        auto index = static_cast<int>(format.asMockColorType());
+        return fOptions.fConfigOptions[index].fTexturable;
     }
 
     bool isConfigTexturable(GrPixelConfig config) const override {
@@ -79,10 +75,7 @@
     }
 
     bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override {
-        if (!format.getMockColorType()) {
-            return false;
-        }
-        return sampleCount <= this->maxRenderTargetSampleCount(*format.getMockColorType());
+        return sampleCount <= this->maxRenderTargetSampleCount(format.asMockColorType());
     }
 
     int getRenderTargetSampleCount(int requestCount, GrColorType ct) const {
@@ -101,10 +94,7 @@
 
     int getRenderTargetSampleCount(int requestCount,
                                    const GrBackendFormat& format) const override {
-        if (!format.getMockColorType()) {
-            return 0;
-        }
-        return this->getRenderTargetSampleCount(requestCount, *format.getMockColorType());
+        return this->getRenderTargetSampleCount(requestCount, format.asMockColorType());
     }
 
     int maxRenderTargetSampleCount(GrColorType ct) const {
@@ -120,10 +110,7 @@
     }
 
     int maxRenderTargetSampleCount(const GrBackendFormat& format) const override {
-        if (!format.getMockColorType()) {
-            return 0;
-        }
-        return this->maxRenderTargetSampleCount(*format.getMockColorType());
+        return this->maxRenderTargetSampleCount(format.asMockColorType());
     }
 
     SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
@@ -138,11 +125,7 @@
 
     GrColorType getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
                                                   bool isAlphaChannel) const override {
-        if (!format.getMockColorType()) {
-            return GrColorType::kUnknown;
-        }
-
-        return *format.getMockColorType();
+        return format.asMockColorType();
     }
 
     GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override {
@@ -174,26 +157,16 @@
 
     GrPixelConfig onGetConfigFromBackendFormat(const GrBackendFormat& format,
                                                GrColorType) const override {
-        if (!format.getMockColorType()) {
-            return kUnknown_GrPixelConfig;
-        }
-
-        return GrColorTypeToPixelConfig(*format.getMockColorType());
-
+        return GrColorTypeToPixelConfig(format.asMockColorType());
     }
 
     bool onAreColorTypeAndFormatCompatible(GrColorType ct,
                                            const GrBackendFormat& format) const override {
-        if (GrColorType::kUnknown == ct) {
+        if (ct == GrColorType::kUnknown) {
             return false;
         }
 
-        const GrColorType* mockColorType = format.getMockColorType();
-        if (!mockColorType) {
-            return false;
-        }
-
-        return ct == *mockColorType;
+        return ct == format.asMockColorType();
     }
 
     SupportedRead onSupportedReadPixelsColorType(GrColorType srcColorType, const GrBackendFormat&,
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index d45d334..0076583 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -275,16 +275,12 @@
                                                  size_t /* rowBytes */,
                                                  const SkColor4f* /* color */,
                                                  GrProtected /* isProtected */) {
-
-    if (!format.getMockColorType()) {
-        return GrBackendTexture();  // invalid;
-    }
-
-    if (!this->caps()->isFormatTexturable(*format.getMockColorType(), format)) {
+    auto colorType = format.asMockColorType();
+    if (!this->caps()->isFormatTexturable(colorType, format)) {
         return GrBackendTexture();  // invalid
     }
 
-    GrMockTextureInfo info(*format.getMockColorType(), NextExternalTextureID());
+    GrMockTextureInfo info(colorType, NextExternalTextureID());
 
     fOutstandingTestingOnlyTextureIDs.add(info.fID);
     return GrBackendTexture(w, h, mipMapped, info);
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index c12c3c3..336a381 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -118,8 +118,6 @@
     };
 
     struct FormatInfo {
-        FormatInfo() : fFlags(0) {}
-
         uint32_t colorTypeFlags(GrColorType colorType) const {
             for (int i = 0; i < fColorTypeInfoCount; ++i) {
                 if (fColorTypeInfos[i].fColorType == colorType) {
@@ -138,7 +136,7 @@
         static const uint16_t kAllFlags = kTextureable_Flag | kRenderable_Flag |
                                           kMSAA_Flag | kResolve_Flag;
 
-        uint16_t fFlags;
+        uint16_t fFlags = 0;
 
         std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
         int fColorTypeInfoCount = 0;
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 8e145ab..a07bd02 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -275,33 +275,20 @@
 }
 
 bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const {
-    if (!format.getMtlFormat()) {
-        return false;
-    }
-
-    return format_is_srgb(static_cast<MTLPixelFormat>(*format.getMtlFormat()));
+    return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format));
 }
 
 bool GrMtlCaps::isFormatCompressed(const GrBackendFormat& format) const {
 #ifdef SK_BUILD_FOR_MAC
     return false;
 #else
-    if (!format.getMtlFormat()) {
-        return false;
-    }
-
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
-
-    return mtlFormat == MTLPixelFormatETC2_RGB8;
+    return GrBackendFormatAsMTLPixelFormat(format) == MTLPixelFormatETC2_RGB8;
 #endif
 }
 
 bool GrMtlCaps::isFormatTexturable(GrColorType ct, const GrBackendFormat& format) const {
-    if (!format.getMtlFormat()) {
-        return false;
-    }
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
 
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
     uint32_t ctFlags = this->getFormatInfo(mtlFormat).colorTypeFlags(ct);
     return this->isFormatTexturable(mtlFormat) &&
            SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag);
@@ -328,8 +315,8 @@
     if (!this->isFormatRenderable(format, sampleCount)) {
         return false;
     }
-    SkASSERT(format.getMtlFormat());
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
+    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
     const auto& info = this->getFormatInfo(mtlFormat);
     if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
         return false;
@@ -338,11 +325,7 @@
 }
 
 bool GrMtlCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
-    if (!format.getMtlFormat()) {
-        return false;
-    }
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
-    return this->isFormatRenderable(mtlFormat, sampleCount);
+    return this->isFormatRenderable(GrBackendFormatAsMTLPixelFormat(format), sampleCount);
 }
 
 bool GrMtlCaps::isFormatRenderable(MTLPixelFormat format, int sampleCount) const {
@@ -350,12 +333,7 @@
 }
 
 int GrMtlCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
-    if (!format.getMtlFormat()) {
-        return 0;
-    }
-
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
-    return this->maxRenderTargetSampleCount(mtlFormat);
+    return this->maxRenderTargetSampleCount(GrBackendFormatAsMTLPixelFormat(format));
 }
 
 int GrMtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const {
@@ -370,17 +348,17 @@
 
 int GrMtlCaps::getRenderTargetSampleCount(int requestedCount,
                                           const GrBackendFormat& format) const {
-    if (!format.getMtlFormat()) {
-        return 0;
-    }
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
 
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
     return this->getRenderTargetSampleCount(requestedCount, mtlFormat);
 }
 
 int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, MTLPixelFormat format) const {
     requestedCount = SkTMax(requestedCount, 1);
     const FormatInfo& formatInfo = this->getFormatInfo(format);
+    if (!(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) {
+        return 0;
+    }
     if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) {
         int count = fSampleCounts.count();
         for (int i = 0; i < count; ++i) {
@@ -388,10 +366,8 @@
                 return fSampleCounts[i];
             }
         }
-    } else if (formatInfo.fFlags & FormatInfo::kRenderable_Flag) {
-        return 1 == requestedCount ? 1 : 0;
     }
-    return 0;
+    return 1 == requestedCount ? 1 : 0;
 }
 
 void GrMtlCaps::initShaderCaps() {
@@ -438,8 +414,6 @@
 // These are all the valid MTLPixelFormats that we support in Skia.  They are roughly ordered from
 // most frequently used to least to improve look up times in arrays.
 static constexpr MTLPixelFormat kMtlFormats[] = {
-    MTLPixelFormatInvalid,
-
     MTLPixelFormatRGBA8Unorm,
     MTLPixelFormatR8Unorm,
     MTLPixelFormatA8Unorm,
@@ -464,13 +438,14 @@
     // Experimental (for Y416 and mutant P016/P010)
     MTLPixelFormatRGBA16Unorm,
     MTLPixelFormatRG16Float,
+
+    MTLPixelFormatInvalid,
 };
 
 size_t GrMtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) {
     static_assert(SK_ARRAY_COUNT(kMtlFormats) == GrMtlCaps::kNumMtlFormats,
                   "Size of kMtlFormats array must match static value in header");
-    // Start at 1, 0 is sentinel value (MTLPixelFormatInvalid)
-    for (size_t i = 1; i < GrMtlCaps::kNumMtlFormats; ++i) {
+    for (size_t i = 0; i < GrMtlCaps::kNumMtlFormats; ++i) {
         if (kMtlFormats[i] == pixelFormat) {
             return i;
         }
@@ -909,35 +884,19 @@
 
 bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
                                                   const GrBackendFormat& format) const {
-    const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
-    if (!mtlFormat) {
-        return false;
-    }
-
-    return kUnknown_GrPixelConfig != validate_sized_format(*mtlFormat, ct);
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
+    return kUnknown_GrPixelConfig != validate_sized_format(mtlFormat, ct);
 }
 
 
 GrPixelConfig GrMtlCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
                                                       GrColorType ct) const {
-    const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
-    if (!mtlFormat) {
-        return kUnknown_GrPixelConfig;
-    }
-    return validate_sized_format(*mtlFormat, ct);
+    return validate_sized_format(GrBackendFormatAsMTLPixelFormat(format), ct);
 }
 
 GrColorType GrMtlCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
                                                          bool isAlphaChannel) const {
-    const GrMTLPixelFormat* grMtlFormat = format.getMtlFormat();
-    if (!grMtlFormat) {
-        return GrColorType::kUnknown;
-    }
-
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*grMtlFormat);
-
-
-    switch (mtlFormat) {
+    switch (GrBackendFormatAsMTLPixelFormat(format)) {
         case MTLPixelFormatA8Unorm:           // fall through
         case MTLPixelFormatR8Unorm:           return isAlphaChannel ? GrColorType::kAlpha_8
                                                                     : GrColorType::kGray_8;
@@ -952,8 +911,6 @@
         case MTLPixelFormatRG16Float:         return GrColorType::kRG_F16;
         default:                              return GrColorType::kUnknown;
     }
-
-    SkUNREACHABLE;
 }
 
 GrBackendFormat GrMtlCaps::onGetDefaultBackendFormat(GrColorType ct,
@@ -984,8 +941,8 @@
 }
 
 GrSwizzle GrMtlCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getMtlFormat());
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
+    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
     const auto& info = this->getFormatInfo(mtlFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
@@ -996,8 +953,8 @@
     return GrSwizzle::RGBA();
 }
 GrSwizzle GrMtlCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getMtlFormat());
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*format.getMtlFormat());
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
+    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
     const auto& info = this->getFormatInfo(mtlFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
@@ -1011,17 +968,11 @@
 GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType(
         GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat,
         GrColorType srcColorType) const {
-    const GrMTLPixelFormat* grMtlFormat = surfaceFormat.getMtlFormat();
-    if (!grMtlFormat) {
-        return {GrColorType::kUnknown, 0};
-    }
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*grMtlFormat);
-
     // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
     // pixels size.
     size_t offsetAlignment = GrColorTypeBytesPerPixel(surfaceColorType);
 
-    const auto& info = this->getFormatInfo(mtlFormat);
+    const auto& info = this->getFormatInfo(GrBackendFormatAsMTLPixelFormat(surfaceFormat));
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
         if (ctInfo.fColorType == surfaceColorType) {
@@ -1034,11 +985,7 @@
 GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType(
         GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
         GrColorType dstColorType) const {
-    const GrMTLPixelFormat* grMtlFormat = srcBackendFormat.getMtlFormat();
-    if (!grMtlFormat) {
-        return {GrColorType::kUnknown, 0};
-    }
-    MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(*grMtlFormat);
+    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat);
 
     // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
     // pixels size.
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index f459c64..1c03064 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -727,13 +727,9 @@
         return GrBackendTexture();
     }
 
-    const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
-    if (!mtlFormat) {
-        return GrBackendTexture();
-    }
-
+    const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
     GrMtlTextureInfo info;
-    if (!this->createTestingOnlyMtlTextureInfo(static_cast<MTLPixelFormat>(*mtlFormat),
+    if (!this->createTestingOnlyMtlTextureInfo(mtlFormat,
                                                w, h, true,
                                                GrRenderable::kYes == renderable, mipMapped,
                                                pixels, rowBytes, &info)) {
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index 31f0923..837ed48 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -10,6 +10,7 @@
 
 #import <Metal/Metal.h>
 
+#include "include/gpu/GrBackendSurface.h"
 #include "include/private/GrTypesPriv.h"
 #include "src/sksl/ir/SkSLProgram.h"
 
@@ -96,4 +97,8 @@
 
 size_t GrMtlBytesPerFormat(MTLPixelFormat);
 
+static inline MTLPixelFormat GrBackendFormatAsMTLPixelFormat(const GrBackendFormat& format) {
+    return static_cast<MTLPixelFormat>(format.asMtlFormat());
+}
+
 #endif
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 3368c90..e6118b0 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1058,30 +1058,31 @@
 }
 
 bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
-    if (!format.getVkFormat()) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return false;
     }
 
-    return format_is_srgb(*format.getVkFormat());
+    return format_is_srgb(vkFormat);
 }
 
 bool GrVkCaps::isFormatCompressed(const GrBackendFormat& format) const {
-    if (!format.getVkFormat()) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return false;
     }
 
-    VkFormat vkFormat = *format.getVkFormat();
     SkASSERT(GrVkFormatIsSupported(vkFormat));
 
     return vkFormat == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
 }
 
 bool GrVkCaps::isFormatTexturable(GrColorType ct, const GrBackendFormat& format) const {
-    if (!format.getVkFormat()) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return false;
     }
 
-    VkFormat vkFormat = *format.getVkFormat();
     uint32_t ctFlags = this->getFormatInfo(vkFormat).colorTypeFlags(ct);
     return this->isVkFormatTexturable(vkFormat) &&
            SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag);
@@ -1108,8 +1109,10 @@
     if (!this->isFormatRenderable(format, sampleCount)) {
         return false;
     }
-    SkASSERT(format.getVkFormat());
-    VkFormat vkFormat = *format.getVkFormat();
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
+        return false;
+    }
     const auto& info = this->getFormatInfo(vkFormat);
     if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
         return false;
@@ -1118,10 +1121,10 @@
 }
 
 bool GrVkCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
-    if (!format.getVkFormat()) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return false;
     }
-    VkFormat vkFormat = *format.getVkFormat();
     return this->isFormatRenderable(vkFormat, sampleCount);
 }
 
@@ -1132,13 +1135,11 @@
 int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
                                          const GrBackendFormat& format) const {
     VkFormat vkFormat;
-    if (const auto* temp = format.getVkFormat()) {
-        vkFormat = *temp;
-    } else {
+    if (!format.asVkFormat(&vkFormat)) {
         return 0;
     }
 
-    return this->getRenderTargetSampleCount(requestedCount, *format.getVkFormat());
+    return this->getRenderTargetSampleCount(requestedCount, vkFormat);
 }
 
 int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
@@ -1166,11 +1167,11 @@
 }
 
 int GrVkCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
-    if (!format.getVkFormat()) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return 0;
     }
-
-    return this->maxRenderTargetSampleCount(*format.getVkFormat());
+    return this->maxRenderTargetSampleCount(vkFormat);
 }
 
 int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
@@ -1197,15 +1198,15 @@
 GrCaps::SupportedWrite GrVkCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
                                                                const GrBackendFormat& surfaceFormat,
                                                                GrColorType srcColorType) const {
-    const VkFormat* vkFormat = surfaceFormat.getVkFormat();
-    if (!vkFormat) {
+    VkFormat vkFormat;
+    if (!surfaceFormat.asVkFormat(&vkFormat)) {
         return {GrColorType::kUnknown, 0};
     }
 
     // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
-    size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(*vkFormat));
+    size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(vkFormat));
 
-    const auto& info = this->getFormatInfo(*vkFormat);
+    const auto& info = this->getFormatInfo(vkFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
         if (ctInfo.fColorType == surfaceColorType) {
@@ -1377,34 +1378,36 @@
 
 bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
                                                  const GrBackendFormat& format) const {
-    const VkFormat* vkFormat = format.getVkFormat();
-    const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
-    if (!vkFormat || !ycbcrInfo) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return false;
     }
+    const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
+    SkASSERT(ycbcrInfo);
 
-    return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
+    return kUnknown_GrPixelConfig != validate_image_info(vkFormat, ct, ycbcrInfo->isValid());
 }
 
 
 GrPixelConfig GrVkCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
                                                      GrColorType ct) const {
-    const VkFormat* vkFormat = format.getVkFormat();
-    const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
-    if (!vkFormat || !ycbcrInfo) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return kUnknown_GrPixelConfig;
     }
-    return validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
+    const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
+    SkASSERT(ycbcrInfo);
+    return validate_image_info(vkFormat, ct, ycbcrInfo->isValid());
 }
 
 GrColorType GrVkCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
                                                         bool isAlphaChannel) const {
-    const VkFormat* vkFormat = format.getVkFormat();
-    if (!vkFormat) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         return GrColorType::kUnknown;
     }
 
-    switch (*vkFormat) {
+    switch (vkFormat) {
         case VK_FORMAT_R8_UNORM:                 return isAlphaChannel ? GrColorType::kAlpha_8
                                                                        : GrColorType::kGray_8;
         case VK_FORMAT_R8G8B8A8_UNORM:           return GrColorType::kRGBA_8888;
@@ -1449,8 +1452,8 @@
 bool GrVkCaps::canClearTextureOnCreation() const { return true; }
 
 GrSwizzle GrVkCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getVkFormat());
-    VkFormat vkFormat = *format.getVkFormat();
+    VkFormat vkFormat;
+    SkAssertResult(format.asVkFormat(&vkFormat));
     const auto& info = this->getFormatInfo(vkFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
@@ -1462,8 +1465,8 @@
 }
 
 GrSwizzle GrVkCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
-    SkASSERT(format.getVkFormat());
-    VkFormat vkFormat = *format.getVkFormat();
+    VkFormat vkFormat;
+    SkAssertResult(format.asVkFormat(&vkFormat));
     const auto& info = this->getFormatInfo(vkFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
@@ -1477,15 +1480,15 @@
 GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
         GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
         GrColorType dstColorType) const {
-    const VkFormat* vkFormat = srcBackendFormat.getVkFormat();
-    if (!vkFormat) {
+    VkFormat vkFormat;
+    if (!srcBackendFormat.asVkFormat(&vkFormat)) {
         return {GrColorType::kUnknown, 0};
     }
 
     // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
-    size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(*vkFormat));
+    size_t offsetAlignment = align_to_4(GrVkBytesPerFormat(vkFormat));
 
-    const auto& info = this->getFormatInfo(*vkFormat);
+    const auto& info = this->getFormatInfo(vkFormat);
     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
         const auto& ctInfo = info.fColorTypeInfos[i];
         if (ctInfo.fColorType == srcColorType) {
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index f1c2ed9..a5f0db6 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1053,10 +1053,10 @@
                                                     SkImage::CompressionType compressionType,
                                                     SkBudgeted budgeted, const void* data) {
     GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
-    if (!format.getVkFormat()) {
+    VkFormat pixelFormat;
+    if (!format.asVkFormat(&pixelFormat)) {
         return nullptr;
     }
-    VkFormat pixelFormat = *format.getVkFormat();
 
     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
 
@@ -1859,19 +1859,19 @@
         return GrBackendTexture();
     }
 
-    const VkFormat* vkFormat = format.getVkFormat();
-    if (!vkFormat) {
+    VkFormat vkFormat;
+    if (!format.asVkFormat(&vkFormat)) {
         SkDebugf("Could net get vkformat\n");
         return GrBackendTexture();
     }
 
-    if (!caps.isVkFormatTexturable(*vkFormat)) {
+    if (!caps.isVkFormatTexturable(vkFormat)) {
         SkDebugf("Config is not texturable\n");
         return GrBackendTexture();
     }
 
     GrVkImageInfo info;
-    if (!this->createVkImageForBackendSurface(*vkFormat, w, h, true,
+    if (!this->createVkImageForBackendSurface(vkFormat, w, h, true,
                                               GrRenderable::kYes == renderable, mipMapped, srcData,
                                               rowBytes, color, &info, isProtected)) {
         SkDebugf("Failed to create testing only image\n");