Last tranche of new SkColorTypes

This CL adds:
    kAlpha_F16_SkColorType
    kRG_F16_SkColorType
    kRGBA_16161616_SkColorType,

which should be it for a while.

Bug: skia:9121
Change-Id: I81b9d46a202a76e9b7d7ca86495d72dbdae32576
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/241357
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/src/core/SkConvertPixels.cpp b/src/core/SkConvertPixels.cpp
index 0745eb7..1000d61 100644
--- a/src/core/SkConvertPixels.cpp
+++ b/src/core/SkConvertPixels.cpp
@@ -100,6 +100,7 @@
         case kRGB_565_SkColorType:
         case kRG_88_SkColorType:
         case kRG_1616_SkColorType:
+        case kRG_F16_SkColorType:
         case kRGB_888x_SkColorType:
         case kRGB_101010x_SkColorType: {
             for (int y = 0; y < srcInfo.height(); ++y) {
@@ -170,6 +171,30 @@
             }
             return true;
         }
+
+        case kAlpha_F16_SkColorType: {
+            auto srcF16 = (const uint16_t*) src;
+            for (int y = 0; y < srcInfo.height(); y++) {
+                for (int x = 0; x < srcInfo.width(); x++) {
+                    dst[x] = (uint8_t) (255.0f * SkHalfToFloat(srcF16[x]));
+                }
+                dst = SkTAddOffset<uint8_t>(dst, dstRB);
+                srcF16 = SkTAddOffset<const uint16_t>(srcF16, srcRB);
+            }
+            return true;
+        }
+
+        case kRGBA_16161616_SkColorType: {
+            auto src64 = (const uint64_t*) src;
+            for (int y = 0; y < srcInfo.height(); y++) {
+                for (int x = 0; x < srcInfo.width(); x++) {
+                    dst[x] = (src64[x] >> 48) >> 8;
+                }
+                dst = SkTAddOffset<uint8_t>(dst, dstRB);
+                src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
+            }
+            return true;
+        }
     }
     return false;
 }
diff --git a/src/core/SkImageInfo.cpp b/src/core/SkImageInfo.cpp
index 471b004..9979381 100644
--- a/src/core/SkImageInfo.cpp
+++ b/src/core/SkImageInfo.cpp
@@ -12,22 +12,25 @@
 
 int SkColorTypeBytesPerPixel(SkColorType ct) {
     switch (ct) {
-        case kUnknown_SkColorType:      return 0;
-        case kAlpha_8_SkColorType:      return 1;
-        case kRGB_565_SkColorType:      return 2;
-        case kARGB_4444_SkColorType:    return 2;
-        case kRGBA_8888_SkColorType:    return 4;
-        case kBGRA_8888_SkColorType:    return 4;
-        case kRGB_888x_SkColorType:     return 4;
-        case kRGBA_1010102_SkColorType: return 4;
-        case kRGB_101010x_SkColorType:  return 4;
-        case kGray_8_SkColorType:       return 1;
-        case kRGBA_F16Norm_SkColorType: return 8;
-        case kRGBA_F16_SkColorType:     return 8;
-        case kRGBA_F32_SkColorType:     return 16;
-        case kRG_88_SkColorType:        return 2;
-        case kAlpha_16_SkColorType:     return 2;
-        case kRG_1616_SkColorType:      return 4;
+        case kUnknown_SkColorType:       return 0;
+        case kAlpha_8_SkColorType:       return 1;
+        case kRGB_565_SkColorType:       return 2;
+        case kARGB_4444_SkColorType:     return 2;
+        case kRGBA_8888_SkColorType:     return 4;
+        case kBGRA_8888_SkColorType:     return 4;
+        case kRGB_888x_SkColorType:      return 4;
+        case kRGBA_1010102_SkColorType:  return 4;
+        case kRGB_101010x_SkColorType:   return 4;
+        case kGray_8_SkColorType:        return 1;
+        case kRGBA_F16Norm_SkColorType:  return 8;
+        case kRGBA_F16_SkColorType:      return 8;
+        case kRGBA_F32_SkColorType:      return 16;
+        case kRG_88_SkColorType:         return 2;
+        case kAlpha_16_SkColorType:      return 2;
+        case kRG_1616_SkColorType:       return 4;
+        case kAlpha_F16_SkColorType:     return 2;
+        case kRG_F16_SkColorType:        return 4;
+        case kRGBA_16161616_SkColorType: return 8;
     }
     SkUNREACHABLE;
 }
