Reland "Add new GrSurfaceInfo class and related backend structs."

This is a reland of 6aac1193a7b6dbd1bb7adaf62df80bb93212a23d

Original change's description:
> Add new GrSurfaceInfo class and related backend structs.
>
> Bug: skia:12402
> Change-Id: I45b2f71dcfa5843e2a19a8de7d34196a4d552905
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/445176
> Commit-Queue: Greg Daniel <egdaniel@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>

Bug: skia:12402
Change-Id: Id540bea408d72ceba43ec4245c3748d630121926
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/450277
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 152e69c..8745221 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -18,6 +18,7 @@
   "$_include/gpu/GrDirectContext.h",
   "$_include/gpu/GrDriverBugWorkarounds.h",
   "$_include/gpu/GrRecordingContext.h",
+  "$_include/gpu/GrSurfaceInfo.h",
   "$_include/gpu/GrTypes.h",
   "$_include/gpu/GrYUVABackendTextures.h",
 
@@ -202,6 +203,7 @@
   "$_src/gpu/GrSubRunAllocator.h",
   "$_src/gpu/GrSurface.cpp",
   "$_src/gpu/GrSurface.h",
+  "$_src/gpu/GrSurfaceInfo.cpp",
   "$_src/gpu/GrSurfaceProxy.cpp",
   "$_src/gpu/GrSurfaceProxy.h",
   "$_src/gpu/GrSurfaceProxyPriv.h",
@@ -390,6 +392,8 @@
   "$_src/gpu/glsl/GrGLSLVertexGeoBuilder.h",
 
   # Mock
+  "$_include/gpu/mock/GrMockTypes.h",
+  "$_include/private/GrMockTypesPriv.h",
   "$_src/gpu/mock/GrMockAttachment.h",
   "$_src/gpu/mock/GrMockBuffer.h",
   "$_src/gpu/mock/GrMockCaps.cpp",
@@ -723,12 +727,15 @@
   "$_src/gpu/d3d/GrD3DTextureResource.cpp",
   "$_src/gpu/d3d/GrD3DTextureResource.h",
   "$_src/gpu/d3d/GrD3DTypesMinimal.cpp",
+  "$_src/gpu/d3d/GrD3DTypesPriv.cpp",
+  "$_src/gpu/d3d/GrD3DTypesPriv.h",
   "$_src/gpu/d3d/GrD3DUtil.cpp",
   "$_src/gpu/d3d/GrD3DUtil.h",
 ]
 
 skia_dawn_sources = [
   "$_include/gpu/dawn/GrDawnTypes.h",
+  "$_include/private/GrDawnTypesPriv.h",
   "$_src/gpu/dawn/GrDawnAttachment.cpp",
   "$_src/gpu/dawn/GrDawnAttachment.h",
   "$_src/gpu/dawn/GrDawnBuffer.cpp",
@@ -751,6 +758,7 @@
   "$_src/gpu/dawn/GrDawnTexture.h",
   "$_src/gpu/dawn/GrDawnTextureRenderTarget.cpp",
   "$_src/gpu/dawn/GrDawnTextureRenderTarget.h",
+  "$_src/gpu/dawn/GrDawnTypesPriv.cpp",
   "$_src/gpu/dawn/GrDawnUtil.cpp",
   "$_src/gpu/dawn/GrDawnUtil.h",
 ]
@@ -797,6 +805,7 @@
   "$_src/gpu/mtl/GrMtlTextureRenderTarget.mm",
   "$_src/gpu/mtl/GrMtlTrampoline.h",
   "$_src/gpu/mtl/GrMtlTrampoline.mm",
+  "$_src/gpu/mtl/GrMtlTypesPriv.mm",
   "$_src/gpu/mtl/GrMtlUniformHandler.h",
   "$_src/gpu/mtl/GrMtlUniformHandler.mm",
   "$_src/gpu/mtl/GrMtlUtil.h",
diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h
index 6349bab..28fd497 100644
--- a/include/gpu/GrBackendSurface.h
+++ b/include/gpu/GrBackendSurface.h
@@ -9,12 +9,17 @@
 #define GrBackendSurface_DEFINED
 
 #include "include/gpu/GrBackendSurfaceMutableState.h"
+#include "include/gpu/GrSurfaceInfo.h"
 #include "include/gpu/GrTypes.h"
+#ifdef SK_GL
 #include "include/gpu/gl/GrGLTypes.h"
-#include "include/gpu/mock/GrMockTypes.h"
-#include "include/gpu/vk/GrVkTypes.h"
 #include "include/private/GrGLTypesPriv.h"
+#endif
+#include "include/gpu/mock/GrMockTypes.h"
+#ifdef SK_VULKAN
+#include "include/gpu/vk/GrVkTypes.h"
 #include "include/private/GrVkTypesPriv.h"
+#endif
 
 #ifdef SK_DAWN
 #include "include/gpu/dawn/GrDawnTypes.h"
@@ -76,15 +81,19 @@
     GrBackendFormat(const GrBackendFormat&);
     GrBackendFormat& operator=(const GrBackendFormat&);
 
+#ifdef SK_GL
     static GrBackendFormat MakeGL(GrGLenum format, GrGLenum target) {
         return GrBackendFormat(format, target);
     }
+#endif
 
+#ifdef SK_VULKAN
     static GrBackendFormat MakeVk(VkFormat format) {
         return GrBackendFormat(format, GrVkYcbcrConversionInfo());
     }
 
     static GrBackendFormat MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo);
