Roll skia/third_party/skcms 06d773b..3f444c5 (1 commits)

https://skia.googlesource.com/skcms.git/+log/06d773b..3f444c5

2018-05-17 mtklein@chromium.org rm skcms_PolyTF and skcms_OptimizeForSpeed()


The AutoRoll server is located here: https://skcms-skia-roll.skia.org

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.



CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel
TBR=herb@google.com

Change-Id: Ibdab92aa3d3cd9cc478623051ad1abb915765a7e
Reviewed-on: https://skia-review.googlesource.com/128981
Reviewed-by: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
diff --git a/third_party/skcms/skcms.c b/third_party/skcms/skcms.c
index 54467af..80ea143 100644
--- a/third_party/skcms/skcms.c
+++ b/third_party/skcms/skcms.c
@@ -11,7 +11,6 @@
 #include "src/GaussNewton.c"
 #include "src/ICCProfile.c"
 #include "src/LinearAlgebra.c"
-#include "src/PolyTF.c"
 #include "src/PortableMath.c"
 #include "src/TransferFunction.c"
 #include "src/Transform.c"
diff --git a/third_party/skcms/skcms.gni b/third_party/skcms/skcms.gni
index 7729208..64eeb16 100644
--- a/third_party/skcms/skcms.gni
+++ b/third_party/skcms/skcms.gni
@@ -12,7 +12,6 @@
   "src/LinearAlgebra.c",
   "src/LinearAlgebra.h",
   "src/Macros.h",
-  "src/PolyTF.c",
   "src/PortableMath.c",
   "src/PortableMath.h",
   "src/RandomBytes.h",
diff --git a/third_party/skcms/skcms.h b/third_party/skcms/skcms.h
index ffc8901..ece944c 100644
--- a/third_party/skcms/skcms.h
+++ b/third_party/skcms/skcms.h
@@ -43,11 +43,6 @@
     float g, a,b,c,d,e,f;
 } skcms_TransferFunction;
 
-// A transfer function that's cheaper to evaluate than skcms_TransferFunction.
-typedef struct skcms_PolyTF {
-    float A,B,C,D;
-} skcms_PolyTF;
-
 // Unified representation of 'curv' or 'para' tag data, or a 1D table from 'mft1' or 'mft2'
 typedef union skcms_Curve {
     struct {
@@ -113,10 +108,6 @@
     // and has_A2B to true.
     bool                   has_A2B;
     skcms_A2B              A2B;
-
-    // If the profile has_trc, we may be able to approximate those curves with skcms_PolyTF.
-    bool     has_poly_tf[3];
-    skcms_PolyTF poly_tf[3];
 } skcms_ICCProfile;
 
 // The sRGB color profile is so commonly used that we offer a canonical skcms_ICCProfile for it.
@@ -135,9 +126,8 @@
 // will be used.
 SKCMS_API bool skcms_Parse(const void*, size_t, skcms_ICCProfile*);
 
-// skcms_Parse() creates a profile that directs skcms_Transform() to favor accuracy.
-// If you want to trade a little accuracy for a big speedup, call skcms_OptimizeForSpeed().
-SKCMS_API void skcms_OptimizeForSpeed(skcms_ICCProfile*);
+// No-op, to be removed.
+static inline void skcms_OptimizeForSpeed(skcms_ICCProfile* p) { (void)p; }
 
 SKCMS_API bool skcms_ApproximateCurve(const skcms_Curve* curve,
                                       skcms_TransferFunction* approx,
@@ -258,7 +248,6 @@
     for (int i = 0; i < 3; ++i) {
         p->trc[i].table_entries = 0;
         p->trc[i].parametric = *tf;
-        p->has_poly_tf[i] = false;
     }
 }
 
diff --git a/third_party/skcms/src/ICCProfile.c b/third_party/skcms/src/ICCProfile.c
index b1a4312..324a34c 100644
--- a/third_party/skcms/src/ICCProfile.c
+++ b/third_party/skcms/src/ICCProfile.c
@@ -831,13 +831,6 @@
             { 0.222488403f, 0.716873169f, 0.060607910f },
             { 0.013916016f, 0.097076416f, 0.714096069f },
         }},
-
-        .has_poly_tf = { true, true, true },
-        .poly_tf = {
-            {0.294143527746201f, 0.703896880149841f, (float)(1/12.92), 0.04045f},
-            {0.294143527746201f, 0.703896880149841f, (float)(1/12.92), 0.04045f},
-            {0.294143527746201f, 0.703896880149841f, (float)(1/12.92), 0.04045f},
-        },
     };
     return &sRGB_profile;
 }
