Add kRGB_888X_GrPixelConfig

This is needed to support importing of RGBX AHB into skia's vulkan backend.
With this CL we only enable the new pixel config to be textureable.

Bug: skia:
Change-Id: Iba9180c14f3ef633ae846091cf453d68f82ce544
Reviewed-on: https://skia-review.googlesource.com/c/192035
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 53bc8ab..0445167 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -46,6 +46,7 @@
     kRGBA_4444_GrPixelConfig,
     kRGBA_8888_GrPixelConfig,
     kRGB_888_GrPixelConfig,
+    kRGB_888X_GrPixelConfig,
     kRG_88_GrPixelConfig,
     kBGRA_8888_GrPixelConfig,
     kSRGBA_8888_GrPixelConfig,
@@ -966,6 +967,7 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
@@ -1003,6 +1005,7 @@
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:  // Assuming GPUs store this 4-byte aligned.
+        case kRGB_888X_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
         case kSRGBA_8888_GrPixelConfig:
         case kSBGRA_8888_GrPixelConfig:
@@ -1026,6 +1029,7 @@
     switch (config) {
         case kRGB_565_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kGray_8_GrPixelConfig:
         case kGray_8_as_Lum_GrPixelConfig:
@@ -1069,6 +1073,7 @@
         case kRGBA_4444_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
         case kSRGBA_8888_GrPixelConfig:
@@ -1096,6 +1101,7 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
@@ -1133,6 +1139,7 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
@@ -1167,6 +1174,7 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
@@ -1207,6 +1215,7 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
@@ -1242,6 +1251,7 @@
         case kRGBA_4444_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
         case kSRGBA_8888_GrPixelConfig:
@@ -1405,6 +1415,9 @@
         case kRGB_888_GrPixelConfig:
             *srgbEncoded = GrSRGBEncoded::kNo;
             return GrColorType::kRGB_888x;
+        case kRGB_888X_GrPixelConfig:
+            *srgbEncoded = GrSRGBEncoded::kNo;
+            return GrColorType::kRGB_888x;
         case kRG_88_GrPixelConfig:
             *srgbEncoded = GrSRGBEncoded::kNo;
             return GrColorType::kRG_88;
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 638a70f..ec8c872 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -138,6 +138,7 @@
         case kRGBA_4444_GrPixelConfig: return "RGBA444";
         case kRGBA_8888_GrPixelConfig: return "RGBA8888";
         case kRGB_888_GrPixelConfig: return "RGB888";
+        case kRGB_888X_GrPixelConfig: return "RGB888X";
         case kRG_88_GrPixelConfig: return "RG88";
         case kBGRA_8888_GrPixelConfig: return "BGRA8888";
         case kSRGBA_8888_GrPixelConfig: return "SRGBA8888";
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index b502bf8..1ba47c8 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -282,6 +282,7 @@
         case kRGBA_4444_GrPixelConfig:          return true;
         case kRGBA_8888_GrPixelConfig:          return true;
         case kRGB_888_GrPixelConfig:            return false;
+        case kRGB_888X_GrPixelConfig:           return false;
         case kRG_88_GrPixelConfig:              return false;
         case kBGRA_8888_GrPixelConfig:          return true;
         case kSRGBA_8888_GrPixelConfig:         return true;
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 952dc00..f39b666 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -39,72 +39,60 @@
     return SkToU16(value);
 }
 
