Add clamped half-float pixel config to Ganesh

Currently doesn't do any clamping, but connects the new config to the
recently added SkColorType. Behavioral changes coming in future CLs.

Bug: skia:
Change-Id: I907396030c435d0aa5931063b3dc6f1b60c661af
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/199980
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 9e2d3a2..06c7080 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -57,6 +57,7 @@
     kAlpha_half_GrPixelConfig,
     kAlpha_half_as_Red_GrPixelConfig,
     kRGBA_half_GrPixelConfig,
+    kRGBA_half_Clamped_GrPixelConfig,
     kRGB_ETC1_GrPixelConfig,
 
     kLast_GrPixelConfig = kRGB_ETC1_GrPixelConfig
@@ -889,6 +890,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
         case kRGB_ETC1_GrPixelConfig:
             return GrSRGBEncoded::kNo;
     }
@@ -924,6 +926,7 @@
         case kRGBA_1010102_GrPixelConfig:
             return 4;
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return 8;
         case kRGBA_float_GrPixelConfig:
             return 16;
@@ -961,6 +964,7 @@
         case kSBGRA_8888_GrPixelConfig:
         case kRGBA_1010102_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
         case kRGBA_float_GrPixelConfig:
         case kUnknown_GrPixelConfig:
             return false;
@@ -994,6 +998,7 @@
         case kRGBA_float_GrPixelConfig:
         case kRG_float_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
         case kRGB_ETC1_GrPixelConfig:
             return false;
     }
@@ -1027,6 +1032,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return true;
     }
     SK_ABORT("Invalid pixel config.");
@@ -1063,6 +1069,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return false;
     }
     SK_ABORT("Invalid pixel config");
@@ -1098,6 +1105,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return config;
         }
     SK_ABORT("Invalid pixel config");
@@ -1139,6 +1147,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             SK_ABORT("Unknown compressed pixel config");
             return 4 * width * height;
     }
@@ -1176,6 +1185,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
         case kRGBA_1010102_GrPixelConfig:
             return kMedium_GrSLPrecision;
     }
@@ -1203,6 +1213,7 @@
     kGray_8,
     kAlpha_F16,
     kRGBA_F16,
+    kRGBA_F16_Clamped,
     kRG_F32,
     kRGBA_F32,
     kRGB_ETC1,   // This type doesn't appear in SkColorType at all.
