For legacy GPU configs, run high contrast filter on linearized values

Uses the same pow(2) approximation at the CPU version, and now produces
results that are nearly identical.

Also removed an extra copy of the config from the GLSL FP class - just use
the data from the FP.

Bug: skia:7265
Change-Id: If7b36094d5ae07f21219faba0bef9b2e4cb1e3d0
Reviewed-on: https://skia-review.googlesource.com/68041
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp
index 1d80710..b1900f0 100644
--- a/src/effects/SkHighContrastFilter.cpp
+++ b/src/effects/SkHighContrastFilter.cpp
@@ -15,6 +15,7 @@
 #include "../jumper/SkJumper.h"
 
 #if SK_SUPPORT_GPU
+#include "GrColorSpaceInfo.h"
 #include "GrContext.h"
 #include "glsl/GrGLSLFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -167,20 +168,26 @@
 #if SK_SUPPORT_GPU
 class HighContrastFilterEffect : public GrFragmentProcessor {
 public:
-    static std::unique_ptr<GrFragmentProcessor> Make(const SkHighContrastConfig& config) {
-        return std::unique_ptr<GrFragmentProcessor>(new HighContrastFilterEffect(config));
+    static std::unique_ptr<GrFragmentProcessor> Make(const SkHighContrastConfig& config,
+                                                     bool linearize) {
+        return std::unique_ptr<GrFragmentProcessor>(new HighContrastFilterEffect(config,
+                                                                                 linearize));
     }
 
     const char* name() const override { return "HighContrastFilter"; }
 
     const SkHighContrastConfig& config() const { return fConfig; }
+    bool linearize() const { return fLinearize; }
 
-    std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(fConfig); }
+    std::unique_ptr<GrFragmentProcessor> clone() const override {
+        return Make(fConfig, fLinearize);
+    }
 
 private:
-    HighContrastFilterEffect(const SkHighContrastConfig& config)
+    HighContrastFilterEffect(const SkHighContrastConfig& config, bool linearize)
         : INHERITED(kHighContrastFilterEffect_ClassID, kNone_OptimizationFlags)
-        , fConfig(config) {
+        , fConfig(config)
+        , fLinearize(linearize) {
     }
 
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -192,10 +199,12 @@
         const HighContrastFilterEffect& that = other.cast<HighContrastFilterEffect>();
         return fConfig.fGrayscale == that.fConfig.fGrayscale &&
             fConfig.fInvertStyle == that.fConfig.fInvertStyle &&
-            fConfig.fContrast == that.fConfig.fContrast;
+            fConfig.fContrast == that.fConfig.fContrast &&
+            fLinearize == that.fLinearize;
     }
 
     SkHighContrastConfig fConfig;
+    bool fLinearize;
 
     typedef GrFragmentProcessor INHERITED;
 };
@@ -204,21 +213,18 @@
 public:
     static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
 
-    GLHighContrastFilterEffect(const SkHighContrastConfig& config);
-
 protected:
     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
     void emitCode(EmitArgs& args) override;
 
 private:
     UniformHandle fContrastUni;
-    SkHighContrastConfig fConfig;
 
     typedef GrGLSLFragmentProcessor INHERITED;
 };
 
 GrGLSLFragmentProcessor* HighContrastFilterEffect::onCreateGLSLInstance() const {
-    return new GLHighContrastFilterEffect(fConfig);
+    return new GLHighContrastFilterEffect();
 }
 
 void HighContrastFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
@@ -232,19 +238,18 @@
     pdm.set1f(fContrastUni, hcfe.config().fContrast);
 }
 
-GLHighContrastFilterEffect::GLHighContrastFilterEffect(const SkHighContrastConfig& config)
-    : INHERITED()
-    , fConfig(config) {
-}
-
 void GLHighContrastFilterEffect::GenKey(
     const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
   const HighContrastFilterEffect& hcfe = proc.cast<HighContrastFilterEffect>();
   b->add32(static_cast<uint32_t>(hcfe.config().fGrayscale));
   b->add32(static_cast<uint32_t>(hcfe.config().fInvertStyle));
+  b->add32(hcfe.linearize() ? 1 : 0);
 }
 
 void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
+    const HighContrastFilterEffect& hcfe = args.fFp.cast<HighContrastFilterEffect>();
+    const SkHighContrastConfig& config = hcfe.config();
+
     const char* contrast;
     fContrastUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                                     "contrast", &contrast);
@@ -261,18 +266,22 @@
     fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.00001);");
     fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
 
+    if (hcfe.linearize()) {
+        fragBuilder->codeAppend("color.rgb = color.rgb * color.rgb;");
+    }
+
     // Grayscale.
-    if (fConfig.fGrayscale) {
+    if (config.fGrayscale) {
         fragBuilder->codeAppendf("half luma = dot(color, half4(%f, %f, %f, 0));",
                                  SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B);
         fragBuilder->codeAppendf("color = half4(luma, luma, luma, 0);");
     }
 
-    if (fConfig.fInvertStyle == InvertStyle::kInvertBrightness) {
+    if (config.fInvertStyle == InvertStyle::kInvertBrightness) {
         fragBuilder->codeAppendf("color = half4(1, 1, 1, 1) - color;");
     }
 
-    if (fConfig.fInvertStyle == InvertStyle::kInvertLightness) {
+    if (config.fInvertStyle == InvertStyle::kInvertLightness) {
         // Convert from RGB to HSL.
         fragBuilder->codeAppendf("half fmax = max(color.r, max(color.g, color.b));");
         fragBuilder->codeAppendf("half fmin = min(color.r, min(color.g, color.b));");
@@ -344,6 +353,10 @@
     // Clamp.
     fragBuilder->codeAppendf("color = clamp(color, 0, 1);");
 
+    if (hcfe.linearize()) {
+        fragBuilder->codeAppend("color.rgb = sqrt(color.rgb);");
+    }
+
     // Restore the original alpha and premultiply.
     fragBuilder->codeAppendf("color.a = %s.a;", args.fInputColor);
     fragBuilder->codeAppendf("color.rgb *= color.a;");
@@ -353,7 +366,8 @@
 }
 
 std::unique_ptr<GrFragmentProcessor> SkHighContrast_Filter::asFragmentProcessor(
-        GrContext*, const GrColorSpaceInfo&) const {
-    return HighContrastFilterEffect::Make(fConfig);
+        GrContext*, const GrColorSpaceInfo& csi) const {
+    bool linearize = !csi.isGammaCorrect();
+    return HighContrastFilterEffect::Make(fConfig, linearize);
 }
 #endif