diff --git a/third_party/skcms/src/PolyTF.c b/third_party/skcms/src/PolyTF.c
deleted file mode 100644
index f74cf54..0000000
--- a/third_party/skcms/src/PolyTF.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../skcms.h"
-#include "Curve.h"
-#include "GaussNewton.h"
-#include "Macros.h"
-#include "PortableMath.h"
-#include "TransferFunction.h"
-#include <limits.h>
-#include <stdlib.h>
-
-// f(x) = skcms_PolyTF{A,B,C,D}(x) =
-//     Cx                       x < D
-//     A(x^3-1) + B(x^2-1) + 1  x ≥ D
-//
-// We'll fit C and D directly, and then hold them constant
-// and fit the other part using Gauss-Newton, subject to
-// the constraint that both parts meet at x=D:
-//
-//     CD = A(D^3-1) + B(D^2-1) + 1
-//
-// This lets us solve for B, reducing the optimization problem
-// for that part down to just a single parameter A:
-//
-//         CD - A(D^3-1) - 1
-//     B = -----------------
-//               D^2-1
-//
-//                    x^2-1
-//  f(x) = A(x^3-1) + ----- [CD - A(D^3-1) - 1] + 1
-//                    D^2-1
-//
-//                  (x^2-1) (D^3-1)
-//  ∂f/∂A = x^3-1 - ---------------
-//                       D^2-1
-//
-// It's important to evaluate as f(x) as A(x^3-1) + B(x^2-1) + 1
-// and not Ax^3 + Bx^2 + (1-A-B) to ensure that f(1.0f) == 1.0f.
-
-
-static float eval_poly_tf(float A, float B, float C, float D,
-                          float x) {
-    return x < D ? C*x
-                 : A*(x*x*x-1) + B*(x*x-1) + 1;
-}
-
-typedef struct {
-    const skcms_Curve*  curve;
-    const skcms_PolyTF* tf;
-} rg_poly_tf_arg;
-
-static float rg_poly_tf(float x, const void* ctx, const float P[3], float dfdP[3]) {
-    const rg_poly_tf_arg* arg = (const rg_poly_tf_arg*)ctx;
-    const skcms_PolyTF* tf = arg->tf;
-
-    float A = P[0],
-          C = tf->C,
-          D = tf->D;
-    float B = (C*D - A*(D*D*D - 1) - 1) / (D*D - 1);
-
-    dfdP[0] = (x*x*x - 1) - (x*x-1)*(D*D*D-1)/(D*D-1);
-
-    return skcms_eval_curve(arg->curve, x)
-         -     eval_poly_tf(A,B,C,D,    x);
-}
-
-static bool fit_poly_tf(const skcms_Curve* curve, skcms_PolyTF* tf) {
-    if (curve->table_entries > (uint32_t)INT_MAX) {
-        return false;
-    }
-
-    const int N = curve->table_entries == 0 ? 256
-                                            : (int)curve->table_entries;
-    const float dx = 1.0f / (N-1);
-
-    // We'll test the quality of our fit by roundtripping through a skcms_TransferFunction,
-    // either the inverse of the curve itself if it is parametric, or of its approximation if not.
-    skcms_TransferFunction baseline;
-    float err;
-    if (curve->table_entries == 0) {
-        baseline = curve->parametric;
-    } else if (!skcms_ApproximateCurve(curve, &baseline, &err)) {
-        return false;
-    }
-
-    // We'll borrow the linear section from baseline, which is either
-    // exactly correct, or already the approximation we'd use anyway.
-    tf->C = baseline.c;
-    tf->D = baseline.d;
-    if (baseline.f != 0) {
-        return false;  // Can't fit this (rare) kind of curve here.
-    }
-
-    // Detect linear baseline: (ax + b)^g + e --> ax ~~> Cx
-    if (baseline.g == 1 && baseline.d == 0) {
-        if (baseline.b + baseline.e == 0) {
-            tf->A = 0;
-            tf->B = 0;
-            tf->C = baseline.a;
-            tf->D = INFINITY_;   // Always use Cx, never Ax^3+Bx^2+(1-A-B)
-            return true;
-        } else {
-            return false;  // Just like baseline.f != 0 above, can't represent this offset.
-        }
-    }
-
-    // This case is less likely, but also guards against divide by zero below.
-    if (tf->D == 1) {
-        tf->A = 0;
-        tf->B = 0;
-        return true;
-    }
-
-    // Number of points already fit in the linear section.
-    // If the curve isn't parametric and we approximated instead, this should be exact.
-    // const int L = (int)( tf->D/dx + 0.5f ) + 1
-    const int L = (int)(tf->D * (N-1) + 0.5f) + 1;
-
-    if (L == N-1) {
-        // All points but one fit the linear section.
-        // We could connect the last point with a quadratic, but let's just be lazy.
-        return false;
-    }
-
-    skcms_TransferFunction inv;
-    if (!skcms_TransferFunction_invert(&baseline, &inv)) {
-        return false;
-    }
-
-    // Start with guess A = 0, i.e. f(x) ≈ x^2.
-    float P[3] = {0, 0,0};
-    for (int i = 0; i < 3; i++) {
-        rg_poly_tf_arg arg = { curve, tf };
-        if (!skcms_gauss_newton_step(rg_poly_tf, &arg,
-                                     P,
-                                     L*dx, dx, N-L)) {
-            return false;
-        }
-    }
-
-    float A = tf->A = P[0],
-          C = tf->C,
-          D = tf->D,
-          B = tf->B = (C*D - A*(D*D*D - 1) - 1) / (D*D - 1);
-
-    for (int i = 0; i < N; i++) {
-        float x = i * (1.0f/(N-1));
-
-        float rt = skcms_TransferFunction_eval(&inv, eval_poly_tf(A,B,C,D, x))
-                 * (N-1) + 0.5f;
-        if (!isfinitef_(rt) || rt >= N || rt < 0) {
-            return false;
-        }
-
-        const int tol = (i == 0 || i == N-1) ? 0
-                                             : N/256;
-        if (abs(i - (int)rt) > tol) {
-            return false;
-        }
-    }
-    return true;
-}
-
-void skcms_OptimizeForSpeed(skcms_ICCProfile* profile) {
-    for (int i = 0; profile->has_trc && i < 3; i++) {
-        if (!profile->has_poly_tf[i]) {
-             profile->has_poly_tf[i] = fit_poly_tf(&profile->trc[i], &profile->poly_tf[i]);
-        }
-    }
-}
diff --git a/third_party/skcms/src/Transform.c b/third_party/skcms/src/Transform.c
index 79feebc..791671e 100644
--- a/third_party/skcms/src/Transform.c
+++ b/third_party/skcms/src/Transform.c
@@ -321,11 +321,6 @@
     const void* arg;
 } OpAndArg;
 