@@ -1210,21 +1221,22 @@
 
 static inline SkColorType GrColorTypeToSkColorType(GrColorType ct) {
     switch (ct) {
-        case GrColorType::kUnknown:      return kUnknown_SkColorType;
-        case GrColorType::kAlpha_8:      return kAlpha_8_SkColorType;
-        case GrColorType::kRGB_565:      return kRGB_565_SkColorType;
-        case GrColorType::kABGR_4444:    return kARGB_4444_SkColorType;
-        case GrColorType::kRGBA_8888:    return kRGBA_8888_SkColorType;
-        case GrColorType::kRGB_888x:     return kRGB_888x_SkColorType;
-        case GrColorType::kRG_88:        return kUnknown_SkColorType;
-        case GrColorType::kBGRA_8888:    return kBGRA_8888_SkColorType;
-        case GrColorType::kRGBA_1010102: return kRGBA_1010102_SkColorType;
-        case GrColorType::kGray_8:       return kGray_8_SkColorType;
-        case GrColorType::kAlpha_F16:    return kUnknown_SkColorType;
-        case GrColorType::kRGBA_F16:     return kRGBA_F16_SkColorType;
-        case GrColorType::kRG_F32:       return kUnknown_SkColorType;
-        case GrColorType::kRGBA_F32:     return kRGBA_F32_SkColorType;
-        case GrColorType::kRGB_ETC1:     return kUnknown_SkColorType;
+        case GrColorType::kUnknown:          return kUnknown_SkColorType;
+        case GrColorType::kAlpha_8:          return kAlpha_8_SkColorType;
+        case GrColorType::kRGB_565:          return kRGB_565_SkColorType;
+        case GrColorType::kABGR_4444:        return kARGB_4444_SkColorType;
+        case GrColorType::kRGBA_8888:        return kRGBA_8888_SkColorType;
+        case GrColorType::kRGB_888x:         return kRGB_888x_SkColorType;
+        case GrColorType::kRG_88:            return kUnknown_SkColorType;
+        case GrColorType::kBGRA_8888:        return kBGRA_8888_SkColorType;
+        case GrColorType::kRGBA_1010102:     return kRGBA_1010102_SkColorType;
+        case GrColorType::kGray_8:           return kGray_8_SkColorType;
+        case GrColorType::kAlpha_F16:        return kUnknown_SkColorType;
+        case GrColorType::kRGBA_F16:         return kRGBA_F16_SkColorType;
+        case GrColorType::kRGBA_F16_Clamped: return kRGBA_F16Norm_SkColorType;
+        case GrColorType::kRG_F32:           return kUnknown_SkColorType;
+        case GrColorType::kRGBA_F32:         return kRGBA_F32_SkColorType;
+        case GrColorType::kRGB_ETC1:         return kUnknown_SkColorType;
     }
     SK_ABORT("Invalid GrColorType");
     return kUnknown_SkColorType;
@@ -1240,7 +1252,7 @@
         case kRGB_888x_SkColorType:     return GrColorType::kRGB_888x;
         case kBGRA_8888_SkColorType:    return GrColorType::kBGRA_8888;
         case kGray_8_SkColorType:       return GrColorType::kGray_8;
-        case kRGBA_F16Norm_SkColorType: return GrColorType::kRGBA_F16;  // TODO(brianosman)
+        case kRGBA_F16Norm_SkColorType: return GrColorType::kRGBA_F16_Clamped;
         case kRGBA_F16_SkColorType:     return GrColorType::kRGBA_F16;
         case kRGBA_1010102_SkColorType: return GrColorType::kRGBA_1010102;
         case kRGB_101010x_SkColorType:  return GrColorType::kUnknown;
@@ -1252,23 +1264,24 @@
 
 static inline uint32_t GrColorTypeComponentFlags(GrColorType ct) {
     switch (ct) {
-        case GrColorType::kUnknown:      return 0;
-        case GrColorType::kAlpha_8:      return kAlpha_SkColorTypeComponentFlag;
-        case GrColorType::kRGB_565:      return kRGB_SkColorTypeComponentFlags;
-        case GrColorType::kABGR_4444:    return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kRGBA_8888:    return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kRGB_888x:     return kRGB_SkColorTypeComponentFlags;
-        case GrColorType::kRG_88:        return kRed_SkColorTypeComponentFlag |
-                                                kGreen_SkColorTypeComponentFlag;
-        case GrColorType::kBGRA_8888:    return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kRGBA_1010102: return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kGray_8:       return kGray_SkColorTypeComponentFlag;
-        case GrColorType::kAlpha_F16:    return kAlpha_SkColorTypeComponentFlag;
-        case GrColorType::kRGBA_F16:     return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kRG_F32:       return kRed_SkColorTypeComponentFlag |
-                                                kGreen_SkColorTypeComponentFlag;
-        case GrColorType::kRGBA_F32:     return kRGBA_SkColorTypeComponentFlags;
-        case GrColorType::kRGB_ETC1:     return kRGB_SkColorTypeComponentFlags;
+        case GrColorType::kUnknown:          return 0;
+        case GrColorType::kAlpha_8:          return kAlpha_SkColorTypeComponentFlag;
+        case GrColorType::kRGB_565:          return kRGB_SkColorTypeComponentFlags;
+        case GrColorType::kABGR_4444:        return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRGBA_8888:        return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRGB_888x:         return kRGB_SkColorTypeComponentFlags;
+        case GrColorType::kRG_88:            return kRed_SkColorTypeComponentFlag |
+                                                    kGreen_SkColorTypeComponentFlag;
+        case GrColorType::kBGRA_8888:        return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRGBA_1010102:     return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kGray_8:           return kGray_SkColorTypeComponentFlag;
+        case GrColorType::kAlpha_F16:        return kAlpha_SkColorTypeComponentFlag;
+        case GrColorType::kRGBA_F16:         return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRGBA_F16_Clamped: return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRG_F32:           return kRed_SkColorTypeComponentFlag |
+                                                    kGreen_SkColorTypeComponentFlag;
+        case GrColorType::kRGBA_F32:         return kRGBA_SkColorTypeComponentFlags;
+        case GrColorType::kRGB_ETC1:         return kRGB_SkColorTypeComponentFlags;
     }
     SK_ABORT("Invalid GrColorType");
     return kUnknown_SkColorType;
@@ -1284,21 +1297,22 @@
 
 static inline int GrColorTypeBytesPerPixel(GrColorType ct) {
     switch (ct) {
-        case GrColorType::kUnknown:      return 0;
-        case GrColorType::kRGB_ETC1:     return 0;
-        case GrColorType::kAlpha_8:      return 1;
-        case GrColorType::kRGB_565:      return 2;
-        case GrColorType::kABGR_4444:    return 2;
-        case GrColorType::kRGBA_8888:    return 4;
-        case GrColorType::kRGB_888x:     return 4;
-        case GrColorType::kRG_88:        return 2;
-        case GrColorType::kBGRA_8888:    return 4;
-        case GrColorType::kRGBA_1010102: return 4;
-        case GrColorType::kGray_8:       return 1;
-        case GrColorType::kAlpha_F16:    return 2;
-        case GrColorType::kRGBA_F16:     return 8;
-        case GrColorType::kRG_F32:       return 8;
-        case GrColorType::kRGBA_F32:     return 16;
+        case GrColorType::kUnknown:          return 0;
+        case GrColorType::kRGB_ETC1:         return 0;
+        case GrColorType::kAlpha_8:          return 1;
+        case GrColorType::kRGB_565:          return 2;
+        case GrColorType::kABGR_4444:        return 2;
+        case GrColorType::kRGBA_8888:        return 4;
+        case GrColorType::kRGB_888x:         return 4;
+        case GrColorType::kRG_88:            return 2;
+        case GrColorType::kBGRA_8888:        return 4;
+        case GrColorType::kRGBA_1010102:     return 4;
+        case GrColorType::kGray_8:           return 1;
+        case GrColorType::kAlpha_F16:        return 2;
+        case GrColorType::kRGBA_F16:         return 8;
+        case GrColorType::kRGBA_F16_Clamped: return 8;
+        case GrColorType::kRG_F32:           return 8;
+        case GrColorType::kRGBA_F32:         return 16;
     }
     SK_ABORT("Invalid GrColorType");
     return 0;
@@ -1358,6 +1372,9 @@
         case kRGBA_half_GrPixelConfig:
             *srgbEncoded = GrSRGBEncoded::kNo;
             return GrColorType::kRGBA_F16;
+        case kRGBA_half_Clamped_GrPixelConfig:
+            *srgbEncoded = GrSRGBEncoded::kNo;
+            return GrColorType::kRGBA_F16_Clamped;
         case kRGB_ETC1_GrPixelConfig:
             *srgbEncoded = GrSRGBEncoded::kNo;
             return GrColorType::kRGB_ETC1;
@@ -1442,6 +1459,10 @@
             return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
                                                         : kRGBA_half_GrPixelConfig;
 
+        case GrColorType::kRGBA_F16_Clamped:
+            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
+                                                        : kRGBA_half_Clamped_GrPixelConfig;
+
         case GrColorType::kRGB_ETC1:
             return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
                                                         : kRGB_ETC1_GrPixelConfig;
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index b6db18a..66d40ae 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -99,7 +99,8 @@
              kRGB_888_GrPixelConfig == config || kRGBA_4444_GrPixelConfig == config ||
              kRGB_565_GrPixelConfig == config || kSRGBA_8888_GrPixelConfig == config ||
              kSBGRA_8888_GrPixelConfig == config || kRGBA_half_GrPixelConfig == config ||
-             kAlpha_8_GrPixelConfig == config || kRGBA_1010102_GrPixelConfig == config);
+             kAlpha_8_GrPixelConfig == config || kRGBA_1010102_GrPixelConfig == config ||
+             kRGBA_half_Clamped_GrPixelConfig == config);
 
     return config;
 }
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index aaba016..4011b37 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -148,6 +148,7 @@
         case kAlpha_half_GrPixelConfig: return "AlphaHalf";
         case kAlpha_half_as_Red_GrPixelConfig: return "AlphaHalf_asRed";
         case kRGBA_half_GrPixelConfig: return "RGBAHalf";