@@ -70,7 +73,8 @@
             alphaType = kUnknown_SkAlphaType;
             break;
         case kAlpha_8_SkColorType:         // fall-through
-        case kAlpha_16_SkColorType:
+        case kAlpha_16_SkColorType:        // fall-through
+        case kAlpha_F16_SkColorType:
             if (kUnpremul_SkAlphaType == alphaType) {
                 alphaType = kPremul_SkAlphaType;
             }
@@ -82,6 +86,7 @@
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType:
         case kRGBA_F32_SkColorType:
+        case kRGBA_16161616_SkColorType:
             if (kUnknown_SkAlphaType == alphaType) {
                 return false;
             }
@@ -89,6 +94,7 @@
         case kGray_8_SkColorType:
         case kRG_88_SkColorType:
         case kRG_1616_SkColorType:
+        case kRG_F16_SkColorType:
         case kRGB_565_SkColorType:
         case kRGB_888x_SkColorType:
         case kRGB_101010x_SkColorType:
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp
index a678950..d0c85c1 100644
--- a/src/core/SkMipMap.cpp
+++ b/src/core/SkMipMap.cpp
@@ -14,6 +14,7 @@
 #include "include/private/SkImageInfoPriv.h"
 #include "include/private/SkNx.h"
 #include "include/private/SkTo.h"
+#include "include/private/SkVx.h"
 #include "src/core/SkMathPriv.h"
 #include <new>
 
@@ -66,7 +67,20 @@
     }
 };
 