+#endif
 
 #ifdef SK_DAWN
     static GrBackendFormat MakeDawn(wgpu::TextureFormat format) {
@@ -121,12 +130,15 @@
 
     GrColorFormatDesc desc() const;
 
+#ifdef SK_GL
     /**
      * If the backend API is GL this gets the format as a GrGLFormat. Otherwise, returns
      * GrGLFormat::kUnknown.
      */
     GrGLFormat asGLFormat() const;
+#endif
 
+#ifdef SK_VULKAN
     /**
      * If the backend API is Vulkan this gets the format as a VkFormat and returns true. Otherwise,
      * returns false.
@@ -134,6 +146,7 @@
     bool asVkFormat(VkFormat*) const;
 
     const GrVkYcbcrConversionInfo* getVkYcbcrConversionInfo() const;
+#endif
 
 #ifdef SK_DAWN
     /**
@@ -181,9 +194,13 @@
 #endif
 
 private:
+#ifdef SK_GL
     GrBackendFormat(GrGLenum format, GrGLenum target);
+#endif
 
+#ifdef SK_VULKAN
     GrBackendFormat(const VkFormat vkFormat, const GrVkYcbcrConversionInfo&);
+#endif
 
 #ifdef SK_DAWN
     GrBackendFormat(wgpu::TextureFormat format);
@@ -207,11 +224,15 @@
     bool         fValid = false;
 
     union {
+#ifdef SK_GL
         GrGLenum fGLFormat; // the sized, internal format of the GL resource
+#endif
+#ifdef SK_VULKAN
         struct {
             VkFormat                 fFormat;
             GrVkYcbcrConversionInfo  fYcbcrConversionInfo;
         } fVk;
+#endif
 #ifdef SK_DAWN
         wgpu::TextureFormat fDawnFormat;
 #endif
@@ -237,11 +258,13 @@
     // Creates an invalid backend texture.
     GrBackendTexture();
 
+#ifdef SK_GL
     // The GrGLTextureInfo must have a valid fFormat.
     GrBackendTexture(int width,
                      int height,
                      GrMipmapped,
                      const GrGLTextureInfo& glInfo);
+#endif
 
 #ifdef SK_VULKAN
     GrBackendTexture(int width,
@@ -289,6 +312,7 @@
     GrBackendApi backend() const {return fBackend; }
     GrTextureType textureType() const { return fTextureType; }
 
+#ifdef SK_GL
     // If the backend API is GL, copies a snapshot of the GrGLTextureInfo struct into the passed in
     // pointer and returns true. Otherwise returns false if the backend API is not GL.
     bool getGLTextureInfo(GrGLTextureInfo*) const;
@@ -296,6 +320,7 @@
     // Call this to indicate that the texture parameters have been modified in the GL context
     // externally to GrContext.
     void glTextureParametersModified();
+#endif
 
 #ifdef SK_DAWN
     // If the backend API is Dawn, copies a snapshot of the GrDawnTextureInfo struct into the passed
@@ -303,6 +328,7 @@
     bool getDawnTextureInfo(GrDawnTextureInfo*) const;
 #endif
 
+#ifdef SK_VULKAN
     // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
     // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
     // state. Otherwise returns false if the backend API is not Vulkan.
@@ -311,6 +337,7 @@
     // Anytime the client changes the VkImageLayout of the VkImage captured by this
     // GrBackendTexture, they must call this function to notify Skia of the changed layout.
     void setVkImageLayout(VkImageLayout);
+#endif
 
 #ifdef SK_METAL
     // If the backend API is Metal, copies a snapshot of the GrMtlTextureInfo struct into the passed
@@ -403,7 +430,9 @@
 #ifdef SK_GL
         GrGLBackendTextureInfo fGLInfo;
 #endif
+#ifdef SK_VULKAN
         GrVkBackendSurfaceInfo fVkInfo;
+#endif
         GrMockTextureInfo fMockInfo;
 #ifdef SK_DIRECT3D
         GrD3DBackendSurfaceInfo fD3DInfo;
@@ -424,6 +453,7 @@
     // Creates an invalid backend texture.
     GrBackendRenderTarget();
 
+#ifdef SK_GL
     // The GrGLTextureInfo must have a valid fFormat. If wrapping in an SkSurface we require the
     // stencil bits to be either 0, 8 or 16.
     GrBackendRenderTarget(int width,
@@ -431,6 +461,7 @@
                           int sampleCnt,
                           int stencilBits,
                           const GrGLFramebufferInfo& glInfo);
+#endif
 
 #ifdef SK_DAWN
     // If wrapping in an SkSurface we require the stencil bits to be either 0, 8 or 16.
@@ -484,9 +515,11 @@
     GrBackendApi backend() const {return fBackend; }
     bool isFramebufferOnly() const { return fFramebufferOnly; }
 
+#ifdef SK_GL
     // If the backend API is GL, copies a snapshot of the GrGLFramebufferInfo struct into the passed
     // in pointer and returns true. Otherwise returns false if the backend API is not GL.
     bool getGLFramebufferInfo(GrGLFramebufferInfo*) const;
+#endif
 
 #ifdef SK_DAWN
     // If the backend API is Dawn, copies a snapshot of the GrDawnRenderTargetInfo struct into the
@@ -494,6 +527,7 @@
     bool getDawnRenderTargetInfo(GrDawnRenderTargetInfo*) const;
 #endif
 
+#ifdef SK_VULKAN
     // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
     // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
     // state. Otherwise returns false if the backend API is not Vulkan.
@@ -502,6 +536,7 @@
     // Anytime the client changes the VkImageLayout of the VkImage captured by this
     // GrBackendRenderTarget, they must call this function to notify Skia of the changed layout.
     void setVkImageLayout(VkImageLayout);
+#endif
 
 #ifdef SK_METAL
     // If the backend API is Metal, copies a snapshot of the GrMtlTextureInfo struct into the passed
@@ -583,7 +618,9 @@
 #ifdef SK_GL
         GrGLFramebufferInfo fGLInfo;
 #endif
+#ifdef SK_VULKAN
         GrVkBackendSurfaceInfo fVkInfo;
+#endif
         GrMockRenderTargetInfo fMockInfo;
 #ifdef SK_DIRECT3D
         GrD3DBackendSurfaceInfo fD3DInfo;
diff --git a/include/gpu/GrSurfaceInfo.h b/include/gpu/GrSurfaceInfo.h
new file mode 100644
index 0000000..e4ef3c1
--- /dev/null
+++ b/include/gpu/GrSurfaceInfo.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSurfaceInfo_DEFINED
+#define GrSurfaceInfo_DEFINED
+
+#include "include/gpu/GrTypes.h"
+
+#ifdef SK_GL
+#include "include/private/GrGLTypesPriv.h"
+#endif
+#ifdef SK_VULKAN
+#include "include/private/GrVkTypesPriv.h"
+#endif
+#ifdef SK_DIRECT3D
+#include "include/private/GrD3DTypesMinimal.h"
+struct GrD3DSurfaceInfo;
+#endif
+#ifdef SK_METAL
+#include "include/private/GrMtlTypesPriv.h"
+#endif
+#ifdef SK_DAWN
+#include "include/private/GrDawnTypesPriv.h"
+#endif
+#include "include/private/GrMockTypesPriv.h"
+
+class GrSurfaceInfo {
+public:
+    GrSurfaceInfo() {}
+#ifdef SK_GL
+    GrSurfaceInfo(const GrGLSurfaceInfo& glInfo)
+            : fBackend(GrBackendApi::kOpenGL)
+            , fValid(true)
+            , fSampleCount(glInfo.fSampleCount)
+            , fLevelCount(glInfo.fLevelCount)
+            , fProtected(glInfo.fProtected)
+            , fGLSpec(glInfo) {}
+#endif
+#ifdef SK_VULKAN
+    GrSurfaceInfo(const GrVkSurfaceInfo& vkInfo)
+            : fBackend(GrBackendApi::kVulkan)
+            , fValid(true)
+            , fSampleCount(vkInfo.fSampleCount)
+            , fLevelCount(vkInfo.fLevelCount)
+            , fProtected(vkInfo.fProtected)
+            , fVkSpec(vkInfo) {}
+#endif
+#ifdef SK_DIRECT3D
+    GrSurfaceInfo(const GrD3DSurfaceInfo& d3dInfo);
+#endif
+#ifdef SK_METAL
+    GrSurfaceInfo(const GrMtlSurfaceInfo& mtlInfo)
+            : fBackend(GrBackendApi::kMetal)
+            , fValid(true)
+            , fSampleCount(mtlInfo.fSampleCount)
+            , fLevelCount(mtlInfo.fLevelCount)
+            , fProtected(mtlInfo.fProtected)
+            , fMtlSpec(mtlInfo) {}
+#endif
+#ifdef SK_DAWN
+    GrSurfaceInfo(const GrDawnSurfaceInfo& dawnInfo)
+            : fBackend(GrBackendApi::kDawn)
+            , fValid(true)
+            , fSampleCount(dawnInfo.fSampleCount)
+            , fLevelCount(dawnInfo.fLevelCount)
+            , fProtected(dawnInfo.fProtected)
+            , fDawnSpec(dawnInfo) {}
+#endif
+    GrSurfaceInfo(const GrMockSurfaceInfo& mockInfo)
+            : fBackend(GrBackendApi::kMock)
+            , fValid(true)
+            , fSampleCount(mockInfo.fSampleCount)
+            , fLevelCount(mockInfo.fLevelCount)
+            , fProtected(mockInfo.fProtected)
+            , fMockSpec(mockInfo) {}
+
+    ~GrSurfaceInfo();
+    GrSurfaceInfo(const GrSurfaceInfo&) = default;
+
+    bool isValid() const { return fValid; }
+    GrBackendApi backend() const { return fBackend; }
+
+    uint32_t numSamples() const { return fSampleCount; }
+    uint32_t numMipLevels() const { return fLevelCount; }
+    GrProtected isProtected() const { return fProtected; }
+
+#ifdef SK_GL
+    bool getGLSurfaceInfo(GrGLSurfaceInfo* info) const {
+        if (!this->isValid() || fBackend != GrBackendApi::kOpenGL) {
+            return false;
+        }
+        *info = GrGLTextureSpecToSurfaceInfo(fGLSpec, fSampleCount, fLevelCount, fProtected);
+        return true;
+    }
+#endif
+#ifdef SK_VULKAN
+    bool getVkSurfaceInfo(GrVkSurfaceInfo* info) const {
+        if (!this->isValid() || fBackend != GrBackendApi::kVulkan) {
+            return false;
+        }
+        *info = GrVkImageSpecToSurfaceInfo(fVkSpec, fSampleCount, fLevelCount, fProtected);
+        return true;
+    }
+#endif
+#ifdef SK_DIRECT3D
+    bool getD3DSurfaceInfo(GrD3DSurfaceInfo*) const;
+#endif
+#ifdef SK_METAL
+    bool getMtlSurfaceInfo(GrMtlSurfaceInfo* info) const {
+        if (!this->isValid() || fBackend != GrBackendApi::kMetal) {
+            return false;
+        }
+        *info = GrMtlTextureSpecToSurfaceInfo(fMtlSpec, fSampleCount, fLevelCount, fProtected);
+        return true;
+    }
+#endif
+#ifdef SK_DAWN
+    bool getDawnSurfaceInfo(GrDawnSurfaceInfo* info) const {
+        if (!this->isValid() || fBackend != GrBackendApi::kDawn) {
+            return false;
+        }
+        *info = GrDawnTextureSpecToSurfaceInfo(fDawnSpec, fSampleCount, fLevelCount, fProtected);
+        return true;
+    }
+#endif
+    bool getMockSurfaceInfo(GrMockSurfaceInfo* info) const {
+        if (!this->isValid() || fBackend != GrBackendApi::kMock) {
+            return false;
+        }
+        *info = GrMockTextureSpecToSurfaceInfo(fMockSpec, fSampleCount, fLevelCount, fProtected);
+        return true;
+    }
+
+private:
+    GrBackendApi fBackend = GrBackendApi::kMock;
+    bool fValid = false;
+
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    union {
+#ifdef SK_GL
+        GrGLTextureSpec fGLSpec;
+#endif
+#ifdef SK_VULKAN
+        GrVkImageSpec fVkSpec;
+#endif
+#ifdef SK_DIRECT3D
+        GrD3DTextureResourceSpecHolder fD3DSpec;
+#endif
+#ifdef SK_METAL
+        GrMtlTextureSpec fMtlSpec;
+#endif
+#ifdef SK_DAWN
+        GrDawnTextureSpec fDawnSpec;
+#endif
+        GrMockTextureSpec fMockSpec;
+    };
+};
+
+#endif
diff --git a/include/gpu/d3d/GrD3DTypes.h b/include/gpu/d3d/GrD3DTypes.h
index f2a2165..d2e890f 100644
--- a/include/gpu/d3d/GrD3DTypes.h
+++ b/include/gpu/d3d/GrD3DTypes.h
@@ -19,7 +19,7 @@
 // * MemoryBarrier
 //
 // You should only include this header if you need the Direct3D definitions and are
-// prepared to rename those identifiers. Otherwise use GrD3DTypesMinimal.h.
+// prepared to rename those identifiers.
 
 #include "include/core/SkRefCnt.h"
 #include "include/gpu/GrTypes.h"
@@ -236,4 +236,13 @@
     uint64_t           fValue;  // signal value for the fence
 };
 
+struct GrD3DSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    DXGI_FORMAT fFormat = DXGI_FORMAT_UNKNOWN;
+    unsigned int fSampleQualityPattern = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
+};
+
 #endif
diff --git a/include/gpu/dawn/GrDawnTypes.h b/include/gpu/dawn/GrDawnTypes.h
index 2bd923e..640516f 100644
--- a/include/gpu/dawn/GrDawnTypes.h
+++ b/include/gpu/dawn/GrDawnTypes.h
@@ -8,6 +8,8 @@
 #ifndef GrDawnTypes_DEFINED
 #define GrDawnTypes_DEFINED
 
+#include "include/gpu/GrTypes.h"
+
 #ifdef Always
 #undef Always
 static constexpr int Always = 2;
@@ -82,4 +84,12 @@
     }
 };
 
+struct GrDawnSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    wgpu::TextureFormat fFormat;
+};
+
 #endif
diff --git a/include/gpu/gl/GrGLTypes.h b/include/gpu/gl/GrGLTypes.h
index 7a3c57f..49f5ee7 100644
--- a/include/gpu/gl/GrGLTypes.h
+++ b/include/gpu/gl/GrGLTypes.h
@@ -194,4 +194,13 @@
     }
 };
 
+struct GrGLSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    GrGLenum fTarget = 0;
+    GrGLenum fFormat = 0;
+};
+
 #endif
diff --git a/include/gpu/mock/GrMockTypes.h b/include/gpu/mock/GrMockTypes.h
index 2adba6d..dbffe3c 100644
--- a/include/gpu/mock/GrMockTypes.h
+++ b/include/gpu/mock/GrMockTypes.h
@@ -79,6 +79,15 @@
     int           fID;
 };
 
+struct GrMockSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    GrColorType fColorType = GrColorType::kUnknown;
+    SkImage::CompressionType fCompressionType = SkImage::CompressionType::kNone;
+};
+
 /**
  * A pointer to this type is used as the GrBackendContext when creating a Mock GrContext. It can be
  * used to specify capability options for the mock context. If nullptr is used a default constructed
diff --git a/include/gpu/mtl/GrMtlTypes.h b/include/gpu/mtl/GrMtlTypes.h
index ce00a81..f7a232e 100644
--- a/include/gpu/mtl/GrMtlTypes.h
+++ b/include/gpu/mtl/GrMtlTypes.h
@@ -14,8 +14,10 @@
 /**
  * Declares typedefs for Metal types used in Ganesh cpp code
  */
-typedef unsigned int GrMTLPixelFormat;
-typedef const void*  GrMTLHandle;
+using GrMTLPixelFormat = unsigned int;
+using GrMTLTextureUsage = unsigned int;
+using GrMTLStorageMode = unsigned int;
+using GrMTLHandle = const void*;
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -44,6 +46,18 @@
     }
 };
 