+        case kRGBA_half_Clamped_GrPixelConfig: return "RGBAHalfClamped";
         case kRGB_ETC1_GrPixelConfig: return "RGBETC1";
     }
     SK_ABORT("Invalid pixel config");
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index 0726b4f..743b33d 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -229,21 +229,22 @@
 
 static bool valid_premul_color_type(GrColorType ct) {
     switch (ct) {
-        case GrColorType::kUnknown:      return false;
-        case GrColorType::kAlpha_8:      return false;
-        case GrColorType::kRGB_565:      return false;
-        case GrColorType::kABGR_4444:    return true;
-        case GrColorType::kRGBA_8888:    return true;
-        case GrColorType::kRGB_888x:     return false;
-        case GrColorType::kRG_88:        return false;
-        case GrColorType::kBGRA_8888:    return true;
-        case GrColorType::kRGBA_1010102: return true;
-        case GrColorType::kGray_8:       return false;
-        case GrColorType::kAlpha_F16:    return false;
-        case GrColorType::kRGBA_F16:     return true;
-        case GrColorType::kRG_F32:       return false;
-        case GrColorType::kRGBA_F32:     return true;
-        case GrColorType::kRGB_ETC1:     return false;
+        case GrColorType::kUnknown:          return false;
+        case GrColorType::kAlpha_8:          return false;
+        case GrColorType::kRGB_565:          return false;
+        case GrColorType::kABGR_4444:        return true;
+        case GrColorType::kRGBA_8888:        return true;
+        case GrColorType::kRGB_888x:         return false;
+        case GrColorType::kRG_88:            return false;
+        case GrColorType::kBGRA_8888:        return true;
+        case GrColorType::kRGBA_1010102:     return true;
+        case GrColorType::kGray_8:           return false;
+        case GrColorType::kAlpha_F16:        return false;
+        case GrColorType::kRGBA_F16:         return true;
+        case GrColorType::kRGBA_F16_Clamped: return true;
+        case GrColorType::kRG_F32:           return false;
+        case GrColorType::kRGBA_F32:         return true;
+        case GrColorType::kRGB_ETC1:         return false;
     }
     SK_ABORT("Invalid GrColorType");
     return false;
@@ -270,6 +271,7 @@
         case kRG_float_GrPixelConfig:           return false;
         case kAlpha_half_GrPixelConfig:         return false;
         case kRGBA_half_GrPixelConfig:          return true;
+        case kRGBA_half_Clamped_GrPixelConfig:  return true;
         case kRGB_ETC1_GrPixelConfig:           return false;
         case kAlpha_8_as_Alpha_GrPixelConfig:   return false;
         case kAlpha_8_as_Red_GrPixelConfig:     return false;
diff --git a/src/gpu/GrRecordingContext.cpp b/src/gpu/GrRecordingContext.cpp
index 9c25f33..5d907bf 100644
--- a/src/gpu/GrRecordingContext.cpp
+++ b/src/gpu/GrRecordingContext.cpp
@@ -248,6 +248,7 @@
         case kBGRA_8888_GrPixelConfig:
         case kRGBA_1010102_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return kRGBA_8888_GrPixelConfig;
         case kSBGRA_8888_GrPixelConfig:
             return kSRGBA_8888_GrPixelConfig;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 6fdfea5..609a14e 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -272,6 +272,7 @@
     if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
         color = xform->apply(color);
     }
