Streamline legacy gradient color conversion

To produce colors for interpolation in legacy mode, we currently do
something like

  SkColor c = Sk4f_toS32(swizzle_rb(Sk4f::Load(c4f)));
    color4f = swizzle_rb(SkNx_cast<float>(Sk4b::Load(&c)) * (1/255.0f));

Let's see if we can streamline some of that.

Change-Id: I423b5aa8c2df8d115cc236d5f0a2e79923a9c2cc
Reviewed-on: https://skia-review.googlesource.com/66142
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/core/SkSRGB.h b/src/core/SkSRGB.h
index 9166ee9..de078a5 100644
--- a/src/core/SkSRGB.h
+++ b/src/core/SkSRGB.h
@@ -49,19 +49,4 @@
     return SkNx_cast<int>(Sk4f::Min(Sk4f::Max(s, 0.0f), 255.0f));
 }
 
-// [0.0f, 1.0f] -> [0.0f, 1.0f].  Correct after rounding.
-static inline Sk4f sk_linear_to_srgb_needs_round(const Sk4f& x) {
-    // Tuned to round trip each sRGB byte after rounding.
-    auto rsqrt = x.rsqrt(),
-         sqrt  = rsqrt.invert(),
-         ftrt  = rsqrt.rsqrt();
-
-    auto lo = 12.46f * x;
-
-    auto hi = Sk4f::Min(1.0f, SkNx_fma(Sk4f{+0.411192f}, ftrt,
-                              SkNx_fma(Sk4f{+0.689206f}, sqrt,
-                                       Sk4f{-0.0988f})));
-    return (x < 0.0043f).thenElse(lo, hi);
-}
-
 #endif//SkSRGB_DEFINED
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 3d4b255..e9f6e69 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -500,8 +500,19 @@
 }
 
 SkColor4f SkGradientShaderBase::getXformedColor(size_t i, SkColorSpace* dstCS) const {
-    return dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS)
-                 : SkColor4f_from_SkColor(this->getLegacyColor(i), nullptr);
+    if (dstCS) {
+        return to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS);
+    }
+
+    // Legacy/srgb color.
+#ifdef SK_SUPPORT_LEGACY_GRADIENT_COLOR_CONVERSION
+    return SkColor4f_from_SkColor(this->getLegacyColor(i), nullptr);
+#else
+    // We quantize upfront to ensure stable SkColor round-trips.
+    auto rgb255 = sk_linear_to_srgb(Sk4f::Load(fOrigColors4f[i].vec()));
+    auto rgb    = SkNx_cast<float>(rgb255) * (1/255.0f);
+    return { rgb[0], rgb[1], rgb[2], fOrigColors4f[i].fA };
+#endif
 }
 
 SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
@@ -1243,12 +1254,10 @@
         SkASSERT(shader.fOrigColors4f);
         fColors4f.setCount(shader.fColorCount);
         for (int i = 0; i < shader.fColorCount; ++i) {
-            if (args.fDstColorSpace) {
-                fColors4f[i] = GrColor4f::FromSkColor4f(shader.fOrigColors4f[i]);
-            } else {
-                GrColor grColor = SkColorToUnpremulGrColor(shader.getLegacyColor(i));
-                fColors4f[i] = GrColor4f::FromGrColor(grColor);
-            }
+            // We apply the dest CS transform separately, so we only use this as a selector
+            // for linear vs. legacy colors.
+            auto* cs = args.fDstColorSpace ? shader.fColorSpace.get() : nullptr;
+            fColors4f[i] = GrColor4f::FromSkColor4f(shader.getXformedColor(i, cs));
 
             if (kBeforeInterp_PremulType == fPremulType) {
                 fColors4f[i] = fColors4f[i].premul();