-struct ColorTypeFilter_F16 {
+struct ColorTypeFilter_Alpha_F16 {
+    typedef uint16_t Type;
+    static Sk4f Expand(uint16_t x) {
+        return SkHalfToFloat_finite_ftz((uint64_t) x); // expand out to four lanes
+
+    }
+    static uint16_t Compact(const Sk4f& x) {
+        uint64_t r;
+        SkFloatToHalf_finite_ftz(x).store(&r);
+        return r & 0xFFFF;  // but ignore the extra 3 here
+    }
+};
+
+struct ColorTypeFilter_RGBA_F16 {
     typedef uint64_t Type; // SkHalf x4
     static Sk4f Expand(uint64_t x) {
         return SkHalfToFloat_finite_ftz(x);
@@ -98,6 +112,30 @@
     }
 };
 
+struct ColorTypeFilter_F16F16 {
+    typedef uint32_t Type;
+    static Sk4f Expand(uint32_t x) {
+        return SkHalfToFloat_finite_ftz((uint64_t) x); // expand out to four lanes
+    }
+    static uint32_t Compact(const Sk4f& x) {
+        uint64_t r;
+        SkFloatToHalf_finite_ftz(x).store(&r);
+        return (uint32_t) (r & 0xFFFFFFFF);  // but ignore the extra 2 here
+    }
+};
+
+struct ColorTypeFilter_16161616 {
+    typedef uint64_t Type;
+    static skvx::Vec<4, uint32_t> Expand(uint64_t x) {
+        return skvx::cast<uint32_t>(skvx::Vec<4, uint16_t>::Load(&x));
+    }
+    static uint64_t Compact(const skvx::Vec<4, uint32_t>& x) {
+        uint64_t r;
+        skvx::cast<uint16_t>(x).store(&r);
+        return r;
+    }
+};
+
 struct ColorTypeFilter_16 {
     typedef uint16_t Type;
     static uint32_t Expand(uint16_t x) {
@@ -417,14 +455,14 @@
             break;
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType:
-            proc_1_2 = downsample_1_2<ColorTypeFilter_F16>;
-            proc_1_3 = downsample_1_3<ColorTypeFilter_F16>;
-            proc_2_1 = downsample_2_1<ColorTypeFilter_F16>;
-            proc_2_2 = downsample_2_2<ColorTypeFilter_F16>;
-            proc_2_3 = downsample_2_3<ColorTypeFilter_F16>;
-            proc_3_1 = downsample_3_1<ColorTypeFilter_F16>;
-            proc_3_2 = downsample_3_2<ColorTypeFilter_F16>;
-            proc_3_3 = downsample_3_3<ColorTypeFilter_F16>;
+            proc_1_2 = downsample_1_2<ColorTypeFilter_RGBA_F16>;
+            proc_1_3 = downsample_1_3<ColorTypeFilter_RGBA_F16>;
+            proc_2_1 = downsample_2_1<ColorTypeFilter_RGBA_F16>;
+            proc_2_2 = downsample_2_2<ColorTypeFilter_RGBA_F16>;
+            proc_2_3 = downsample_2_3<ColorTypeFilter_RGBA_F16>;
+            proc_3_1 = downsample_3_1<ColorTypeFilter_RGBA_F16>;
+            proc_3_2 = downsample_3_2<ColorTypeFilter_RGBA_F16>;
+            proc_3_3 = downsample_3_3<ColorTypeFilter_RGBA_F16>;
             break;
         case kRG_88_SkColorType:
             proc_1_2 = downsample_1_2<ColorTypeFilter_88>;
@@ -466,6 +504,36 @@
             proc_3_2 = downsample_3_2<ColorTypeFilter_1010102>;
             proc_3_3 = downsample_3_3<ColorTypeFilter_1010102>;
             break;
+        case kAlpha_F16_SkColorType:
+            proc_1_2 = downsample_1_2<ColorTypeFilter_Alpha_F16>;
+            proc_1_3 = downsample_1_3<ColorTypeFilter_Alpha_F16>;
+            proc_2_1 = downsample_2_1<ColorTypeFilter_Alpha_F16>;
+            proc_2_2 = downsample_2_2<ColorTypeFilter_Alpha_F16>;
+            proc_2_3 = downsample_2_3<ColorTypeFilter_Alpha_F16>;
+            proc_3_1 = downsample_3_1<ColorTypeFilter_Alpha_F16>;
+            proc_3_2 = downsample_3_2<ColorTypeFilter_Alpha_F16>;
+            proc_3_3 = downsample_3_3<ColorTypeFilter_Alpha_F16>;
+            break;
+        case kRG_F16_SkColorType:
+            proc_1_2 = downsample_1_2<ColorTypeFilter_F16F16>;
+            proc_1_3 = downsample_1_3<ColorTypeFilter_F16F16>;
+            proc_2_1 = downsample_2_1<ColorTypeFilter_F16F16>;
+            proc_2_2 = downsample_2_2<ColorTypeFilter_F16F16>;
+            proc_2_3 = downsample_2_3<ColorTypeFilter_F16F16>;
+            proc_3_1 = downsample_3_1<ColorTypeFilter_F16F16>;
+            proc_3_2 = downsample_3_2<ColorTypeFilter_F16F16>;
+            proc_3_3 = downsample_3_3<ColorTypeFilter_F16F16>;
+            break;
+        case kRGBA_16161616_SkColorType:
+            proc_1_2 = downsample_1_2<ColorTypeFilter_16161616>;
+            proc_1_3 = downsample_1_3<ColorTypeFilter_16161616>;
+            proc_2_1 = downsample_2_1<ColorTypeFilter_16161616>;
+            proc_2_2 = downsample_2_2<ColorTypeFilter_16161616>;
+            proc_2_3 = downsample_2_3<ColorTypeFilter_16161616>;
+            proc_3_1 = downsample_3_1<ColorTypeFilter_16161616>;
+            proc_3_2 = downsample_3_2<ColorTypeFilter_16161616>;
+            proc_3_3 = downsample_3_3<ColorTypeFilter_16161616>;
+            break;
         default:
             return nullptr;
     }
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index add2d60..876675c 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -102,6 +102,7 @@
         case kGray_8_SkColorType:
         case kRG_88_SkColorType:
         case kRG_1616_SkColorType:
+        case kRG_F16_SkColorType:
         case kRGB_565_SkColorType:
         case kRGB_888x_SkColorType:
         case kRGB_101010x_SkColorType:
@@ -112,10 +113,16 @@
         case kAlpha_16_SkColorType:
             value = static_cast<const uint16_t*>(srcPtr)[0] * (1.0f/65535);
             break;
+        case kAlpha_F16_SkColorType: {
+            SkHalf half = static_cast<const SkHalf*>(srcPtr)[0];
+            value = SkHalfToFloat(half);
+            break;
+        }
         case kARGB_4444_SkColorType: {
             uint16_t u16 = static_cast<const uint16_t*>(srcPtr)[0];
             value = SkGetPackedA4444(u16) * (1.0f/15);
-        } break;
+            break;
+        }
         case kRGBA_8888_SkColorType:
         case kBGRA_8888_SkColorType:
             value = static_cast<const uint8_t*>(srcPtr)[3] * (1.0f/255);
@@ -123,13 +130,20 @@
         case kRGBA_1010102_SkColorType: {
             uint32_t u32 = static_cast<const uint32_t*>(srcPtr)[0];
             value = (u32 >> 30) * (1.0f/3);
-        } break;
+            break;
+        }
+        case kRGBA_16161616_SkColorType: {
+            uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0];
+            value = (u64 >> 48) * (1.0f/65535);
+            break;
+        }
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType: {
             uint64_t px;
             memcpy(&px, srcPtr, sizeof(px));
             value = SkHalfToFloat_finite_ftz(px)[3];
-        } break;
+            break;
+        }
         case kRGBA_F32_SkColorType:
             value = static_cast<const float*>(srcPtr)[3];
             break;
