Add SkSurfaceCharacterization::isCompatible

Although the main change in this CL is the addition of GrCaps::areColorTypeAndFormatCompatible.

This is split out of:

https://skia-review.googlesource.com/c/skia/+/222781 (Add bridge between GrContext::createBackendTexture and SkSurface::MakeFromBackendTexture)

Change-Id: I2e50fff91eb07fb1358840e1a4a76dc138a2f195
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223932
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index 67e2209..275fc79 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -349,6 +349,8 @@
     virtual GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
                                                       SkColorType) const = 0;
 
+    virtual bool areColorTypeAndFormatCompatible(SkColorType ct, const GrBackendFormat&) const = 0;
+
     // TODO: replace validateBackendRenderTarget with calls to getConfigFromBackendFormat?
     // TODO: it seems like we could pass the full SkImageInfo and validate its colorSpace too
     // Returns kUnknown if a valid config could not be determined.
diff --git a/src/gpu/GrContextThreadSafeProxy.cpp b/src/gpu/GrContextThreadSafeProxy.cpp
index 8da3afe..8bf5afb 100644
--- a/src/gpu/GrContextThreadSafeProxy.cpp
+++ b/src/gpu/GrContextThreadSafeProxy.cpp
@@ -38,6 +38,8 @@
         return SkSurfaceCharacterization(); // return an invalid characterization
     }
 
+    SkASSERT(isTextureable || !isMipMapped);
+
     if (GrBackendApi::kOpenGL != backendFormat.backend() && willUseGLFBO0) {
         // The willUseGLFBO0 flags can only be used for a GL backend.
         return SkSurfaceCharacterization(); // return an invalid characterization
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index cb2cefa..c7d4de9 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -422,8 +422,8 @@
         // SkColorType are correct.
         return true;
     }
-    GrPixelConfig testConfig = caps->getConfigFromBackendFormat(format, colorType);
-    return testConfig != kUnknown_GrPixelConfig;
+
+    return caps->areColorTypeAndFormatCompatible(colorType, format);
 }
 #endif
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index a1dfca6..cba9277 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -3621,6 +3621,16 @@
     return validate_sized_format(fbInfo.fFormat, ct, fStandard);
 }
 
+bool GrGLCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+                                               const GrBackendFormat& format) const {
+    const GrGLenum* glFormat = format.getGLFormat();
+    if (!glFormat) {
+        return false;
+    }
+
+    return kUnknown_GrPixelConfig != validate_sized_format(*glFormat, ct, fStandard);
+}
+
 GrPixelConfig GrGLCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
                                                    SkColorType ct) const {
     const GrGLenum* glFormat = format.getGLFormat();
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index d9cb6e6..c3e8918 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -427,6 +427,8 @@
     GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
                                               SkColorType) const override;
 
+    bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
     GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
     GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
 
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index ff39757..b4b005f 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -124,6 +124,84 @@
         return kUnknown_GrPixelConfig;
     }
 
+    bool areColorTypeAndFormatCompatible(SkColorType ct,
+                                         const GrBackendFormat& format) const override {
+        const GrPixelConfig* mockFormat = format.getMockFormat();
+        if (!mockFormat) {
+            return kUnknown_GrPixelConfig;
+        }
+
+        switch (ct) {
+            case kUnknown_SkColorType:
+                return false;
+            case kAlpha_8_SkColorType:
+                if (kAlpha_8_GrPixelConfig == *mockFormat ||
+                    kAlpha_8_as_Alpha_GrPixelConfig == *mockFormat ||
+                    kAlpha_8_as_Red_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGB_565_SkColorType:
+                if (kRGB_565_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kARGB_4444_SkColorType:
+                if (kRGBA_4444_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGBA_8888_SkColorType:
+                if (kRGBA_8888_GrPixelConfig == *mockFormat ||
+                    kSRGBA_8888_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGB_888x_SkColorType:
+                if (kRGB_888X_GrPixelConfig == *mockFormat ||
+                    kRGB_888_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kBGRA_8888_SkColorType:
+                if (kBGRA_8888_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGBA_1010102_SkColorType:
+                if (kRGBA_1010102_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGB_101010x_SkColorType:
+                return false;
+            case kGray_8_SkColorType:
+                if (kGray_8_GrPixelConfig == *mockFormat ||
+                    kGray_8_as_Lum_GrPixelConfig == *mockFormat ||
+                    kGray_8_as_Red_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGBA_F16Norm_SkColorType:
+                if (kRGBA_half_Clamped_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGBA_F16_SkColorType:
+                if (kRGBA_half_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+            case kRGBA_F32_SkColorType:
+                if (kRGBA_float_GrPixelConfig == *mockFormat) {
+                    return true;
+                }
+                break;
+        }
+
+        return false;
+    }
+
     GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat& format,
                                              SkColorType ct) const override {
         const GrPixelConfig* mockFormat = format.getMockFormat();
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index adebbce..8de71ce 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -67,6 +67,8 @@
     GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
                                               SkColorType) const override;
 
+    bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
     GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
 
     GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index dc3469a..b662578 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -566,6 +566,17 @@
     return validate_sized_format(texture.pixelFormat, ct);
 }
 
+bool GrMtlCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+                                                const GrBackendFormat& format) const {
+    const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
+    if (!mtlFormat) {
+        return false;
+    }
+
+    return kUnknown_GrPixelConfig != validate_sized_format(*mtlFormat, ct);
+}
+
+
 GrPixelConfig GrMtlCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
                                                     SkColorType ct) const {
     const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 7d28cd8..aa4bac3 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1026,6 +1026,18 @@
     return validate_image_info(imageInfo.fFormat, ct, imageInfo.fYcbcrConversionInfo.isValid());
 }
 
+bool GrVkCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+                                               const GrBackendFormat& format) const {
+    const VkFormat* vkFormat = format.getVkFormat();
+    const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
+    if (!vkFormat || !ycbcrInfo) {
+        return false;
+    }
+
+    return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
+}
+
+
 GrPixelConfig GrVkCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
                                                    SkColorType ct) const {
     const VkFormat* vkFormat = format.getVkFormat();
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index c859121..771d8e9 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -164,6 +164,8 @@
     GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
                                               SkColorType) const override;
 
+    bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
     GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
     GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;