Add Ganesh support for LUM16F (take 2)

When Chrome has a LUM16F texture they tell Skia it is R16F. Although this has been working for them so far it causes trouble with some upcoming changes.

Change-Id: I2473f70e4f725128f143c2dfb08adb79f3c7c166
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228565
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index d8ad5f1..cfbfa9d 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -153,6 +153,7 @@
         case kRGBA_1010102_GrPixelConfig: return "RGBA1010102";
         case kRGBA_float_GrPixelConfig: return "RGBAFloat";
         case kAlpha_half_GrPixelConfig: return "AlphaHalf";
+        case kAlpha_half_as_Lum_GrPixelConfig: return "AlphaHalf_asLum";
         case kAlpha_half_as_Red_GrPixelConfig: return "AlphaHalf_asRed";
         case kRGBA_half_GrPixelConfig: return "RGBAHalf";
         case kRGBA_half_Clamped_GrPixelConfig: return "RGBAHalfClamped";
@@ -398,7 +399,8 @@
             break;
         case kAlpha_half_GrPixelConfig:
             compatible = kAlpha_half_GrPixelConfig == specificConfig || // bc of the mock context
-                         kAlpha_half_as_Red_GrPixelConfig == specificConfig;
+                         kAlpha_half_as_Red_GrPixelConfig == specificConfig ||
+                         kAlpha_half_as_Lum_GrPixelConfig == specificConfig;
             break;
         case kRGB_888_GrPixelConfig:
             compatible = kRGB_888_GrPixelConfig == specificConfig ||
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index 0ac04f8..939ac3b 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -235,6 +235,7 @@
             }
             break;
         }
+        case kAlpha_half_as_Lum_GrPixelConfig:                  // fall through
         case kAlpha_half_as_Red_GrPixelConfig:                  // fall through
         case kAlpha_half_GrPixelConfig: {
             SkHalf alphaHalf = SkFloatToHalf(colorf.fA);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d7fa9e7..188babe 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1374,6 +1374,8 @@
     uint32_t fpRenderFlags = (GR_IS_GR_GL(standard)) ? msaaRenderFlags : nonMSAARenderFlags;
 
     if (GR_IS_GR_GL(standard)) {
+        // TODO: it seems like GL_ARB_texture_float GL_ARB_color_buffer_float should be taken
+        // into account here
         if (version >= GR_GL_VER(3, 0)) {
             hasFP16Textures = true;
             halfFPRenderTargetSupport = HalfFPRenderTargetSupport::kAll;
@@ -1839,6 +1841,67 @@
         }
     }
 
+    // LUMINANCE16F
+    {
+        // NOTE: We disallow lum16f on ES devices if linear filtering modes are not
+        // supported. This is for simplicity, but a more granular approach is possible.
+        bool lum16FSupported = false;
+
+        if (GR_IS_GR_GL(standard)) {
+            if (version >= GR_GL_VER(3, 0)) {
+                lum16FSupported = true;
+            } else if (ctxInfo.hasExtension("GL_ARB_texture_float")) {
+                lum16FSupported = true;
+            }
+        } else if (GR_IS_GR_GL_ES(standard)) {
+            if (version >= GR_GL_VER(3, 0)) {
+                lum16FSupported = true;
+            } else if (ctxInfo.hasExtension("GL_OES_texture_float_linear") &&
+                       ctxInfo.hasExtension("GL_OES_texture_float")) {
+                lum16FSupported = true;
+            } else if (ctxInfo.hasExtension("GL_OES_texture_half_float_linear") &&
+                       ctxInfo.hasExtension("GL_OES_texture_half_float")) {
+                lum16FSupported = true;
+            }
+        } // No WebGL support
+
+        if (formatWorkarounds.fDisableLuminance16F) {
+            lum16FSupported = false;
+        }
+
+        FormatInfo& info = this->getFormatInfo(GrGLFormat::kLUMINANCE16F);
+        info.fFormatType = FormatType::kFloat;
+        info.fBaseInternalFormat = GR_GL_LUMINANCE;
+        info.fSizedInternalFormat = GR_GL_LUMINANCE16F;
+        info.fInternalFormatForTexImage =
+                texImageSupportsSizedInternalFormat ? GR_GL_LUMINANCE16F : GR_GL_LUMINANCE;
+        info.fInternalFormatForRenderbuffer =
+                renderbufferStorageSupportsSizedInternalFormat ? GR_GL_LUMINANCE16F
+                                                               : GR_GL_LUMINANCE;
+        info.fDefaultExternalType = halfFloatType;
+
+        if (lum16FSupported) {
+            info.fFlags = FormatInfo::kTextureable_Flag;
+        }
+        if (texStorageSupported &&
+            !formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
+            info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
+        }
+
+        if (lum16FSupported) {
+            // kAlpha_F16
+            {
+                uint32_t flags = ColorTypeInfo::kUploadData_Flag;
+                info.fColorTypeInfos.emplace_back(GrColorType::kAlpha_F16, flags);
+
+                int idx = static_cast<int>(GrColorType::kAlpha_F16);
+                if (fColorTypeToFormatTable[idx] == GrGLFormat::kUnknown) {
+                    this->setColorTypeFormat(GrColorType::kAlpha_F16, GrGLFormat::kLUMINANCE16F);
+                }
+            }
+        }
+    }
+
     // RGB8
     {
         FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGB8);
@@ -2461,17 +2524,38 @@
     rgbaF32Info.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RGBA;
     rgbaF32Info.fFormats.fExternalType = GR_GL_FLOAT;
 
-    GrGLenum redHalfExternalType;
-    if (GR_IS_GR_GL(standard) ||
-       (GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0))) {
-        redHalfExternalType = GR_GL_HALF_FLOAT;
-    } else {
-        redHalfExternalType = GR_GL_HALF_FLOAT_OES;
+    // single channel half formats
+    {
+        GrGLenum halfExternalType;
+        if (GR_IS_GR_GL(standard) ||
+            (GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0))) {
+            halfExternalType = GR_GL_HALF_FLOAT;
+        } else {
+            halfExternalType = GR_GL_HALF_FLOAT_OES;
+        }
+
+        // RED16F
+        {
+            ConfigInfo& redHalf = fConfigTable[kAlpha_half_as_Red_GrPixelConfig];
+            redHalf.fFormats.fExternalType = halfExternalType;
+            redHalf.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RED;
+
+            if (textureRedSupport) {
+                fConfigTable[kAlpha_half_GrPixelConfig] = redHalf;
+            }
+        }
+
+        // LUM16F
+        {
+            ConfigInfo& lumHalf = fConfigTable[kAlpha_half_as_Lum_GrPixelConfig];
+            lumHalf.fFormats.fExternalType = halfExternalType;
+            lumHalf.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_LUMINANCE;
+
+            if (!textureRedSupport) {
+                fConfigTable[kAlpha_half_GrPixelConfig] = lumHalf;
+            }
+        }
     }