+struct GrMtlSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    // Since we aren't in an Obj-C header we can't directly use Mtl types here. Each of these can
+    // cast to their mapped Mtl types list below.
+    GrMTLPixelFormat fFormat = 0;       // MTLPixelFormat fFormat = MTLPixelFormatInvalid;
+    GrMTLTextureUsage fUsage = 0;       // MTLTextureUsage fUsage = MTLTextureUsageUnknown;
+    GrMTLStorageMode fStorageMode = 0;  // MTLStorageMode fStorageMode = MTLStorageModeShared;
+};
+
 #endif
 
 #endif
diff --git a/include/gpu/vk/GrVkTypes.h b/include/gpu/vk/GrVkTypes.h
index 954753b..140695d 100644
--- a/include/gpu/vk/GrVkTypes.h
+++ b/include/gpu/vk/GrVkTypes.h
@@ -160,4 +160,16 @@
     VkImage         fImage;
 };
 
+struct GrVkSurfaceInfo {
+    uint32_t fSampleCount = 1;
+    uint32_t fLevelCount = 0;
+    GrProtected fProtected = GrProtected::kNo;
+
+    VkImageTiling fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+    VkFormat fFormat = VK_FORMAT_UNDEFINED;
+    VkImageUsageFlags fImageUsageFlags = 0;
+    GrVkYcbcrConversionInfo fYcbcrConversionInfo;
+    VkSharingMode fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+};
+
 #endif
