Improve GrGLNonlinearColorSpaceXformEffect to support scRGB

Improve GrGLNonlinearColorSpaceXformEffect to correctly implement
scRGB transfer function and allow for negative colors.
Relax SkSurface_Gpu::Valid to allow kRGBA_half_GrPixelConfig
render target without a color space needed for legacy blending on
Android.

Bug: b/62347704
Change-Id: Ibc6144e69c26cdbdcbf29348c4f612fb6b639e01
Reviewed-on: https://skia-review.googlesource.com/26143
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/core/SkImageInfoPriv.h b/src/core/SkImageInfoPriv.h
index 38de97f..716c35d 100644
--- a/src/core/SkImageInfoPriv.h
+++ b/src/core/SkImageInfoPriv.h
@@ -34,7 +34,7 @@
     }
 
     if (kRGBA_F16_SkColorType == info.colorType() &&
-       (!info.colorSpace() || !info.colorSpace()->gammaIsLinear())) {
+       (info.colorSpace() && (!info.colorSpace()->gammaIsLinear()))) {
         return false;
     }
 
diff --git a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
index bfa2ed7..c0573e9 100644
--- a/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
+++ b/src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp
@@ -63,7 +63,9 @@
             transferFnBody.appendf("float E = %s[4];", coeffsName);
             transferFnBody.appendf("float F = %s[5];", coeffsName);
             transferFnBody.appendf("float G = %s[6];", coeffsName);
-            transferFnBody.appendf("return (x < D) ? (C * x) + F : pow(A * x + B, G) + E;");
+            transferFnBody.append("float s = sign(x);");
+            transferFnBody.append("x = abs(x);");
+            transferFnBody.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
             fragBuilder->emitFunction(kFloat_GrSLType, fnName, SK_ARRAY_COUNT(gTransferFnFuncArgs),
                                       gTransferFnFuncArgs, transferFnBody.c_str(), &tfFuncNames[i]);
         }
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 143a603..a474ffe 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -161,7 +161,7 @@
 bool SkSurface_Gpu::Valid(const SkImageInfo& info) {
     switch (info.colorType()) {
         case kRGBA_F16_SkColorType:
-            return info.colorSpace() && info.colorSpace()->gammaIsLinear();
+            return (!info.colorSpace()) || info.colorSpace()->gammaIsLinear();
         case kRGBA_8888_SkColorType:
         case kBGRA_8888_SkColorType:
             return !info.colorSpace() || info.colorSpace()->gammaCloseToSRGB();
@@ -173,7 +173,7 @@
 bool SkSurface_Gpu::Valid(GrContext* context, GrPixelConfig config, SkColorSpace* colorSpace) {
     switch (config) {
         case kRGBA_half_GrPixelConfig:
-            return colorSpace && colorSpace->gammaIsLinear();
+            return (!colorSpace) || colorSpace->gammaIsLinear();
         case kSRGBA_8888_GrPixelConfig:
         case kSBGRA_8888_GrPixelConfig:
             return context->caps()->srgbSupport() && colorSpace && colorSpace->gammaCloseToSRGB();
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index 51b9487..3869487 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -63,7 +63,7 @@
             shift = 2;
             break;
         case kRGBA_F16_SkColorType:
-            if (!info.colorSpace() || !info.colorSpace()->gammaIsLinear()) {
+            if (info.colorSpace() && (!info.colorSpace()->gammaIsLinear())) {
                 return false;
             }
             shift = 3;
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 797750f..202df58f 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -837,7 +837,7 @@
         { kN32_SkColorType,       srgbColorSpace,   true,  "N32-srgb"    },
         { kN32_SkColorType,       adobeColorSpace,  true,  "N32-adobe"   },
         { kN32_SkColorType,       oddColorSpace,    false, "N32-odd"     },
-        { kRGBA_F16_SkColorType,  nullptr,          false, "F16-nullptr" },
+        { kRGBA_F16_SkColorType,  nullptr,          true,  "F16-nullptr" },
         { kRGBA_F16_SkColorType,  linearColorSpace, true,  "F16-linear"  },
         { kRGBA_F16_SkColorType,  srgbColorSpace,   false, "F16-srgb"    },
         { kRGBA_F16_SkColorType,  adobeColorSpace,  false, "F16-adobe"   },