-static uint16_t sampler_key(GrTextureType textureType, GrPixelConfig config,
+static uint32_t sampler_key(GrTextureType textureType, GrPixelConfig config,
                             const GrShaderCaps& caps) {
     int samplerTypeKey = texture_type_key(textureType);
 
-    GR_STATIC_ASSERT(1 == sizeof(caps.configTextureSwizzle(config).asKey()));
-    return SkToU16(samplerTypeKey |
+    GR_STATIC_ASSERT(2 == sizeof(caps.configTextureSwizzle(config).asKey()));
+    return SkToU32(samplerTypeKey |
                    caps.configTextureSwizzle(config).asKey() << kSamplerOrImageTypeKeyBits |
-                   (GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits)));
+                   (GrSLSamplerPrecision(config) << (16 + kSamplerOrImageTypeKeyBits)));
 }
 
 static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrFragmentProcessor& fp,
                              GrGpu* gpu, const GrShaderCaps& caps) {
     int numTextureSamplers = fp.numTextureSamplers();
-    // Need two bytes per key.
-    int word32Count = (numTextureSamplers + 1) / 2;
-    if (0 == word32Count) {
+    if (!numTextureSamplers) {
         return;
     }
-    uint16_t* k16 = reinterpret_cast<uint16_t*>(b->add32n(word32Count));
+    uint32_t* k32 = b->add32n(numTextureSamplers);
     for (int i = 0; i < numTextureSamplers; ++i) {
         const GrFragmentProcessor::TextureSampler& sampler = fp.textureSampler(i);
         const GrTexture* tex = sampler.peekTexture();
-        k16[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps);
+        k32[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps);
         uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(
                 sampler.samplerState(), sampler.proxy()->backendFormat());
         if (extraSamplerKey) {
             SkASSERT(sampler.proxy()->textureType() == GrTextureType::kExternal);
             // We first mark the normal sampler key with last bit to flag that it has an extra
             // sampler key. We then add all the extraSamplerKeys to the end of the normal ones.
-            SkASSERT((k16[i] & (1 << 15)) == 0);
-            k16[i] = k16[i] | (1 << 15);
+            SkASSERT((k32[i] & (1 << 31)) == 0);
+            k32[i] = k32[i] | (1 << 31);
             b->add32(extraSamplerKey);
         }
     }
-    // zero the last 16 bits if the number of uniforms for samplers is odd.
-    if (numTextureSamplers & 0x1) {
-        k16[numTextureSamplers] = 0;
-    }
 }
 
 static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrPrimitiveProcessor& pp,
                              const GrShaderCaps& caps) {
     int numTextureSamplers = pp.numTextureSamplers();
-    // Need two bytes per key.
-    int word32Count = (numTextureSamplers + 1) / 2;
-    if (0 == word32Count) {
+    if (!numTextureSamplers) {
         return;
     }
-    uint16_t* k16 = reinterpret_cast<uint16_t*>(b->add32n(word32Count));
+    uint32_t* k32 = b->add32n(numTextureSamplers);
     for (int i = 0; i < numTextureSamplers; ++i) {
         const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i);
-        k16[i] = sampler_key(sampler.textureType(), sampler.config(), caps);
+        k32[i] = sampler_key(sampler.textureType(), sampler.config(), caps);
         uint32_t extraSamplerKey = sampler.extraSamplerKey();
         if (extraSamplerKey) {
             SkASSERT(sampler.textureType() == GrTextureType::kExternal);
             // We first mark the normal sampler key with last bit to flag that it has an extra
             // sampler key. We then add all the extraSamplerKeys to the end of the normal ones.
-            SkASSERT((k16[i] & (1 << 15)) == 0);
-            k16[i] = k16[i] | (1 << 15);
+            SkASSERT((k32[i] & (1 << 15)) == 0);
+            k32[i] = k32[i] | (1 << 15);
             b->add32(extraSamplerKey);
         }
     }
-    // zero the last 16 bits if the number of uniforms for samplers is odd.
-    if (numTextureSamplers & 0x1) {
-        k16[numTextureSamplers] = 0;
-    }
 }
 
 /**
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 08e03c9..274fcef 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -92,7 +92,7 @@
 
     struct KeyHeader {
         // Set to uniquely idenitify any swizzling of the shader's output color(s).
-        uint8_t fOutputSwizzle;
+        uint16_t fOutputSwizzle;
         uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
         uint8_t fCoverageFragmentProcessorCnt;
         // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
@@ -101,7 +101,7 @@
         bool fHasPointSize : 1;
         uint8_t fPad : 4;
     };
-    GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
+    GR_STATIC_ASSERT(sizeof(KeyHeader) == 6);
 
     // This should really only be used internally, base classes should return their own headers
     const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
diff --git a/src/gpu/GrSwizzle.h b/src/gpu/GrSwizzle.h
index 109c3a6..469740b 100644
--- a/src/gpu/GrSwizzle.h
+++ b/src/gpu/GrSwizzle.h
@@ -33,11 +33,11 @@
     }
 
     /** Recreates a GrSwizzle from the output of asKey() */