diff --git a/include/private/GrD3DTypesMinimal.h b/include/private/GrD3DTypesMinimal.h
index b28094e..049c07b 100644
--- a/include/private/GrD3DTypesMinimal.h
+++ b/include/private/GrD3DTypesMinimal.h
@@ -19,7 +19,9 @@
 struct ID3D12Resource;
 class GrD3DResourceState;
 typedef int GrD3DResourceStateEnum;
+struct GrD3DSurfaceInfo;
 struct GrD3DTextureResourceInfo;
+struct GrD3DTextureResourceSpec;
 struct GrD3DFenceInfo;
 
 // This struct is to used to store the the actual information about the Direct3D backend image on
@@ -55,4 +57,18 @@
     GrD3DResourceState* fResourceState;
 };
 
+struct GrD3DTextureResourceSpecHolder {
+public:
+    GrD3DTextureResourceSpecHolder(const GrD3DSurfaceInfo&);
+
+    void cleanup();
+
+    GrD3DSurfaceInfo getSurfaceInfo(uint32_t sampleCount,
+                                    uint32_t levelCount,
+                                    GrProtected isProtected) const;
+
+private:
+    GrD3DTextureResourceSpec* fSpec;
+};
+
 #endif
diff --git a/include/private/GrDawnTypesPriv.h b/include/private/GrDawnTypesPriv.h
new file mode 100644
index 0000000..5eacf2e
--- /dev/null
+++ b/include/private/GrDawnTypesPriv.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnTypesPriv_DEFINED
+#define GrDawnTypesPriv_DEFINED
+
+#include "include/gpu/dawn/GrDawnTypes.h"
+
+struct GrDawnTextureSpec {
+    GrDawnTextureSpec() {}
+    GrDawnTextureSpec(const GrDawnSurfaceInfo& info) : fFormat(info.fFormat) {}
+
+    wgpu::TextureFormat fFormat;
+};
+
+GrDawnSurfaceInfo GrDawnTextureSpecToSurfaceInfo(const GrDawnTextureSpec& dawnSpec,
+                                                 uint32_t sampleCount,
+                                                 uint32_t levelCount,
+                                                 GrProtected isProtected);
+
+#endif
+
diff --git a/include/private/GrGLTypesPriv.h b/include/private/GrGLTypesPriv.h
index 3726f6b..4abef05 100644
--- a/include/private/GrGLTypesPriv.h
+++ b/include/private/GrGLTypesPriv.h
@@ -91,4 +91,17 @@
     GrGLTextureParameters* fParams;
 };
 