@@ -267,6 +281,10 @@
             uint16_t value = *this->addr16(x, y);
             return SkColorSetA(0, value * (255 / 65535.0f));
         }
+        case kAlpha_F16_SkColorType: {
+            SkHalf value = *this->addr16(x, y);
+            return SkColorSetA(0, 255 * SkHalfToFloat(value));
+        }
         case kRGB_565_SkColorType: {
             return SkPixel16ToColor(*this->addr16(x, y));
         }
@@ -287,6 +305,12 @@
                  | (uint32_t)( ((value >> 16) & 0xffff) * (255/65535.0f) ) <<  8
                  | 0xff000000;
         }
+        case kRG_F16_SkColorType: {
+            uint32_t value = *this->addr32(x, y);
+            uint32_t r = 255 * SkHalfToFloat((value >>  0) & 0xffff);
+            uint32_t g = 255 * SkHalfToFloat((value >> 16) & 0xffff);
+            return (r << 16) | (g << 8) | 0xff000000;
+        }
         case kRGB_888x_SkColorType: {
             uint32_t value = *this->addr32(x, y);
             return SkSwizzle_RB(value | 0xff000000);
@@ -326,6 +350,23 @@
                  | (uint32_t)( b * 255.0f ) <<  0
                  | (uint32_t)( a * 255.0f ) << 24;
         }
+        case kRGBA_16161616_SkColorType: {
+            uint64_t value = *this->addr64(x, y);
+
+            float r = ((value      ) & 0xffff) * (1/65535.0f),
+                  g = ((value >> 16) & 0xffff) * (1/65535.0f),
+                  b = ((value >> 32) & 0xffff) * (1/65535.0f),
+                  a = ((value >> 48) & 0xffff) * (1/65535.0f);
+            if (a != 0 && needsUnpremul) {
+                r *= (1.0f/a);
+                g *= (1.0f/a);
+                b *= (1.0f/a);
+            }
+            return (uint32_t)( r * 255.0f ) << 16
+                 | (uint32_t)( g * 255.0f ) <<  8
+                 | (uint32_t)( b * 255.0f ) <<  0
+                 | (uint32_t)( a * 255.0f ) << 24;
+        }
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType: {
             const uint64_t* addr =
@@ -377,7 +418,7 @@
                 }
             }
             return true;
-        } break;
+        }
         case kAlpha_16_SkColorType: {
             unsigned a = 0xFFFF;
             for (int y = 0; y < height; ++y) {
@@ -390,11 +431,23 @@
                 }
             }
             return true;
-        } break;
+        }
+        case kAlpha_F16_SkColorType: {
+            for (int y = 0; y < height; ++y) {
+                const SkHalf* row = this->addr16(0, y);
+                for (int x = 0; x < width; ++x) {
+                    if (row[x] < SK_Half1) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
         case kRGB_565_SkColorType:
         case kGray_8_SkColorType:
         case kRG_88_SkColorType:
         case kRG_1616_SkColorType:
+        case kRG_F16_SkColorType:
         case kRGB_888x_SkColorType:
         case kRGB_101010x_SkColorType:
             return true;
@@ -411,7 +464,7 @@
                 }
             }
             return true;
-        } break;
+        }
         case kBGRA_8888_SkColorType:
         case kRGBA_8888_SkColorType: {
             SkPMColor c = (SkPMColor)~0;
@@ -464,6 +517,19 @@
             }
             return true;
         }