-    constexpr void setFromKey(uint8_t key) {
+    constexpr void setFromKey(uint16_t key) {
         fKey = key;
         for (int i = 0; i < 4; ++i) {
-            fSwiz[i] = IToC(key & 3);
-            key >>= 2;
+            fSwiz[i] = IToC(key & 15);
+            key >>= 4;
         }
         SkASSERT(fSwiz[4] == 0);
     }
@@ -46,7 +46,7 @@
     constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
 
     /** Compact representation of the swizzle suitable for a key. */
-    constexpr uint8_t asKey() const { return fKey; }
+    constexpr uint16_t asKey() const { return fKey; }
 
     /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
     const char* c_str() const { return fSwiz; }
@@ -56,22 +56,38 @@
         return fSwiz[i];
     }
 
+
+    // The normal component swizzles map to key values 0-3. We set the key for constant 1 to the
+    // next int.
+    static const int k1KeyValue = 4;
+
+    static float component_idx_to_float(const SkPMColor4f& color, int idx) {
+        if (idx <= 3) {
+            return color[idx];
+        }
+        if (idx == k1KeyValue) {
+            return 1.0f;
+        }
+        SK_ABORT("Unexpected swizzle component indx");
+        return -1.0f;
+    }
+
     /** Applies this swizzle to the input color and returns the swizzled color. */
     SkPMColor4f applyTo(const SkPMColor4f& color) const {
         int idx;
         uint32_t key = fKey;
         // Index of the input color that should be mapped to output r.
-        idx = (key & 3);
-        float outR = color[idx];
-        key >>= 2;
-        idx = (key & 3);
-        float outG = color[idx];
-        key >>= 2;
-        idx = (key & 3);
-        float outB = color[idx];
-        key >>= 2;
-        idx = (key & 3);
-        float outA = color[idx];
+        idx = (key & 15);
+        float outR = component_idx_to_float(color, idx);
+        key >>= 4;
+        idx = (key & 15);
+        float outG = component_idx_to_float(color, idx);
+        key >>= 4;
+        idx = (key & 15);
+        float outB = component_idx_to_float(color, idx);
+        key >>= 4;
+        idx = (key & 15);
+        float outA = component_idx_to_float(color, idx);
         return { outR, outG, outB, outA };
     }
 
@@ -81,10 +97,11 @@
     static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); }
     static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); }
     static constexpr GrSwizzle RGRG() { return GrSwizzle("rgrg"); }
+    static constexpr GrSwizzle RGB1() { return GrSwizzle("rgb1"); }
 
 private:
     char fSwiz[5];
-    uint8_t fKey;
+    uint16_t fKey;
 
     static constexpr int CToI(char c) {
         switch (c) {
@@ -92,23 +109,25 @@
             case 'g': return (GrColor_SHIFT_G / 8);
             case 'b': return (GrColor_SHIFT_B / 8);
             case 'a': return (GrColor_SHIFT_A / 8);
+            case '1': return k1KeyValue;
             default:  return -1;
         }
     }
 
     static constexpr char IToC(int idx) {
         switch (8 * idx) {
-            case GrColor_SHIFT_R : return 'r';
-            case GrColor_SHIFT_G : return 'g';
-            case GrColor_SHIFT_B : return 'b';
-            case GrColor_SHIFT_A : return 'a';
-            default:               return -1;
+            case GrColor_SHIFT_R  : return 'r';
+            case GrColor_SHIFT_G  : return 'g';
+            case GrColor_SHIFT_B  : return 'b';
+            case GrColor_SHIFT_A  : return 'a';
+            case (k1KeyValue * 8) : return '1';
+            default:                return -1;
         }
     }
 
     constexpr GrSwizzle(const char c[4])
             : fSwiz{c[0], c[1], c[2], c[3], '\0'}
-            , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 2) | (CToI(c[2]) << 4) | (CToI(c[3]) << 6)) {}
+            , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {}
 };
 
 #endif
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index dd18074..5994657 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -341,6 +341,7 @@
         case kGray_8_as_Red_GrPixelConfig:
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:
+        case kRGB_888X_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
             return 0;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index a3da939..31a05d1 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1480,6 +1480,13 @@
         fConfigTable[kRGB_888_GrPixelConfig].fFlags = 0;
     }
 