+    // TODO: Should we clamp here if config is kRGBA_half_Clamped_GrPixelConfig?
     if (!GrPixelConfigIsFloatingPoint(colorSpaceInfo.config()) ||
         !caps.halfFloatVertexAttributeSupport()) {
         color = { SkTPin(color.fR, 0.0f, 1.0f),
@@ -306,8 +307,8 @@
             return kUnknown_GrPixelConfig;
         case kGray_8_SkColorType:
             return kGray_8_GrPixelConfig;
-        case kRGBA_F16Norm_SkColorType:  // TODO(brianosman): anything to do here?
-            return kRGBA_half_GrPixelConfig;
+        case kRGBA_F16Norm_SkColorType:
+            return kRGBA_half_Clamped_GrPixelConfig;
         case kRGBA_F16_SkColorType:
             return kRGBA_half_GrPixelConfig;
         case kRGBA_F32_SkColorType:
@@ -363,6 +364,7 @@
         case kRGBA_float_GrPixelConfig:
         case kRG_float_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
         case kRGB_ETC1_GrPixelConfig:
         case kAlpha_8_GrPixelConfig:
         case kAlpha_8_as_Alpha_GrPixelConfig:
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 308b46a..891c9ec 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1921,6 +1921,10 @@
     }
     fConfigTable[kRGBA_half_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
 
+    // kRGBA_half_Clamped is just distinguished by clamps added to the shader. At the API level,
+    // it's identical to kRGBA_half.
+    fConfigTable[kRGBA_half_Clamped_GrPixelConfig] = fConfigTable[kRGBA_half_GrPixelConfig];
+
     // Compressed texture support
 
     // glCompressedTexImage2D is available on all OpenGL ES devices. It is available on standard
@@ -2989,9 +2993,9 @@
                 return kGray_8_as_Red_GrPixelConfig;
             }
             break;
-        case kRGBA_F16Norm_SkColorType:  // TODO(brianosman): anything here?
+        case kRGBA_F16Norm_SkColorType:
             if (GR_GL_RGBA16F == format) {
-                return kRGBA_half_GrPixelConfig;
+                return kRGBA_half_Clamped_GrPixelConfig;
             }
             break;
         case kRGBA_F16_SkColorType:
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 1ae4a41..9107fd1 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -862,6 +862,7 @@
         case kAlpha_half_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
+        case kRGBA_half_Clamped_GrPixelConfig:
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kRGB_888_GrPixelConfig:  // We're really talking about GrColorType::kRGB_888x here.
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index b2e6970..cccc96e 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -423,6 +423,9 @@
     // RGBA_half uses RGBA16Float
     info = &fConfigTable[kRGBA_half_GrPixelConfig];
     info->fFlags = ConfigInfo::kAllFlags;
+
+    info = &fConfigTable[kRGBA_half_Clamped_GrPixelConfig];
+    info->fFlags = ConfigInfo::kAllFlags;
 }
 
 void GrMtlCaps::initStencilFormat(id<MTLDevice> physDev) {
@@ -489,13 +492,13 @@
                 return kGray_8_as_Red_GrPixelConfig;
             }
             break;