+        case kRGBA_16161616_SkColorType: {
+            uint16_t acc = 0xFFFF;
+            for (int y = 0; y < height; ++y) {
+                const uint64_t* row = this->addr64(0, y);
+                for (int x = 0; x < width; ++x) {
+                    acc &= (row[x] >> 48);
+                }
+                if (0xFFFF != acc) {
+                    return false;
+                }
+            }
+            return true;
+        }
         case kUnknown_SkColorType:
             SkDEBUGFAIL("");
             break;
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index 2fe3e6f..7fa573f 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -167,12 +167,15 @@
 
         case kAlpha_8_SkColorType:      this->append(load_a8,      ctx); break;
         case kAlpha_16_SkColorType:     this->append(load_a16,     ctx); break;
+        case kAlpha_F16_SkColorType:    this->append(load_af16,    ctx); break;
         case kRGB_565_SkColorType:      this->append(load_565,     ctx); break;
         case kARGB_4444_SkColorType:    this->append(load_4444,    ctx); break;
         case kRG_88_SkColorType:        this->append(load_rg88,    ctx); break;
         case kRG_1616_SkColorType:      this->append(load_rg1616,  ctx); break;
+        case kRG_F16_SkColorType:       this->append(load_rgf16,   ctx); break;
         case kRGBA_8888_SkColorType:    this->append(load_8888,    ctx); break;
         case kRGBA_1010102_SkColorType: this->append(load_1010102, ctx); break;
+        case kRGBA_16161616_SkColorType:this->append(load_16161616,ctx); break;
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType:     this->append(load_f16,     ctx); break;
         case kRGBA_F32_SkColorType:     this->append(load_f32,     ctx); break;
@@ -201,12 +204,15 @@
 
         case kAlpha_8_SkColorType:      this->append(load_a8_dst,      ctx); break;
         case kAlpha_16_SkColorType:     this->append(load_a16_dst,     ctx); break;
+        case kAlpha_F16_SkColorType:    this->append(load_af16_dst,    ctx); break;
         case kRGB_565_SkColorType:      this->append(load_565_dst,     ctx); break;
         case kARGB_4444_SkColorType:    this->append(load_4444_dst,    ctx); break;
         case kRG_88_SkColorType:        this->append(load_rg88_dst,    ctx); break;
         case kRG_1616_SkColorType:      this->append(load_rg1616_dst,  ctx); break;
+        case kRG_F16_SkColorType:       this->append(load_rgf16_dst,   ctx); break;
         case kRGBA_8888_SkColorType:    this->append(load_8888_dst,    ctx); break;
         case kRGBA_1010102_SkColorType: this->append(load_1010102_dst, ctx); break;
+        case kRGBA_16161616_SkColorType:this->append(load_16161616_dst,ctx); break;
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType:     this->append(load_f16_dst,     ctx); break;
         case kRGBA_F32_SkColorType:     this->append(load_f32_dst,     ctx); break;
@@ -235,12 +241,15 @@
 
         case kAlpha_8_SkColorType:      this->append(store_a8,      ctx); break;
         case kAlpha_16_SkColorType:     this->append(store_a16,     ctx); break;
+        case kAlpha_F16_SkColorType:    this->append(store_af16,    ctx); break;
         case kRGB_565_SkColorType:      this->append(store_565,     ctx); break;
         case kARGB_4444_SkColorType:    this->append(store_4444,    ctx); break;
         case kRG_88_SkColorType:        this->append(store_rg88,    ctx); break;
         case kRG_1616_SkColorType:      this->append(store_rg1616,  ctx); break;
+        case kRG_F16_SkColorType:       this->append(store_rgf16,   ctx); break;
         case kRGBA_8888_SkColorType:    this->append(store_8888,    ctx); break;
         case kRGBA_1010102_SkColorType: this->append(store_1010102, ctx); break;
