Roll skia/third_party/skcms e040063..a7e79c5 (2 commits)
authorskcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Wed, 16 May 2018 16:03:08 +0000 (16:03 +0000)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Wed, 16 May 2018 17:18:52 +0000 (17:18 +0000)
https://skia.googlesource.com/skcms.git/+log/e040063..a7e79c5

2018-05-16 mtklein@chromium.org try yet again to fix gauss-newton stepping
2018-05-16 mtklein@chromium.org add clang.O0 build

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: I63a0ed3f912f69b114e3100ea44311f478563d3a
Reviewed-on: https://skia-review.googlesource.com/128475
Commit-Queue: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Reviewed-by: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
third_party/skcms/src/Curve.c
third_party/skcms/src/GaussNewton.c
third_party/skcms/src/GaussNewton.h
third_party/skcms/src/ICCProfile.c
third_party/skcms/src/PolyTF.c
third_party/skcms/src/TransferFunction.c
third_party/skcms/version.sha1

index 1e48d657992e804f4bea3115a692d9975ef4acb0..f52eb983fe0fe74853f95a64a33cf6e181c1fe03 100644 (file)
@@ -6,7 +6,9 @@
  */
 
 #include "Curve.h"
+#include "PortableMath.h"
 #include "TransferFunction.h"