+    fConfigTable[kRGB_888X_GrPixelConfig] = fConfigTable[kRGBA_8888_GrPixelConfig];
+    fConfigTable[kRGB_888X_GrPixelConfig].fSwizzle = GrSwizzle::RGB1();
+    // Currently we don't allow RGB_888X to be renderable because we don't have a way to handle
+    // blends that reference the dst alpha when the values in the dst alpha channel are
+    // uninitialized.
+    fConfigTable[kRGB_888X_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag;
+
     // ES2 Command Buffer has several TexStorage restrictions. It appears to fail for any format
     // not explicitly allowed by GL_EXT_texture_storage, particularly those from other extensions.
     bool isCommandBufferES2 = kChromium_GrGLDriver == ctxInfo.driver() && version < GR_GL_VER(3, 0);
@@ -2850,6 +2857,9 @@
     // this as makes sense to increase performance and correctness.
     switch (fConfigTable[config].fFormatType) {
         case kNormalizedFixedPoint_FormatType:
+            if (kRGB_888X_GrPixelConfig == config) {
+                return GrColorType::kRGB_888x;
+            }
             return GrColorType::kRGBA_8888;
         case kFloat_FormatType:
             if ((kAlpha_half_GrPixelConfig == config ||
@@ -2939,6 +2949,8 @@
         case kRGB_888x_SkColorType:
             if (GR_GL_RGB8 == format) {
                 return kRGB_888_GrPixelConfig;
+            } else if (GR_GL_RGBA8 == format) {
+                return kRGB_888X_GrPixelConfig;
             }
             break;
         case kBGRA_8888_SkColorType:
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 7c4e12c..ebda8ac 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -870,6 +870,7 @@
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:  // We're really talking about GrColorType::kRGB_888x here.
+        case kRGB_888X_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
         case kSRGBA_8888_GrPixelConfig:
         case kSBGRA_8888_GrPixelConfig:
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 0ef3031..45ceb50 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -304,6 +304,8 @@
         } else {
             if (kGray_8_GrPixelConfig == config) {
                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRA();
+            } else if (kRGB_888X_GrPixelConfig == config) {
+                shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGB1();
             } else {
                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA();
             }
@@ -382,6 +384,10 @@
     info = &fConfigTable[kRGBA_8888_GrPixelConfig];
     info->fFlags = ConfigInfo::kAllFlags;
 
+    // RGB_888X uses RGBA8Unorm and we will swizzle the 1
+    info = &fConfigTable[kRGB_888X_GrPixelConfig];
+    info->fFlags = ConfigInfo::kTextureable_Flag;
+
     // BGRA_8888 uses BGRA8Unorm
     info = &fConfigTable[kBGRA_8888_GrPixelConfig];
     info->fFlags = ConfigInfo::kAllFlags;
@@ -460,6 +466,9 @@
             }
             break;
         case kRGB_888x_SkColorType:
+            if (MTLPixelFormatRGBA8Unorm == format) {
+                return kRGB_888X_GrPixelConfig;
+            }
             break;
         case kBGRA_8888_SkColorType:
             if (MTLPixelFormatBGRA8Unorm == format) {
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index fa43295..a622534 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -22,11 +22,6 @@
 bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format);
 
 /**
-* Returns the GrPixelConfig for the given Metal texture format
-*/
-GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format);
-
-/**
  * Returns a id<MTLTexture> to the MTLTexture pointed at by the const void*. Will use
  * __bridge_transfer if we are adopting ownership.
  */
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index 824bbf5..6739b51 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -33,6 +33,9 @@
         case kRGB_888_GrPixelConfig:
             // TODO: MTLPixelFormatRGB8Unorm
             return false;
+        case kRGB_888X_GrPixelConfig:
+            *format = MTLPixelFormatRGBA8Unorm;
+            return true;
         case kRG_88_GrPixelConfig:
             // TODO: MTLPixelFormatRG8Unorm
             return false;
@@ -99,46 +102,6 @@
     return false;
 }
 
-GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format) {
-    switch (format) {
-        case MTLPixelFormatRGBA8Unorm:
-            return kRGBA_8888_GrPixelConfig;
-        case MTLPixelFormatBGRA8Unorm:
-            return kBGRA_8888_GrPixelConfig;
-        case MTLPixelFormatRGBA8Unorm_sRGB:
-            return kSRGBA_8888_GrPixelConfig;
-        case MTLPixelFormatBGRA8Unorm_sRGB:
-            return kSBGRA_8888_GrPixelConfig;
-        case MTLPixelFormatRGB10A2Unorm:
-            return kRGBA_1010102_GrPixelConfig;
-#ifdef SK_BUILD_FOR_IOS
-        case MTLPixelFormatB5G6R5Unorm:
-            return kRGB_565_GrPixelConfig;
-        case MTLPixelFormatABGR4Unorm:
-            return kRGBA_4444_GrPixelConfig;
-#endif
-        case MTLPixelFormatRG8Unorm:
-            return kRG_88_GrPixelConfig;
-        case MTLPixelFormatR8Unorm:
-            // We currently set this to be Alpha_8 and have no way to go to Gray_8
-            return kAlpha_8_GrPixelConfig;
-        case MTLPixelFormatRGBA32Float:
-            return kRGBA_float_GrPixelConfig;
-        case MTLPixelFormatRG32Float:
-            return kRG_float_GrPixelConfig;
-        case MTLPixelFormatRGBA16Float:
-            return kRGBA_half_GrPixelConfig;
-        case MTLPixelFormatR16Float:
-            return kAlpha_half_GrPixelConfig;
-#ifdef SK_BUILD_FOR_IOS
-        case MTLPixelFormatETC2_RGB8:
-            return kRGB_ETC1_GrPixelConfig;
-#endif
-        default:
-            return kUnknown_GrPixelConfig;
-    }
-}
-
 id<MTLTexture> GrGetMTLTexture(const void* mtlTexture, GrWrapOwnership wrapOwnership) {
     if (GrWrapOwnership::kAdopt_GrWrapOwnership == wrapOwnership) {
         return (__bridge_transfer id<MTLTexture>)mtlTexture;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 1123325..55f632a 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -517,6 +517,8 @@
                 // only extra work is the swizzle in the shader for all operations.
                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::BGRA();
                 shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::BGRA();
+            } else if (kRGB_888X_GrPixelConfig == config) {
+                shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGB1();
             } else {
                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA();
             }
@@ -593,19 +595,27 @@
         VkFormat format;
         if (GrPixelConfigToVkFormat(static_cast<GrPixelConfig>(i), &format)) {
             if (!GrPixelConfigIsSRGB(static_cast<GrPixelConfig>(i)) || fSRGBSupport) {
-                fConfigTable[i].init(interface, physDev, properties, format);
+                bool disableRendering = false;
+                if (static_cast<GrPixelConfig>(i) == kRGB_888X_GrPixelConfig) {
+                    // Currently we don't allow RGB_888X to be renderable because we don't have a
+                    // way to handle blends that reference dst alpha when the values in the dst
+                    // alpha channel are uninitialized.
+                    disableRendering = true;
+                }
+                fConfigTable[i].init(interface, physDev, properties, format, disableRendering);
             }
         }
     }
 }
 