+        case kRGBA_16161616_SkColorType:this->append(store_16161616,ctx); break;
         case kRGBA_F16Norm_SkColorType:
         case kRGBA_F16_SkColorType:     this->append(store_f16,     ctx); break;
         case kRGBA_F32_SkColorType:     this->append(store_f32,     ctx); break;
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 22f24b0..82fee3e 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -48,15 +48,15 @@
     M(load_565)    M(load_565_dst)  M(store_565)   M(gather_565)   \
     M(load_4444)   M(load_4444_dst) M(store_4444)  M(gather_4444)  \
     M(load_f16)    M(load_f16_dst)  M(store_f16)   M(gather_f16)   \
-    M(load_af16)                    M(store_af16)                  \
-    M(load_rgf16)                   M(store_rgf16)                 \
+    M(load_af16)   M(load_af16_dst) M(store_af16)  M(gather_af16)  \
+    M(load_rgf16)  M(load_rgf16_dst) M(store_rgf16) M(gather_rgf16) \
     M(load_f32)    M(load_f32_dst)  M(store_f32)   M(gather_f32)   \
     M(load_rgf32)                   M(store_rgf32)                 \
     M(load_8888)   M(load_8888_dst) M(store_8888)  M(gather_8888)  \
     M(load_rg88)   M(load_rg88_dst) M(store_rg88)  M(gather_rg88)  \
     M(load_a16)    M(load_a16_dst)  M(store_a16)   M(gather_a16)   \
     M(load_rg1616) M(load_rg1616_dst) M(store_rg1616) M(gather_rg1616) \
-    M(load_16161616)                M(store_16161616)              \
+    M(load_16161616) M(load_16161616_dst) M(store_16161616) M(gather_16161616) \
     M(load_1010102) M(load_1010102_dst) M(store_1010102) M(gather_1010102) \
     M(alpha_to_gray) M(alpha_to_gray_dst) M(bt709_luminance_or_luma_to_alpha)         \
     M(bilerp_clamp_8888) M(bicubic_clamp_8888)                     \
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index 51292ad..724437b 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -299,7 +299,7 @@
             uint32_t rHalf = SkFloatToHalf(colorf.fR);
             uint32_t gHalf = SkFloatToHalf(colorf.fG);
 
-            uint32_t rgHalf = (rHalf << 16) | gHalf;
+            uint32_t rgHalf = (gHalf << 16) | rHalf;
 
             sk_memset32((uint32_t *) dest, rgHalf, width * height);
             break;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 41257f0..750e554 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -263,9 +263,14 @@
             return kRG_1616_GrPixelConfig;
         case kAlpha_16_SkColorType:
             return kAlpha_16_GrPixelConfig;
+        case kAlpha_F16_SkColorType:
+            return kAlpha_half_GrPixelConfig;
+        case kRG_F16_SkColorType:
+            return kRG_half_GrPixelConfig;
+        case kRGBA_16161616_SkColorType:
+            return kRGBA_16161616_GrPixelConfig;
     }