-        case kRGBA_F16Norm_SkColorType:  // TODO(brianosman): ?
-            if (MTLPixelFormatRG16Float == format) {
-                return kRGBA_half_GrPixelConfig;
+        case kRGBA_F16Norm_SkColorType:
+            if (MTLPixelFormatRGBA16Float == format) {
+                return kRGBA_half_Clamped_GrPixelConfig;
             }
             break;
         case kRGBA_F16_SkColorType:
-            if (MTLPixelFormatRG16Float == format) {
+            if (MTLPixelFormatRGBA16Float == format) {
                 return kRGBA_half_GrPixelConfig;
             }
             break;
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index 6739b51..aabd5ff 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -86,6 +86,9 @@
         case kRGBA_half_GrPixelConfig:
             *format = MTLPixelFormatRGBA16Float;
             return true;
+        case kRGBA_half_Clamped_GrPixelConfig:
+            *format = MTLPixelFormatRGBA16Float;
+            return true;
         case kAlpha_half_GrPixelConfig: // fall through
         case kAlpha_half_as_Red_GrPixelConfig:
             *format = MTLPixelFormatR16Float;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 0007ba9..165ea68 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -800,9 +800,9 @@
                 return kGray_8_as_Red_GrPixelConfig;
             }
             break;
-        case kRGBA_F16Norm_SkColorType:  // TODO(brianosman): ?
+        case kRGBA_F16Norm_SkColorType:
             if (VK_FORMAT_R16G16B16A16_SFLOAT == format) {
-                return kRGBA_half_GrPixelConfig;
+                return kRGBA_half_Clamped_GrPixelConfig;
             }
             break;
         case kRGBA_F16_SkColorType:
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index cf8b9ec..0fccb86 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -72,6 +72,9 @@
         case kRGBA_half_GrPixelConfig:
             *format = VK_FORMAT_R16G16B16A16_SFLOAT;
             return true;
+        case kRGBA_half_Clamped_GrPixelConfig:
+            *format = VK_FORMAT_R16G16B16A16_SFLOAT;
+            return true;
         case kRGB_ETC1_GrPixelConfig:
             // converting to ETC2 which is a superset of ETC1
             *format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
@@ -121,7 +124,8 @@
         case VK_FORMAT_R32G32_SFLOAT:
             return kRG_float_GrPixelConfig == config;
         case VK_FORMAT_R16G16B16A16_SFLOAT:
-            return kRGBA_half_GrPixelConfig == config;
+            return kRGBA_half_GrPixelConfig == config ||
+                   kRGBA_half_Clamped_GrPixelConfig == config;
         case VK_FORMAT_R16_SFLOAT:
             return kAlpha_half_GrPixelConfig == config ||
                    kAlpha_half_as_Red_GrPixelConfig == config;
diff --git a/tests/DeferredDisplayListTest.cpp b/tests/DeferredDisplayListTest.cpp
index 8adc90b..6aea20e 100644
--- a/tests/DeferredDisplayListTest.cpp
+++ b/tests/DeferredDisplayListTest.cpp
@@ -807,11 +807,6 @@
     for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
         SkColorType colorType = static_cast<SkColorType>(ct);
 
-        if (colorType == kRGBA_F16Norm_SkColorType) {
-            // TODO(brianosman): we can't yet distinguish F16 and F16Norm in this test.
-            continue;
-        }
-
         SurfaceParameters params(context->backend());
         params.setColorType(colorType);
         params.setColorSpace(nullptr);
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 9035cd7..ce12da6 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -99,6 +99,7 @@
         kAlpha_half_GrPixelConfig,
         kAlpha_half_as_Red_GrPixelConfig,
         kRGBA_half_GrPixelConfig,
+        kRGBA_half_Clamped_GrPixelConfig,
         kRGB_ETC1_GrPixelConfig,
     };
     GR_STATIC_ASSERT(kGrPixelConfigCnt == SK_ARRAY_COUNT(configs));