+#include <assert.h>
 
 float skcms_eval_curve(const skcms_Curve* curve, float x) {
     if (curve->table_entries == 0) {
@@ -15,7 +17,10 @@ float skcms_eval_curve(const skcms_Curve* curve, float x) {
 
     // TODO: today we should always hit an entry exactly, but if that changes, lerp?
     // (We add half to account for slight int -> float -> int round tripping issues.)
-    int ix = (int)( x*(curve->table_entries - 1) + 0.5f );
+    float fx = x*(curve->table_entries - 1);
+    int ix = (int)( fx + 0.5f );
+
+    assert ( fabsf_(fx - (float)ix) < 0.0005 );
 
     if (curve->table_8) {
         return curve->table_8[ix] * (1/255.0f);
index 7e9f774538ccbd4355dd159c5952e7d623a842fc..61aeddbcdbe08ab530b7835d027a145d45ec3df8 100644 (file)
@@ -16,7 +16,7 @@
 bool skcms_gauss_newton_step(float (*rg)(float x, const void*, const float P[3], float dfdP[3]),
                              const void* ctx,
                              float P[3],
-                             float x0, float x1, int N) {
+                             float x0, float dx, int N) {
     // We'll sample x from the range [x0,x1] (both inclusive) N times with even spacing.
     //
     // We want to do P' = P + (Jf^T Jf)^-1 Jf^T r(P),
@@ -56,7 +56,6 @@ bool skcms_gauss_newton_step(float (*rg)(float x, const void*, const float P[3],
     // 1,2) evaluate lhs and evaluate rhs
     //   We want to evaluate Jf only once, but both lhs and rhs involve Jf^T,
     //   so we'll have to update lhs and rhs at the same time.
-    float dx = (x1-x0)/(N-1);
     for (int i = 0; i < N; i++) {
         float x = x0 + i*dx;
 
index 1c18b9ad93e1ea78cc0db3ebc8caa4515cb73d0b..5de9927ed3a470082aae079f512647d517ed3aef 100644 (file)
@@ -14,7 +14,7 @@
 //   rg:       residual function r(x,P) to minimize, and gradient at x in dfdP
 //   ctx:      arbitrary context argument passed to rg
 //   P:        in-out, both your initial guess for parameters of r(), and our updated values
-//   x0,x1,N:  N x-values to test in [x0,x1] (both inclusive) with even spacing
+//   x0,dx,N:  N x-values to test with even dx spacing, [x0, x0+dx, x0+2dx, ...]
 //
 // If you have fewer than 3 parameters, set the unused P to zero, don't touch their dfdP.
 //
@@ -22,4 +22,4 @@
 bool skcms_gauss_newton_step(float (*rg)(float x, const void*, const float P[3], float dfdP[3]),
                              const void* ctx,
                              float P[3],
-                             float x0, float x1, int N);
+                             float x0, float dx, int N);
index b3f34d10ce90c98bfbb39d139fec2d80c1b4fa9a..b1a431210a9ccd7caa3b41d9478bdcbbbd24b1c9 100644 (file)
@@ -834,9 +834,9 @@ const skcms_ICCProfile* skcms_sRGB_profile() {
 
         .has_poly_tf = { true, true, true },
         .poly_tf = {
-        {0.294143557548523f, 0.703896820545197f, (float)(1/12.92), 0.04045f},
-        {0.294143557548523f, 0.703896820545197f, (float)(1/12.92), 0.04045f},
-        {0.294143557548523f, 0.703896820545197f, (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},
+            {0.294143527746201f, 0.703896880149841f, (float)(1/12.92), 0.04045f},
         },
     };
     return &sRGB_profile;
index ff93ec55869cc3637860a7add8a7b5d0275b55c7..f74cf5418dd8e7c0c84452863d5124b1d6e183b7 100644 (file)
@@ -76,6 +76,7 @@ static bool fit_poly_tf(const skcms_Curve* curve, skcms_PolyTF* tf) {
 
     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.
@@ -117,7 +118,8 @@ static bool fit_poly_tf(const skcms_Curve* curve, skcms_PolyTF* tf) {
 
     // 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 * (N-1)) + 1;
+    // 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.
@@ -136,7 +138,7 @@ static bool fit_poly_tf(const skcms_Curve* curve, skcms_PolyTF* tf) {
         rg_poly_tf_arg arg = { curve, tf };
         if (!skcms_gauss_newton_step(rg_poly_tf, &arg,
                                      P,
-                                     tf->D, 1, N-L)) {
+                                     L*dx, dx, N-L)) {
             return false;
         }
     }
index 94ad410b40a57ed4de96e95dcaad40bd4bad0ddb..a27bd13bd2253bd252b89b2ec85fe14a9fb4ab02 100644 (file)
@@ -198,7 +198,7 @@ int skcms_fit_linear(const skcms_Curve* curve, int N, float tol, float* c, float
     // Some points' error intervals may intersect the running interval but not lie fully
     // within it.  So we keep track of the last point we saw that is a valid end point candidate,
     // and once the search is done, back up to build the line through *that* point.
-    const float x_scale = 1.0f / (N - 1);
+    const float dx = 1.0f / (N - 1);
 
     int lin_points = 1;
     *f = skcms_eval_curve(curve, 0);
@@ -206,7 +206,7 @@ int skcms_fit_linear(const skcms_Curve* curve, int N, float tol, float* c, float
     float slope_min = -INFINITY_;
     float slope_max = +INFINITY_;
     for (int i = 1; i < N; ++i) {
-        float x = i * x_scale;
+        float x = i * dx;
         float y = skcms_eval_curve(curve, x);
 
         float slope_max_i = (y + tol - *f) / x,
@@ -226,16 +226,16 @@ int skcms_fit_linear(const skcms_Curve* curve, int N, float tol, float* c, float
     }
 
     // Set D to the last point that met our tolerance.
-    *d = (lin_points - 1) * x_scale;
+    *d = (lin_points - 1) * dx;
     return lin_points;
 }
 
-// Fit the points in [start,N) to the non-linear piece of tf, or return false if we can't.
-static bool fit_nonlinear(const skcms_Curve* curve, int start, int N, skcms_TransferFunction* tf) {
+// Fit the points in [L,N) to the non-linear piece of tf, or return false if we can't.
+static bool fit_nonlinear(const skcms_Curve* curve, int L, int N, skcms_TransferFunction* tf) {
     float P[3] = { tf->g, tf->a, tf->b };
 
-    // No matter where we start, x_scale should always represent N even steps from 0 to 1.
-    const float x_scale = 1.0f / (N-1);
+    // No matter where we start, dx should always represent N even steps from 0 to 1.
+    const float dx = 1.0f / (N-1);
 
     for (int j = 0; j < 3/*TODO: tune*/; j++) {
         // These extra constraints a >= 0 and ad+b >= 0 are not modeled in the optimization.
@@ -253,7 +253,7 @@ static bool fit_nonlinear(const skcms_Curve* curve, int start, int N, skcms_Tran
         rg_nonlinear_arg arg = { curve, tf};
         if (!skcms_gauss_newton_step(rg_nonlinear, &arg,
                                      P,
-                                     start*x_scale, 1, N-start)) {
+                                     L*dx, dx, N-L)) {
             return false;
         }
     }
@@ -292,7 +292,7 @@ bool skcms_ApproximateCurve(const skcms_Curve* curve,
     }
 
     int N = (int)curve->table_entries;
-    const float x_scale = 1.0f / (N - 1);
+    const float dx = 1.0f / (N - 1);
 
     *max_error = INFINITY_;
     const float kTolerances[] = { 1.5f / 65535.0f, 1.0f / 512.0f };
@@ -311,11 +311,11 @@ bool skcms_ApproximateCurve(const skcms_Curve* curve,
         } else if (L == N - 1) {
             // Degenerate case with only two points in the nonlinear segment. Solve directly.
             tf.g = 1;
-            tf.a = (skcms_eval_curve(curve, (N-1)*x_scale) -
-                    skcms_eval_curve(curve, (N-2)*x_scale))
-                 / x_scale;
-            tf.b = skcms_eval_curve(curve, (N-2)*x_scale)
-                 - tf.a * (N-2)*x_scale;
+            tf.a = (skcms_eval_curve(curve, (N-1)*dx) -
+                    skcms_eval_curve(curve, (N-2)*dx))
+                 / dx;
+            tf.b = skcms_eval_curve(curve, (N-2)*dx)
+                 - tf.a * (N-2)*dx;
             tf.e = 0;
         } else {
             // Start by guessing a gamma-only curve through the midpoint.
@@ -353,7 +353,7 @@ bool skcms_ApproximateCurve(const skcms_Curve* curve,
 
         float err = 0;
         for (int i = 0; i < N; i++) {
-            float x = i * x_scale,
+            float x = i * dx,
                   y = skcms_eval_curve(curve, x);
             err = fmaxf_(err, fabsf_(x - skcms_TransferFunction_eval(&tf_inv, y)));
         }
index b0e2170f5604ab3182ada6a42474407cdc1f91e2..a7ddc513c7c96d6055ee49788f63ef87e8a2c8c2 100755 (executable)
@@ -1 +1 @@
-e040063b5d7d52615d0060bd79cbe90c5e2d90b4
\ No newline at end of file
+a7e79c5f3f8b2ac778d7ef6fb28d81a79be5debb
\ No newline at end of file