From 6c78b2b7cd01525c43939dcee4e5e370a5b66ac2 Mon Sep 17 00:00:00 2001 From: "skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com" Date: Wed, 16 May 2018 16:03:08 +0000 Subject: Roll skia/third_party/skcms e040063..a7e79c5 (2 commits) 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 Reviewed-by: skcms-skia-autoroll --- third_party/skcms/src/Curve.c | 7 ++++++- third_party/skcms/src/GaussNewton.c | 3 +-- third_party/skcms/src/GaussNewton.h | 4 ++-- third_party/skcms/src/ICCProfile.c | 6 +++--- third_party/skcms/src/PolyTF.c | 6 ++++-- third_party/skcms/src/TransferFunction.c | 30 +++++++++++++++--------------- third_party/skcms/version.sha1 | 2 +- 7 files changed, 32 insertions(+), 26 deletions(-) (limited to 'third_party/skcms') diff --git a/third_party/skcms/src/Curve.c b/third_party/skcms/src/Curve.c index 1e48d65799..f52eb983fe 100644 --- a/third_party/skcms/src/Curve.c +++ b/third_party/skcms/src/Curve.c @@ -6,7 +6,9 @@ */ #include "Curve.h" +#include "PortableMath.h" #include "TransferFunction.h" +#include 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); diff --git a/third_party/skcms/src/GaussNewton.c b/third_party/skcms/src/GaussNewton.c index 7e9f774538..61aeddbcdb 100644 --- a/third_party/skcms/src/GaussNewton.c +++ b/third_party/skcms/src/GaussNewton.c @@ -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; diff --git a/third_party/skcms/src/GaussNewton.h b/third_party/skcms/src/GaussNewton.h index 1c18b9ad93..5de9927ed3 100644 --- a/third_party/skcms/src/GaussNewton.h +++ b/third_party/skcms/src/GaussNewton.h @@ -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); diff --git a/third_party/skcms/src/ICCProfile.c b/third_party/skcms/src/ICCProfile.c index b3f34d10ce..b1a431210a 100644 --- a/third_party/skcms/src/ICCProfile.c +++ b/third_party/skcms/src/ICCProfile.c @@ -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; diff --git a/third_party/skcms/src/PolyTF.c b/third_party/skcms/src/PolyTF.c index ff93ec5586..f74cf5418d 100644 --- a/third_party/skcms/src/PolyTF.c +++ b/third_party/skcms/src/PolyTF.c @@ -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; } } diff --git a/third_party/skcms/src/TransferFunction.c b/third_party/skcms/src/TransferFunction.c index 94ad410b40..a27bd13bd2 100644 --- a/third_party/skcms/src/TransferFunction.c +++ b/third_party/skcms/src/TransferFunction.c @@ -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))); } diff --git a/third_party/skcms/version.sha1 b/third_party/skcms/version.sha1 index b0e2170f56..a7ddc513c7 100755 --- a/third_party/skcms/version.sha1 +++ b/third_party/skcms/version.sha1 @@ -1 +1 @@ -e040063b5d7d52615d0060bd79cbe90c5e2d90b4 \ No newline at end of file +a7e79c5f3f8b2ac778d7ef6fb28d81a79be5debb \ No newline at end of file -- cgit v1.2.3