-    SkASSERT(0);    // shouldn't get here
-    return kUnknown_GrPixelConfig;
+    SkUNREACHABLE;
 }
 
 GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info) {
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index fbadae3..c2bffff 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -970,6 +970,7 @@
         case MTLPixelFormatBGRA8Unorm:        return GrColorType::kBGRA_8888;
         case MTLPixelFormatRGB10A2Unorm:      return GrColorType::kRGBA_1010102;
         case MTLPixelFormatR16Unorm:          return GrColorType::kAlpha_16;
+        case MTLPixelFormatR16Float:          return GrColorType::kAlpha_F16;
         case MTLPixelFormatRG16Unorm:         return GrColorType::kRG_1616;
         // Experimental (for Y416 and mutant P016/P010)
         case MTLPixelFormatRGBA16Unorm:       return GrColorType::kRGBA_16161616;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 1ec7371..738f461 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1584,6 +1584,7 @@
         case VK_FORMAT_B8G8R8A8_UNORM:           return GrColorType::kBGRA_8888;
         case VK_FORMAT_A2B10G10R10_UNORM_PACK32: return GrColorType::kRGBA_1010102;
         case VK_FORMAT_R16_UNORM:                return GrColorType::kAlpha_16;
+        case VK_FORMAT_R16_SFLOAT:               return GrColorType::kAlpha_F16;
         case VK_FORMAT_R16G16_UNORM:             return GrColorType::kRG_1616;
         // Experimental (for Y416 and mutant P016/P010)
         case VK_FORMAT_R16G16B16A16_UNORM:       return GrColorType::kRGBA_16161616;
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index 2ba4c5f..c587e82 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -44,7 +44,10 @@
 
     if (info.colorType() == kRG_88_SkColorType ||
         info.colorType() == kRG_1616_SkColorType ||
-        info.colorType() == kAlpha_16_SkColorType) {
+        info.colorType() == kRG_F16_SkColorType ||
+        info.colorType() == kAlpha_16_SkColorType ||
+        info.colorType() == kAlpha_F16_SkColorType ||
+        info.colorType() == kRGBA_16161616_SkColorType) {
         return false;
     }
 
diff --git a/src/images/SkPngEncoder.cpp b/src/images/SkPngEncoder.cpp
index 79e9812..20c1a5f 100644
--- a/src/images/SkPngEncoder.cpp
+++ b/src/images/SkPngEncoder.cpp
@@ -317,7 +317,10 @@
             return transform_scanline_A8_to_GrayAlpha;
         case kRG_88_SkColorType:
         case kRG_1616_SkColorType:
+        case kRG_F16_SkColorType:
         case kAlpha_16_SkColorType:
+        case kAlpha_F16_SkColorType:
+        case kRGBA_16161616_SkColorType:
             return nullptr;
     }
     SkASSERT(false);
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index f43b556..ee4d00a 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -2031,7 +2031,7 @@
 }
 
 STAGE(load_rg1616, const SkRasterPipeline_MemoryCtx* ctx) {
-    auto ptr = ptr_at_xy<const uint32_t>(ctx, dx,dy);
+    auto ptr = ptr_at_xy<const uint32_t>(ctx, dx, dy);
     b = 0; a = 1;
     from_1616(load<U32>(ptr, tail), &r,&g);
 }
@@ -2057,9 +2057,18 @@
 }
 
 STAGE(load_16161616, const SkRasterPipeline_MemoryCtx* ctx) {
-    auto ptr = ptr_at_xy<const uint64_t>(ctx, dx,dy);
+    auto ptr = ptr_at_xy<const uint64_t>(ctx, dx, dy);
     from_16161616(load<U64>(ptr, tail), &r,&g, &b, &a);
 }
+STAGE(load_16161616_dst, const SkRasterPipeline_MemoryCtx* ctx) {
+    auto ptr = ptr_at_xy<const uint64_t>(ctx, dx, dy);
+    from_16161616(load<U64>(ptr, tail), &dr, &dg, &db, &da);
+}
+STAGE(gather_16161616, const SkRasterPipeline_GatherCtx* ctx) {
+    const uint64_t* ptr;
+    U32 ix = ix_and_ptr(&ptr, ctx, r, g);
+    from_16161616(gather(ptr, ix), &r, &g, &b, &a);
+}
 STAGE(store_16161616, const SkRasterPipeline_MemoryCtx* ctx) {
     auto ptr = ptr_at_xy<uint16_t>(ctx, 4*dx,4*dy);
 
@@ -2155,23 +2164,58 @@
     b = 0;
     a = from_half(A);
 }
+STAGE(load_af16_dst, const SkRasterPipeline_MemoryCtx* ctx) {
+    auto ptr = ptr_at_xy<const uint16_t>(ctx, dx, dy);
+
+    U16 A = load<U16>((const uint16_t*)ptr, tail);
+    dr = dg = db = 0.0f;
+    da = from_half(A);
+}
+STAGE(gather_af16, const SkRasterPipeline_GatherCtx* ctx) {
+    const uint16_t* ptr;
+    U32 ix = ix_and_ptr(&ptr, ctx, r, g);
+    r = g = b = 0.0f;
+    a = from_half(gather(ptr, ix));
+}
 STAGE(store_af16, const SkRasterPipeline_MemoryCtx* ctx) {
     auto ptr = ptr_at_xy<uint16_t>(ctx, dx,dy);
     store(ptr, to_half(a), tail);
 }
 
 STAGE(load_rgf16, const SkRasterPipeline_MemoryCtx* ctx) {
-    auto ptr = ptr_at_xy<const uint32_t>(ctx, dx,dy);
+    auto ptr = ptr_at_xy<const uint32_t>(ctx, dx, dy);
 
     U16 R,G;
-    load2((const uint16_t*)ptr,tail, &R,&G);
+    load2((const uint16_t*)ptr, tail, &R, &G);
     r = from_half(R);
     g = from_half(G);
     b = 0;
-    a = from_half(0x3C00); // one
+    a = 1;
+}
+STAGE(load_rgf16_dst, const SkRasterPipeline_MemoryCtx* ctx) {
+    auto ptr = ptr_at_xy<const uint32_t>(ctx, dx, dy);
+
+    U16 R,G;
+    load2((const uint16_t*)ptr, tail, &R, &G);
+    dr = from_half(R);
+    dg = from_half(G);
+    db = 0;
+    da = 1;
+}
+STAGE(gather_rgf16, const SkRasterPipeline_GatherCtx* ctx) {
+    const uint32_t* ptr;
+    U32 ix = ix_and_ptr(&ptr, ctx, r, g);
+    auto px = gather(ptr, ix);
+
+    U16 R,G;
+    load2((const uint16_t*)&px, 0, &R, &G);
+    r = from_half(R);
+    g = from_half(G);
+    b = 0;
+    a = 1;
 }
 STAGE(store_rgf16, const SkRasterPipeline_MemoryCtx* ctx) {
-    auto ptr = ptr_at_xy<uint32_t>(ctx, dx,dy);
+    auto ptr = ptr_at_xy<uint32_t>(ctx, dx, dy);
     store2((uint16_t*)ptr, tail, to_half(r)
                                , to_half(g));
 }