-    ConfigInfo& redHalf = fConfigTable[kAlpha_half_as_Red_GrPixelConfig];
-    redHalf.fFormats.fExternalType = redHalfExternalType;
-    redHalf.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RED;
-    fConfigTable[kAlpha_half_GrPixelConfig] = redHalf;
 
     fConfigTable[kRGBA_half_GrPixelConfig].fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] =
         GR_GL_RGBA;
@@ -3225,6 +3309,11 @@
 
     // Mali-400 fails ReadPixels tests, mostly with non-0xFF alpha values when read as GL_RGBA8.
     formatWorkarounds->fDisableRGB8ForMali400 = kMali4xx_GrGLRenderer == ctxInfo.renderer();
+
+    // On the Intel Iris 6100, interacting with LUM16F seems to confuse the driver. After
+    // writing to/reading from a LUM16F texture reads from/writes to other formats behave
+    // erratically.
+    formatWorkarounds->fDisableLuminance16F = kIntelBroadwell_GrGLRenderer == ctxInfo.renderer();
 }
 
 void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
@@ -3411,6 +3500,8 @@
             return GrGLFormat::kLUMINANCE8;
         case kGray_8_as_Red_GrPixelConfig:
             return GrGLFormat::kR8;
+        case kAlpha_half_as_Lum_GrPixelConfig:
+            return GrGLFormat::kLUMINANCE16F;
         case kAlpha_half_as_Red_GrPixelConfig:
             return GrGLFormat::kR16F;
         case kRGB_ETC1_GrPixelConfig: {
@@ -3512,7 +3603,9 @@
             }
             break;
         case GrColorType::kAlpha_F16:
-            if (GR_GL_R16F == format) {
+            if (GR_GL_LUMINANCE16F == format) {
+                return kAlpha_half_as_Lum_GrPixelConfig;
+            } else if (GR_GL_R16F == format) {
                 return kAlpha_half_as_Red_GrPixelConfig;
             }
             break;
@@ -3610,6 +3703,9 @@
         case GR_GL_RGB10_A2:
             config = kRGBA_1010102_GrPixelConfig;
             break;
+        case GR_GL_LUMINANCE16F:
+            config = kAlpha_half_as_Lum_GrPixelConfig;
+            break;
         case GR_GL_R16F:
             config = kAlpha_half_as_Red_GrPixelConfig;
             break;
@@ -3688,7 +3784,7 @@
         case GrColorType::kGray_8:
             return GR_GL_LUMINANCE8 == format || GR_GL_R8 == format;
         case GrColorType::kAlpha_F16:
-            return GR_GL_R16F == format;
+            return GR_GL_R16F == format || GR_GL_LUMINANCE16F == format;
         case GrColorType::kRGBA_F16:
             return GR_GL_RGBA16F == format;
         case GrColorType::kRGBA_F16_Clamped:
@@ -3736,12 +3832,13 @@
             }
             break;
         case GrColorType::kAlpha_F16:
-            SkASSERT(glFormat == GR_GL_R16F);
+            SkASSERT(glFormat == GR_GL_R16F || glFormat == GR_GL_LUMINANCE16F);
             if (forOutput) {
                 return GrSwizzle::AAAA();
             } else {
                 return GrSwizzle::RRRR();
             }
+            break;
         case GrColorType::kGray_8:
             if (glFormat == GR_GL_R8) {
                 if (!forOutput) {
@@ -3753,9 +3850,11 @@
             if (!forOutput) {
                 return GrSwizzle::RGB1();
             }
+            break;
         default:
             return GrSwizzle::RGBA();
     }
+
     return GrSwizzle::RGBA();
 }
 
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 437a7a9..45f3e13 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -481,6 +481,7 @@
         bool fDisableNonRedSingleChannelTexStorageForANGLEGL = false;
         bool fDisableBGRATextureStorageForIntelWindowsES = false;
         bool fDisableRGB8ForMali400 = false;