+struct GrGLTextureSpec {
+    GrGLTextureSpec() : fTarget(0), fFormat(0) {}
+    GrGLTextureSpec(const GrGLSurfaceInfo& info) : fTarget(info.fTarget), fFormat(info.fFormat) {}
+
+    GrGLenum fTarget;
+    GrGLenum fFormat;
+};
+
+GrGLSurfaceInfo GrGLTextureSpecToSurfaceInfo(const GrGLTextureSpec& glSpec,
+                                             uint32_t sampleCount,
+                                             uint32_t levelCount,
+                                             GrProtected isProtected);
+
 #endif
diff --git a/include/private/GrMockTypesPriv.h b/include/private/GrMockTypesPriv.h
new file mode 100644
index 0000000..fc72c7f
--- /dev/null
+++ b/include/private/GrMockTypesPriv.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrMockTypesPriv_DEFINED
+#define GrMockTypesPriv_DEFINED
+
+#include "include/gpu/mock/GrMockTypes.h"
+
+struct GrMockTextureSpec {
+    GrMockTextureSpec()
+            : fColorType(GrColorType::kUnknown)
+             , fCompressionType(SkImage::CompressionType::kNone) {}
+    GrMockTextureSpec(const GrMockSurfaceInfo& info)
+            : fColorType(info.fColorType)
+            , fCompressionType(info.fCompressionType) {}
+
+    GrColorType fColorType = GrColorType::kUnknown;
+    SkImage::CompressionType fCompressionType = SkImage::CompressionType::kNone;
+};
+
+GrMockSurfaceInfo GrMockTextureSpecToSurfaceInfo(const GrMockTextureSpec& mockSpec,
+                                                 uint32_t sampleCount,
+                                                 uint32_t levelCount,
+                                                 GrProtected isProtected);
+
+#endif
+
diff --git a/include/private/GrMtlTypesPriv.h b/include/private/GrMtlTypesPriv.h
index d5cae62..550d017 100644
--- a/include/private/GrMtlTypesPriv.h
+++ b/include/private/GrMtlTypesPriv.h
@@ -9,6 +9,7 @@
 #define GrMtlTypesPriv_DEFINED
 
 #include "include/gpu/GrTypes.h"
+#include "include/gpu/mtl/GrMtlTypes.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -49,6 +50,26 @@
 #define GR_NORETAIN_END
 #endif
 
+struct GrMtlTextureSpec {
+    GrMtlTextureSpec()
+            : fFormat(0)
+            , fUsage(0)
+            , fStorageMode(0) {}
+    GrMtlTextureSpec(const GrMtlSurfaceInfo& info)
+            : fFormat(info.fFormat)
+            , fUsage(info.fUsage)
+            , fStorageMode(info.fStorageMode) {}
+
+    GrMTLPixelFormat fFormat;
+    GrMTLTextureUsage fUsage;
+    GrMTLStorageMode fStorageMode;
+};
+
+GrMtlSurfaceInfo GrMtlTextureSpecToSurfaceInfo(const GrMtlTextureSpec& mtlSpec,
+                                               uint32_t sampleCount,
+                                               uint32_t levelCount,
+                                               GrProtected isProtected);
+
 #endif  // __APPLE__
 
 #endif  // GrMtlTypesPriv_DEFINED
diff --git a/include/private/GrVkTypesPriv.h b/include/private/GrVkTypesPriv.h
index b46cf8b..cec98c4 100644
--- a/include/private/GrVkTypesPriv.h
+++ b/include/private/GrVkTypesPriv.h
@@ -78,4 +78,30 @@
     std::atomic<uint32_t> fQueueFamilyIndex;
 };
 
+struct GrVkImageSpec {
+    GrVkImageSpec()
+            : fImageTiling(VK_IMAGE_TILING_OPTIMAL)
+            , fFormat(VK_FORMAT_UNDEFINED)
+            , fImageUsageFlags(0)
+            , fSharingMode(VK_SHARING_MODE_EXCLUSIVE) {}
+
+    GrVkImageSpec(const GrVkSurfaceInfo& info)
+            : fImageTiling(info.fImageTiling)
+            , fFormat(info.fFormat)
+            , fImageUsageFlags(info.fImageUsageFlags)
+            , fYcbcrConversionInfo(info.fYcbcrConversionInfo)
+            , fSharingMode(info.fSharingMode) {}
+
+    VkImageTiling fImageTiling;
+    VkFormat fFormat;
+    VkImageUsageFlags fImageUsageFlags;
+    GrVkYcbcrConversionInfo fYcbcrConversionInfo;
+    VkSharingMode fSharingMode;
+};
+
+GrVkSurfaceInfo GrVkImageSpecToSurfaceInfo(const GrVkImageSpec& vkSpec,
+                                           uint32_t sampleCount,
+                                           uint32_t levelCount,
+                                           GrProtected isProtected);
+
 #endif
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index b483054..fe2012b 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -100,17 +100,6 @@
     int width = this->getInfo().width();
     int height = this->getInfo().height();
 
-    GrTextureType textureType = GrTextureType::k2D;
-    if (context->backend() == GrBackendApi::kOpenGL) {
-        textureType = GrTextureType::kExternal;
-    } else if (context->backend() == GrBackendApi::kVulkan) {
-        VkFormat format;
-        SkAssertResult(backendFormat.asVkFormat(&format));
-        if (format == VK_FORMAT_UNDEFINED) {
-            textureType = GrTextureType::kExternal;
-        }
-    }
-
     auto proxyProvider = context->priv().proxyProvider();
 
     AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 883626a..f1357d6 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -103,7 +103,6 @@
         , fValid(true)
         , fGLFormat(format)
         , fTextureType(gl_target_to_gr_target(target)) {}