-static OpAndArg select_poly_tf_op(const skcms_PolyTF* tf, int channel) {
-    static const Op ops[] = { Op_poly_tf_r, Op_poly_tf_g, Op_poly_tf_b };
-    return (OpAndArg){ops[channel], tf};
-}
-
 static OpAndArg select_curve_op(const skcms_Curve* curve, int channel) {
     static const struct { Op parametric, table_8, table_16; } ops[] = {
         { Op_tf_r, Op_table_8_r, Op_table_16_r },
@@ -518,9 +513,6 @@
             for (int i = 0; i < 3; i++) {
                 OpAndArg oa = select_curve_op(&srcProfile->trc[i], i);
                 if (oa.op != Op_noop) {
-                    if (srcProfile->has_poly_tf[i]) {
-                        oa = select_poly_tf_op(&srcProfile->poly_tf[i], i);
-                    }
                     *ops++  = oa.op;
                     *args++ = oa.arg;
                 }
diff --git a/third_party/skcms/src/Transform.h b/third_party/skcms/src/Transform.h
index c5892f1..1c4c15b 100644
--- a/third_party/skcms/src/Transform.h
+++ b/third_party/skcms/src/Transform.h
@@ -34,9 +34,6 @@
     M(tf_g)           \
     M(tf_b)           \
     M(tf_a)           \
-    M(poly_tf_r)      \
-    M(poly_tf_g)      \
-    M(poly_tf_b)      \
     M(table_8_r)      \
     M(table_8_g)      \
     M(table_8_b)      \
diff --git a/third_party/skcms/src/Transform_inl.h b/third_party/skcms/src/Transform_inl.h
index 97b2ea0..cb11777 100644
--- a/third_party/skcms/src/Transform_inl.h
+++ b/third_party/skcms/src/Transform_inl.h
@@ -252,13 +252,6 @@
 }
 #define apply_transfer_function NS(apply_transfer_function_)
 
-SI ATTR F NS(apply_poly_tf_)(const skcms_PolyTF* tf, F x) {
-    // TODO: handle x<0
-    return (F)if_then_else(x < tf->D, tf->C*x
-                                    , tf->A*(x*x*x-1) + tf->B*(x*x-1) + 1);
-}
-#define apply_poly_tf NS(apply_poly_tf_)
-
 // Strided loads and stores of N values, starting from p.
 #if N == 1
     #define LOAD_3(T, p) (T)(p)[0]
@@ -860,10 +853,6 @@
             case Op_tf_b:{ b = apply_transfer_function(*args++, b); } break;
             case Op_tf_a:{ a = apply_transfer_function(*args++, a); } break;
 
-            case Op_poly_tf_r:{ r = apply_poly_tf(*args++, r); } break;
-            case Op_poly_tf_g:{ g = apply_poly_tf(*args++, g); } break;
-            case Op_poly_tf_b:{ b = apply_poly_tf(*args++, b); } break;
-
             case Op_table_8_r: { r = NS(table_8_ )(*args++, r); } break;
             case Op_table_8_g: { g = NS(table_8_ )(*args++, g); } break;
             case Op_table_8_b: { b = NS(table_8_ )(*args++, b); } break;
diff --git a/third_party/skcms/version.sha1 b/third_party/skcms/version.sha1
index e72ae03..1ca44cf 100755
--- a/third_party/skcms/version.sha1
+++ b/third_party/skcms/version.sha1
@@ -1 +1 @@
-06d773bdba22d7d60599a3da5c8475bba3f45934
\ No newline at end of file
+3f444c5a52cb85be179f86ab1bef61719d2d949f
\ No newline at end of file