+        bool fDisableLuminance16F = false;
     };
 
     void applyDriverCorrectnessWorkarounds(const GrGLContextInfo&, const GrContextOptions&,
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 6d3ed39..5bf4350 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -461,6 +461,7 @@
 
 /* Luminance sized formats */
 #define GR_GL_LUMINANCE8                     0x8040
+#define GR_GL_LUMINANCE16F                   0x881E
 
 /* Alpha sized formats */
 #define GR_GL_ALPHA8                         0x803C
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 58bd698..f865d44 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -875,6 +875,7 @@
         case kRGBA_4444_GrPixelConfig:
         case kRG_88_GrPixelConfig:
         case kAlpha_half_GrPixelConfig:
+        case kAlpha_half_as_Lum_GrPixelConfig:
         case kAlpha_half_as_Red_GrPixelConfig:
         case kRGBA_half_GrPixelConfig:
         case kRGBA_half_Clamped_GrPixelConfig:
@@ -3750,7 +3751,6 @@
         case GrGLFormat::kRGBA4:                return kRGBA_4444_GrPixelConfig;
         case GrGLFormat::kRGBA32F:              return kRGBA_float_GrPixelConfig;
         case GrGLFormat::kRGBA16F:              return kRGBA_half_GrPixelConfig;
-        case GrGLFormat::kR16F:                 return kAlpha_half_GrPixelConfig;
         case GrGLFormat::kR16:                  return kR_16_GrPixelConfig;
         case GrGLFormat::kRG16:                 return kRG_1616_GrPixelConfig;
         case GrGLFormat::kRGBA16:               return kRGBA_16161616_GrPixelConfig;
@@ -3759,6 +3759,9 @@
 
         // Configs with multiple equivalent formats.
 
+        case GrGLFormat::kR16F:                 return kAlpha_half_GrPixelConfig;
+        case GrGLFormat::kLUMINANCE16F:         return kAlpha_half_GrPixelConfig;
+
         case GrGLFormat::kALPHA8:               return kAlpha_8_GrPixelConfig;
         case GrGLFormat::kR8:                   return kAlpha_8_GrPixelConfig;
 
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 21aede6..fd92b39 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -608,6 +608,7 @@
         case GrGLFormat::kRGB565:
         case GrGLFormat::kRGBA16F:
         case GrGLFormat::kR16F:
+        case GrGLFormat::kLUMINANCE16F:
         case GrGLFormat::kRGB8:
         case GrGLFormat::kRG8:
         case GrGLFormat::kRGB10_A2:
@@ -639,6 +640,7 @@
         case GrGLFormat::kRGB565:
         case GrGLFormat::kRGBA16F:
         case GrGLFormat::kR16F:
+        case GrGLFormat::kLUMINANCE16F:
         case GrGLFormat::kRGB8:
         case GrGLFormat::kRG8:
         case GrGLFormat::kRGB10_A2:
@@ -666,6 +668,7 @@
         case GrGLFormat::kRGBA4:
         case GrGLFormat::kRG8:
         case GrGLFormat::kR16F:
+        case GrGLFormat::kLUMINANCE16F:
         case GrGLFormat::kR16:
             return 2;
 
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 5d41495..644eae8 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -283,6 +283,7 @@
         case GR_GL_BGRA8:                return GrGLFormat::kBGRA8;
         case GR_GL_RGB565:               return GrGLFormat::kRGB565;
         case GR_GL_RGBA16F:              return GrGLFormat::kRGBA16F;
+        case GR_GL_LUMINANCE16F:         return GrGLFormat::kLUMINANCE16F;
         case GR_GL_R16F:                 return GrGLFormat::kR16F;
         case GR_GL_RGB8:                 return GrGLFormat::kRGB8;
         case GR_GL_RG8:                  return GrGLFormat::kRG8;
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index de5641f..77e93bd 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -91,6 +91,8 @@
         case kAlpha_half_as_Red_GrPixelConfig:
             *format = MTLPixelFormatR16Float;
             return true;
+        case kAlpha_half_as_Lum_GrPixelConfig:
+            return false;
         case kRGB_ETC1_GrPixelConfig:
 #ifdef SK_BUILD_FOR_IOS
             *format = MTLPixelFormatETC2_RGB8;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 355373b..09798d9 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -93,6 +93,7 @@
         case kUnknown_GrPixelConfig:
         case kAlpha_8_as_Alpha_GrPixelConfig:
         case kGray_8_as_Lum_GrPixelConfig:
+        case kAlpha_half_as_Lum_GrPixelConfig:
             SK_ABORT("Unsupported Vulkan pixel config");
             return 0;
 
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index 0153af2..197d4a0 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -77,6 +77,8 @@
         case kAlpha_half_as_Red_GrPixelConfig:
             *format = VK_FORMAT_R16_SFLOAT;
             return true;
+        case kAlpha_half_as_Lum_GrPixelConfig:
+            return false;
         case kR_16_GrPixelConfig:
             *format = VK_FORMAT_R16_UNORM;
             return true;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 4ac8ed4..2f2989b 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -1143,18 +1143,19 @@
     switch (modifiers.fLayout.fFormat) {
         case Layout::Format::kUnspecified:
             break;
-        case Layout::Format::kRGBA32F: // fall through
+        case Layout::Format::kRGBA32F:      // fall through
         case Layout::Format::kR32F:
             this->write("highp ");
             break;
-        case Layout::Format::kRGBA16F: // fall through
-        case Layout::Format::kR16F:    // fall through
+        case Layout::Format::kRGBA16F:      // fall through
+        case Layout::Format::kR16F:         // fall through
+        case Layout::Format::kLUMINANCE16F: // fall through
         case Layout::Format::kRG16F:
             this->write("mediump ");
             break;
-        case Layout::Format::kRGBA8:  // fall through
-        case Layout::Format::kR8:     // fall through
-        case Layout::Format::kRGBA8I: // fall through
+        case Layout::Format::kRGBA8:        // fall through
+        case Layout::Format::kR8:           // fall through
+        case Layout::Format::kRGBA8I:       // fall through
         case Layout::Format::kR8I:
             this->write("lowp ");
             break;
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index d4b1cb6..143aff3 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -60,6 +60,7 @@
         kR32F,
         kRGBA16F,
         kR16F,
+        kLUMINANCE16F,
         kRGBA8,
         kR8,
         kRGBA8I,
@@ -102,6 +103,7 @@
             case Format::kR32F:         return "r32f";
             case Format::kRGBA16F:      return "rgba16f";
             case Format::kR16F:         return "r16f";
+            case Format::kLUMINANCE16F: return "lum16f";
             case Format::kRGBA8:        return "rgba8";
             case Format::kR8:           return "r8";
             case Format::kRGBA8I:       return "rgba8i";
@@ -124,6 +126,9 @@
         } else if (str == "r16f") {
             *format = Format::kR16F;
             return true;
+        } else if (str == "lum16f") {
+            *format = Format::kLUMINANCE16F;
+            return true;
         } else if (str == "rgba8") {
             *format = Format::kRGBA8;
             return true;