-#endif
 
 GrGLFormat GrBackendFormat::asGLFormat() const {
     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
@@ -111,7 +110,9 @@
     }
     return GrGLFormat::kUnknown;
 }
+#endif
 
+#ifdef SK_VULKAN
 GrBackendFormat GrBackendFormat::MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo) {
     SkASSERT(ycbcrInfo.isValid());
     return GrBackendFormat(ycbcrInfo.fFormat, ycbcrInfo);
@@ -119,11 +120,7 @@
 
 GrBackendFormat::GrBackendFormat(VkFormat vkFormat, const GrVkYcbcrConversionInfo& ycbcrInfo)
         : fBackend(GrBackendApi::kVulkan)
-#ifdef SK_VULKAN
         , fValid(true)
-#else
-        , fValid(false)
-#endif
         , fTextureType(GrTextureType::k2D) {
     fVk.fFormat = vkFormat;
     fVk.fYcbcrConversionInfo = ycbcrInfo;
@@ -147,6 +144,7 @@
     }
     return nullptr;
 }
+#endif
 
 #ifdef SK_DAWN
 GrBackendFormat::GrBackendFormat(wgpu::TextureFormat format)
@@ -322,6 +320,7 @@
 
 GrBackendFormat GrBackendFormat::makeTexture2D() const {
     GrBackendFormat copy = *this;
+#ifdef SK_VULKAN
     if (const GrVkYcbcrConversionInfo* ycbcrInfo = this->getVkYcbcrConversionInfo()) {
         if (ycbcrInfo->isValid()) {
             // If we have a ycbcr we remove it from the backend format and set the VkFormat to
@@ -331,6 +330,7 @@
             copy.fVk.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
         }
     }
+#endif
     copy.fTextureType = GrTextureType::k2D;
     return copy;
 }
@@ -676,23 +676,21 @@
 }
 #endif
 
-bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
 #ifdef SK_VULKAN
+bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
         *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
         return true;
     }
-#endif
     return false;
 }
 
 void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
-#ifdef SK_VULKAN
     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
         fMutableState->setImageLayout(layout);
     }
-#endif
 }
+#endif
 
 #ifdef SK_METAL
 bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
@@ -727,12 +725,13 @@
 }
 #endif
 
-bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
 #ifdef SK_GL
+bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
     if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
         *outInfo = fGLInfo.info();
         return true;
-    } else if (this->isValid() && GrBackendApi::kMock == fBackend) {
+    }
+    else if (this->isValid() && GrBackendApi::kMock == fBackend) {
         // Hack! This allows some blink unit tests to work when using the Mock GrContext.
         // Specifically, tests that rely on CanvasResourceProviderTextureGpuMemoryBuffer.
         // If that code ever goes away (or ideally becomes backend-agnostic), this can go away.
@@ -741,17 +740,15 @@
                                     GR_GL_RGBA8 };
         return true;
     }
-#endif
     return false;
 }
 
 void GrBackendTexture::glTextureParametersModified() {
-#ifdef SK_GL
     if (this->isValid() && fBackend == GrBackendApi::kOpenGL) {
         fGLInfo.parameters()->invalidate();
     }
-#endif
 }
+#endif
 
 bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
     if (this->isValid() && GrBackendApi::kMock == fBackend) {
@@ -766,10 +763,15 @@
 }
 
 bool GrBackendTexture::isProtected() const {
-    if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
+    if (!this->isValid()) {
         return false;
     }
-    return fVkInfo.isProtected();
+#ifdef SK_VULKAN
+    if (this->backend() == GrBackendApi::kVulkan) {
+        return fVkInfo.isProtected();
+    }
+#endif
+    return false;
 }
 
 bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
@@ -1117,23 +1119,21 @@
 }
 #endif
 
-bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
 #ifdef SK_VULKAN
+bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
         *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
         return true;
     }
-#endif
     return false;
 }
 
 void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
-#ifdef SK_VULKAN
     if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
         fMutableState->setImageLayout(layout);
     }
-#endif
 }
+#endif
 
 #ifdef SK_METAL
 bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
@@ -1240,7 +1240,11 @@
     if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
         return false;
     }
+#ifdef SK_VULKAN
     return fVkInfo.isProtected();
+#else
+    return false;
+#endif
 }
 
 #if GR_TEST_UTILS
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index cc410a3..b7ba674 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -21,9 +21,9 @@
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrShaderUtils.h"
+#include "src/gpu/GrThreadSafePipelineBuilder.h"
 #include "src/gpu/SurfaceContext.h"
 #include "src/gpu/effects/GrSkSLFP.h"
-#include "src/gpu/gl/GrGLGpu.h"
 #include "src/gpu/mock/GrMockGpu.h"
 #include "src/gpu/text/GrAtlasManager.h"
 #include "src/gpu/text/GrStrikeCache.h"
@@ -40,6 +40,9 @@
 };
 }
 #endif
+#ifdef SK_GL
+#include "src/gpu/gl/GrGLGpu.h"
+#endif
 #ifdef SK_METAL
 #include "include/gpu/mtl/GrMtlBackendContext.h"
 #include "src/gpu/mtl/GrMtlTrampoline.h"
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 673b359..efad1d4 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -41,6 +41,7 @@
 class GrSurface;
 class GrTexture;
 class GrThreadSafePipelineBuilder;
+struct GrVkDrawableInfo;
 class SkJSONWriter;
 
 namespace SkSL {
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index 0a9dd3e..c18c4d6 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -33,6 +33,10 @@
 #include "src/gpu/SkGr.h"
 #include "src/image/SkImage_Base.h"
 
+#ifdef SK_VULKAN
+#include "include/gpu/vk/GrVkTypes.h"
+#endif
+
 #define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fImageContext->priv().singleOwner())
 
 GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
@@ -661,6 +665,7 @@
     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), UseAllocator::kNo));
 }
 
+#ifdef SK_VULKAN
 sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
     if (this->isAbandoned()) {
@@ -696,6 +701,12 @@
     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
             std::move(rt), UseAllocator::kNo, GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
 }