-void GrVkCaps::ConfigInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
+void GrVkCaps::ConfigInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags,
+                                           bool disableRendering) {
     if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
         SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
         *flags = *flags | kTextureable_Flag;
 
         // Ganesh assumes that all renderable surfaces are also texturable
-        if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
+        if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags) & !disableRendering) {
             *flags = *flags | kRenderable_Flag;
         }
     }
@@ -666,12 +676,13 @@
 void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface,
                                 VkPhysicalDevice physDev,
                                 const VkPhysicalDeviceProperties& properties,
-                                VkFormat format) {
+                                VkFormat format,
+                                bool disableRendering) {
     VkFormatProperties props;
     memset(&props, 0, sizeof(VkFormatProperties));
     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
-    InitConfigFlags(props.linearTilingFeatures, &fLinearFlags);
-    InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags);
+    InitConfigFlags(props.linearTilingFeatures, &fLinearFlags, disableRendering);
+    InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags, disableRendering);
     if (fOptimalFlags & kRenderable_Flag) {
         this->initSampleCounts(interface, physDev, properties, format);
     }
@@ -762,6 +773,9 @@
             if (VK_FORMAT_R8G8B8_UNORM == format) {
                 return kRGB_888_GrPixelConfig;
             }
+            if (VK_FORMAT_R8G8B8A8_UNORM == format) {
+                return kRGB_888X_GrPixelConfig;
+            }
             break;
         case kBGRA_8888_SkColorType:
             if (VK_FORMAT_B8G8R8A8_UNORM == format) {
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 2309541..41c31fb 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -191,8 +191,8 @@
         ConfigInfo() : fOptimalFlags(0), fLinearFlags(0) {}
 
         void init(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&,
-                  VkFormat);
-        static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags);
+                  VkFormat, bool disableRendering);
+        static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags, bool disableRendering);
         void initSampleCounts(const GrVkInterface*, VkPhysicalDevice,
                               const VkPhysicalDeviceProperties&, VkFormat);
 
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 3a820d9..934d858 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -611,9 +611,8 @@
 
     // For RGB_888x src data we are uploading it first to an RGBA texture and then copying it to the
     // dst RGB texture. Thus we do not upload mip levels for that.