@@ -4141,7 +4185,9 @@
     NOT_IMPLEMENTED(from_srgb)
     NOT_IMPLEMENTED(to_srgb)
     NOT_IMPLEMENTED(load_16161616)
+    NOT_IMPLEMENTED(load_16161616_dst)
     NOT_IMPLEMENTED(store_16161616)
+    NOT_IMPLEMENTED(gather_16161616)
     NOT_IMPLEMENTED(load_a16)
     NOT_IMPLEMENTED(load_a16_dst)
     NOT_IMPLEMENTED(store_a16)
@@ -4155,9 +4201,13 @@
     NOT_IMPLEMENTED(store_f16)
     NOT_IMPLEMENTED(gather_f16)
     NOT_IMPLEMENTED(load_af16)
+    NOT_IMPLEMENTED(load_af16_dst)
     NOT_IMPLEMENTED(store_af16)
+    NOT_IMPLEMENTED(gather_af16)
     NOT_IMPLEMENTED(load_rgf16)
+    NOT_IMPLEMENTED(load_rgf16_dst)
     NOT_IMPLEMENTED(store_rgf16)
+    NOT_IMPLEMENTED(gather_rgf16)
     NOT_IMPLEMENTED(load_f32)
     NOT_IMPLEMENTED(load_f32_dst)
     NOT_IMPLEMENTED(store_f32)
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 0f463a9..5b6d6c8 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -422,12 +422,15 @@
         switch (info.colorType()) {
             case kAlpha_8_SkColorType:      p->append(SkRasterPipeline::gather_a8,      ctx); break;
             case kAlpha_16_SkColorType:     p->append(SkRasterPipeline::gather_a16,     ctx); break;
+            case kAlpha_F16_SkColorType:    p->append(SkRasterPipeline::gather_af16,    ctx); break;
             case kRGB_565_SkColorType:      p->append(SkRasterPipeline::gather_565,     ctx); break;
             case kARGB_4444_SkColorType:    p->append(SkRasterPipeline::gather_4444,    ctx); break;
             case kRG_88_SkColorType:        p->append(SkRasterPipeline::gather_rg88,    ctx); break;
             case kRG_1616_SkColorType:      p->append(SkRasterPipeline::gather_rg1616,  ctx); break;
+            case kRG_F16_SkColorType:       p->append(SkRasterPipeline::gather_rgf16,  ctx); break;
             case kRGBA_8888_SkColorType:    p->append(SkRasterPipeline::gather_8888,    ctx); break;
             case kRGBA_1010102_SkColorType: p->append(SkRasterPipeline::gather_1010102, ctx); break;
+            case kRGBA_16161616_SkColorType:p->append(SkRasterPipeline::gather_16161616,ctx); break;
             case kRGBA_F16Norm_SkColorType:
             case kRGBA_F16_SkColorType:     p->append(SkRasterPipeline::gather_f16,     ctx); break;
             case kRGBA_F32_SkColorType:     p->append(SkRasterPipeline::gather_f32,     ctx); break;