+#else
+sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
+        const SkImageInfo&, const GrVkDrawableInfo&) {
+    return nullptr;
+}
+#endif
 
 sk_sp<GrTextureProxy> GrProxyProvider::CreatePromiseProxy(GrContextThreadSafeProxy* threadSafeProxy,
                                                           LazyInstantiateCallback&& callback,
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index 17d2798..d89bfa9 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -15,6 +15,7 @@
 
 class GrImageContext;
 class GrBackendRenderTarget;
+struct GrVkDrawableInfo;
 class SkBitmap;
 class SkImage;
 
diff --git a/src/gpu/GrSurfaceInfo.cpp b/src/gpu/GrSurfaceInfo.cpp
new file mode 100644
index 0000000..2c0b73e
--- /dev/null
+++ b/src/gpu/GrSurfaceInfo.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/GrSurfaceInfo.h"
+
+#ifdef SK_DIRECT3D
+#include "include/gpu/d3d/GrD3DTypes.h"
+#endif
+
+#ifdef SK_DIRECT3D
+GrSurfaceInfo::GrSurfaceInfo(const GrD3DSurfaceInfo& d3dInfo)
+        : fBackend(GrBackendApi::kDirect3D)
+        , fValid(true)
+        , fSampleCount(d3dInfo.fSampleCount)
+        , fLevelCount(d3dInfo.fLevelCount)
+        , fProtected(d3dInfo.fProtected)
+        , fD3DSpec(d3dInfo) {}
+#endif
+
+GrSurfaceInfo::~GrSurfaceInfo() {
+#ifdef SK_DIRECT3D
+    if (this->isValid() && fBackend == GrBackendApi::kDirect3D) {
+        fD3DSpec.cleanup();
+    }
+#endif
+}
+
+#ifdef SK_DIRECT3D
+bool GrSurfaceInfo::getD3DSurfaceInfo(GrD3DSurfaceInfo* outSpec) const {
+    if (!this->isValid() || fBackend != GrBackendApi::kDirect3D) {
+        return false;
+    }
+    *outSpec = fD3DSpec.getSurfaceInfo(fSampleCount, fLevelCount, fProtected);
+    return true;
+}
+#endif
diff --git a/src/gpu/d3d/GrD3DTypesMinimal.cpp b/src/gpu/d3d/GrD3DTypesMinimal.cpp
index b85d950..1848a21 100644
--- a/src/gpu/d3d/GrD3DTypesMinimal.cpp
+++ b/src/gpu/d3d/GrD3DTypesMinimal.cpp
@@ -9,6 +9,7 @@
 
 #include "include/gpu/d3d/GrD3DTypes.h"
 #include "src/gpu/d3d/GrD3DResourceState.h"
+#include "src/gpu/d3d/GrD3DTypesPriv.h"
 
 GrD3DBackendSurfaceInfo::GrD3DBackendSurfaceInfo(const GrD3DTextureResourceInfo& info,
                                                  GrD3DResourceState* state)
@@ -65,3 +66,19 @@
     return cpyInfoThis == cpyInfoThat && fResourceState == that.fResourceState;
 }
 #endif
+
+GrD3DTextureResourceSpecHolder::GrD3DTextureResourceSpecHolder(const GrD3DSurfaceInfo& info)
+        : fSpec(new GrD3DTextureResourceSpec(info)) {}
+
+GrD3DSurfaceInfo GrD3DTextureResourceSpecHolder::getSurfaceInfo(uint32_t sampleCount,
+                                                                uint32_t levelCount,
+                                                                GrProtected isProtected) const {
+    SkASSERT(fSpec);
+    return GrD3DTextureResourceSpecToSurfaceInfo(*fSpec, sampleCount, levelCount, isProtected);
+}
+
+void GrD3DTextureResourceSpecHolder::cleanup() {
+    delete fSpec;
+    fSpec = nullptr;
+}
+
diff --git a/src/gpu/d3d/GrD3DTypesPriv.cpp b/src/gpu/d3d/GrD3DTypesPriv.cpp
new file mode 100644
index 0000000..1af1d69
--- /dev/null
+++ b/src/gpu/d3d/GrD3DTypesPriv.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/d3d/GrD3DTypesPriv.h"
+
+GrD3DSurfaceInfo GrD3DTextureResourceSpecToSurfaceInfo(const GrD3DTextureResourceSpec& d3dSpec,
+                                                       uint32_t sampleCount,
+                                                       uint32_t levelCount,
+                                                       GrProtected isProtected) {
+    GrD3DSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // D3D info
+    info.fFormat = d3dSpec.fFormat;
+    info.fSampleQualityPattern = d3dSpec.fSampleQualityPattern;
+
+    return info;
+}
diff --git a/src/gpu/d3d/GrD3DTypesPriv.h b/src/gpu/d3d/GrD3DTypesPriv.h
new file mode 100644
index 0000000..05034db
--- /dev/null
+++ b/src/gpu/d3d/GrD3DTypesPriv.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DTypesPriv_DEFINED
+#define GrD3DTypesPriv_DEFINED
+
+#include "include/gpu/d3d/GrD3DTypes.h"
+
+struct GrD3DTextureResourceSpec {
+    GrD3DTextureResourceSpec()
+            : fFormat(DXGI_FORMAT_UNKNOWN)
+            , fSampleQualityPattern(DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN) {}
+
+    GrD3DTextureResourceSpec(const GrD3DSurfaceInfo& info)
+            : fFormat(info.fFormat), fSampleQualityPattern(info.fSampleQualityPattern) {}
+
+    DXGI_FORMAT fFormat;
+    unsigned int fSampleQualityPattern;
+};
+
+GrD3DSurfaceInfo GrD3DTextureResourceSpecToSurfaceInfo(const GrD3DTextureResourceSpec& d3dSpec,
+                                                       uint32_t sampleCount,
+                                                       uint32_t levelCount,
+                                                       GrProtected isProtected);
+
+#endif
diff --git a/src/gpu/dawn/GrDawnTypesPriv.cpp b/src/gpu/dawn/GrDawnTypesPriv.cpp
new file mode 100644
index 0000000..391142d
--- /dev/null
+++ b/src/gpu/dawn/GrDawnTypesPriv.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/private/GrDawnTypesPriv.h"
+
+GrDawnSurfaceInfo GrDawnTextureSpecToSurfaceInfo(const GrDawnTextureSpec& dawnSpec,
+                                                 uint32_t sampleCount,
+                                                 uint32_t levelCount,
+                                                 GrProtected isProtected) {
+    GrDawnSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // Dawn info
+    info.fFormat = dawnSpec.fFormat;
+
+    return info;
+}
diff --git a/src/gpu/gl/GrGLTypesPriv.cpp b/src/gpu/gl/GrGLTypesPriv.cpp
index ce5ca4d..3034ddb 100644
--- a/src/gpu/gl/GrGLTypesPriv.cpp
+++ b/src/gpu/gl/GrGLTypesPriv.cpp
@@ -65,3 +65,20 @@
 }
 
 void GrGLBackendTextureInfo::cleanup() { SkSafeUnref(fParams); }