-    if (dataColorType == GrColorType::kRGB_888x) {
-        SkASSERT(tex->imageFormat() == VK_FORMAT_R8G8B8_UNORM &&
-                 tex->config() == kRGB_888_GrPixelConfig);
+    if (dataColorType == GrColorType::kRGB_888x && tex->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
+        SkASSERT(tex->config() == kRGB_888_GrPixelConfig);
         // First check that we'll be able to do the copy to the to the R8G8B8 image in the end via a
         // blit or draw.
         if (!this->vkCaps().configCanBeDstofBlit(kRGB_888_GrPixelConfig, tex->isLinearTiled()) &&
@@ -681,7 +680,7 @@
     // For uploading RGB_888x data to an R8G8B8_UNORM texture we must first upload the data to an
     // R8G8B8A8_UNORM image and then copy it.
     sk_sp<GrVkTexture> copyTexture;
-    if (dataColorType == GrColorType::kRGB_888x) {
+    if (dataColorType == GrColorType::kRGB_888x && tex->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
         GrSurfaceDesc surfDesc;
         surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
         surfDesc.fWidth = width;
@@ -2066,9 +2065,8 @@
     // 32 bits, but the Vulkan format is only 24. So we first copy the surface into an R8G8B8A8
     // image and then do the read pixels from that.
     sk_sp<GrVkTextureRenderTarget> copySurface;
-    if (dstColorType == GrColorType::kRGB_888x) {
-        SkASSERT(image->imageFormat() == VK_FORMAT_R8G8B8_UNORM &&
-                 surface->config() == kRGB_888_GrPixelConfig);
+    if (dstColorType == GrColorType::kRGB_888x && image->imageFormat() == VK_FORMAT_R8G8B8_UNORM) {
+        SkASSERT(surface->config() == kRGB_888_GrPixelConfig);
 
         // Make a new surface that is RGBA to copy the RGB surface into.
         GrSurfaceDesc surfDesc;
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index 8dffe4c..cf8b9ec 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -25,6 +25,9 @@
         case kRGB_888_GrPixelConfig:
             *format = VK_FORMAT_R8G8B8_UNORM;
             return true;
+        case kRGB_888X_GrPixelConfig:
+            *format = VK_FORMAT_R8G8B8A8_UNORM;
+            return true;
         case kRG_88_GrPixelConfig:
             *format = VK_FORMAT_R8G8_UNORM;
             return true;
@@ -86,7 +89,8 @@
 bool GrVkFormatPixelConfigPairIsValid(VkFormat format, GrPixelConfig config) {
     switch (format) {
         case VK_FORMAT_R8G8B8A8_UNORM:
-            return kRGBA_8888_GrPixelConfig == config;
+            return kRGBA_8888_GrPixelConfig == config ||
+                   kRGB_888X_GrPixelConfig == config;
         case VK_FORMAT_B8G8R8A8_UNORM:
             return kBGRA_8888_GrPixelConfig == config;
         case VK_FORMAT_R8G8B8A8_SRGB:
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index e62d953..95f3794 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -88,6 +88,7 @@
         kRGBA_4444_GrPixelConfig,
         kRGBA_8888_GrPixelConfig,
         kRGB_888_GrPixelConfig,
+        kRGB_888X_GrPixelConfig,
         kRG_88_GrPixelConfig,
         kBGRA_8888_GrPixelConfig,
         kSRGBA_8888_GrPixelConfig,