+
+GrGLSurfaceInfo GrGLTextureSpecToSurfaceInfo(const GrGLTextureSpec& glSpec,
+                                             uint32_t sampleCount,
+                                             uint32_t levelCount,
+                                             GrProtected isProtected) {
+    GrGLSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // GL info
+    info.fTarget = glSpec.fTarget;
+    info.fFormat = glSpec.fFormat;
+
+    return info;
+}
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index eb54aa7..e41834d 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -7,7 +7,6 @@
 
 #include "src/gpu/GrRenderTarget.h"
 #include "src/gpu/GrShaderCaps.h"
-#include "src/gpu/gl/GrGLGpu.h"
 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
diff --git a/src/gpu/mock/GrMockTypes.cpp b/src/gpu/mock/GrMockTypes.cpp
index 3f6caf7..098053a 100644
--- a/src/gpu/mock/GrMockTypes.cpp
+++ b/src/gpu/mock/GrMockTypes.cpp
@@ -16,3 +16,20 @@
 GrBackendFormat GrMockTextureInfo::getBackendFormat() const {
     return GrBackendFormat::MakeMock(fColorType, fCompressionType);
 }
+
+GrMockSurfaceInfo GrMockTextureSpecToSurfaceInfo(const GrMockTextureSpec& mockSpec,
+                                                 uint32_t sampleCount,
+                                                 uint32_t levelCount,
+                                                 GrProtected isProtected) {
+    GrMockSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // Mock info
+    info.fColorType = mockSpec.fColorType;
+    info.fCompressionType = mockSpec.fCompressionType;
+
+    return info;
+}
diff --git a/src/gpu/mtl/GrMtlTypesPriv.mm b/src/gpu/mtl/GrMtlTypesPriv.mm
new file mode 100644
index 0000000..54a68f3
--- /dev/null
+++ b/src/gpu/mtl/GrMtlTypesPriv.mm
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/private/GrMtlTypesPriv.h"
+
+GrMtlSurfaceInfo GrMtlTextureSpecToSurfaceInfo(const GrMtlTextureSpec& mtlSpec,
+                                               uint32_t sampleCount,
+                                               uint32_t levelCount,
+                                               GrProtected isProtected) {
+    GrMtlSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // Mtl info
+    info.fFormat = mtlSpec.fFormat;
+    info.fUsage = mtlSpec.fUsage;
+    info.fStorageMode = mtlSpec.fStorageMode;
+
+    return info;
+}
diff --git a/src/gpu/vk/GrVkTypesPriv.cpp b/src/gpu/vk/GrVkTypesPriv.cpp
index 9133a81..f1bfa30 100644
--- a/src/gpu/vk/GrVkTypesPriv.cpp
+++ b/src/gpu/vk/GrVkTypesPriv.cpp
@@ -25,6 +25,26 @@
     return newInfo;
 }
 
+GrVkSurfaceInfo GrVkImageSpecToSurfaceInfo(const GrVkImageSpec& vkSpec,
+                                           uint32_t sampleCount,
+                                           uint32_t levelCount,
+                                           GrProtected isProtected) {
+    GrVkSurfaceInfo info;
+    // Shared info
+    info.fSampleCount = sampleCount;
+    info.fLevelCount = levelCount;
+    info.fProtected = isProtected;
+
+    // Vulkan info
+    info.fImageTiling = vkSpec.fImageTiling;
+    info.fFormat = vkSpec.fFormat;
+    info.fImageUsageFlags = vkSpec.fImageUsageFlags;
+    info.fYcbcrConversionInfo = vkSpec.fYcbcrConversionInfo;
+    info.fSharingMode = vkSpec.fSharingMode;
+
+    return info;
+}
+
 #if GR_TEST_UTILS
 bool GrVkBackendSurfaceInfo::operator==(const GrVkBackendSurfaceInfo& that) const {
     GrVkImageInfo cpyInfoThis = fImageInfo;
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index ce2c1de..23fdd57 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -190,6 +190,7 @@
             GrBackendTexture genBackendTex = genTexture->getBackendTexture();
 
             if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
+#ifdef SK_GL
                 GrGLTextureInfo genTexInfo;
                 GrGLTextureInfo origTexInfo;
                 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
@@ -203,6 +204,7 @@
                 } else {
                     ERRORF(reporter, "Failed to get GrGLTextureInfo");
                 }
+#endif
 #ifdef SK_VULKAN
             } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
                 GrVkImageInfo genImageInfo;
diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp
index 780b4e2..c3553ad 100644
--- a/tests/GrPorterDuffTest.cpp
+++ b/tests/GrPorterDuffTest.cpp
@@ -15,7 +15,6 @@
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrXferProcessor.h"
 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
-#include "src/gpu/gl/GrGLCaps.h"
 #include "tools/gpu/GrContextFactory.h"
 #include "tools/gpu/ManagedBackendTexture.h"
 
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index d0163b4..485d278 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -30,7 +30,6 @@
 #include "tools/gpu/dawn/DawnTestContext.h"
 #endif
 #include "src/gpu/GrCaps.h"
-#include "src/gpu/gl/GrGLGpu.h"
 #include "tools/gpu/mock/MockTestContext.h"
 
 #if defined(SK_BUILD_FOR_WIN) && defined(SK_ENABLE_DISCRETE_GPU)
diff --git a/tools/sk_app/MetalWindowContext.mm b/tools/sk_app/MetalWindowContext.mm
index 5b62381..c464c39 100644
--- a/tools/sk_app/MetalWindowContext.mm
+++ b/tools/sk_app/MetalWindowContext.mm
@@ -65,7 +65,6 @@
             fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
             if (!fPipelineArchive) {
                 (*desc).url = nil; // create new
-                NSError* error;
                 fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
                 if (!fPipelineArchive) {
                     SkDebugf("Error creating MTLBinaryArchive:\n%s\n",