Roll skia/third_party/skcms fe14a6a..e8bc226 (1 commits)

https://skia.googlesource.com/skcms.git/+log/fe14a6a..e8bc226

2018-04-23 mtklein@chromium.org 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.



TBR=stani@google.com

Change-Id: Ib0c40a1dc5314ee6ca18da6ddac9895977c12bdc
Reviewed-on: https://skia-review.googlesource.com/123072
Reviewed-by: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Commit-Queue: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
This commit is contained in:
skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com 2018-04-23 18:57:32 +00:00 committed by Skia Commit-Bot
parent 9ad12134c9
commit 3315f7e9c6
6 changed files with 46 additions and 7 deletions

View File

@ -73,6 +73,12 @@ typedef struct skcms_A2B {
skcms_Curve output_curves[3];
} skcms_A2B;
// A specialized approximation for transfer functions with gamma between 1 and 3.
// f(x) = sign(x) * (A|x|^3 + B|x|^2 + (1-A-B)|x|)
typedef struct skcms_TF13 {
float A,B;
} skcms_TF13;
typedef struct skcms_ICCProfile {
const uint8_t* buffer;
@ -97,6 +103,10 @@ typedef struct skcms_ICCProfile {
// and has_A2B to true.
bool has_A2B;
skcms_A2B A2B;
// If has_trc, we may be able to approximate the curves more efficiently.
bool has_tf13[3];
skcms_TF13 tf13[3];
} skcms_ICCProfile;
// The sRGB color profile is so commonly used that we offer a canonical skcms_ICCProfile for it.
@ -114,15 +124,13 @@ bool skcms_ApproximatelyEqualProfiles(const skcms_ICCProfile* A, const skcms_ICC
// will be used.
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().
void skcms_OptimizeForSpeed(skcms_ICCProfile*);
bool skcms_ApproximateCurve(const skcms_Curve* curve, skcms_TransferFunction* approx,
float* max_error);
// A specialized approximation for transfer functions with gamma between 1 and 3.
// f(x) = Ax^3 + Bx^2 + (1-A-B)x
typedef struct skcms_TF13 {
float A,B;
} skcms_TF13;
bool skcms_ApproximateCurve13(const skcms_Curve* curve, skcms_TF13* approx, float* max_error);
// What is the best single transfer function to use for the given profile? Note that there is

View File

@ -781,6 +781,14 @@ bool skcms_Parse(const void* buf, size_t len, skcms_ICCProfile* profile) {
return usable_as_src(profile);
}
void skcms_OptimizeForSpeed(skcms_ICCProfile* profile) {
// If we can approximate any of the TRC curves with a skcms_TF13, do so.
for (int i = 0; profile->has_trc && i < 3; i++) {
float err;
profile->has_tf13[i] = skcms_ApproximateCurve13(&profile->trc[i], &profile->tf13[i], &err);
}
}
const skcms_ICCProfile skcms_sRGB_profile = {
// These fields are moot when not a skcms_Parse()'d profile.
.buffer = NULL,

View File

@ -314,6 +314,11 @@ typedef struct {
const void* arg;
} OpAndArg;
static OpAndArg select_tf13_op(const skcms_TF13* tf, int channel) {
static const Op ops[] = { Op_tf13_r, Op_tf13_g, Op_tf13_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 },
@ -513,8 +518,13 @@ bool skcms_Transform(const void* src,
} else if (srcProfile->has_trc && srcProfile->has_toXYZD50) {
for (int i = 0; i < 3; i++) {
// Favor Op_noop (identity curve) over anything else,
// and select_tf_op() over over select_curve_op() when possible.
OpAndArg oa = select_curve_op(&srcProfile->trc[i], i);
if (oa.op != Op_noop) {
if (srcProfile->has_tf13[i]) {
oa = select_tf13_op(&srcProfile->tf13[i], i);
}
*ops++ = oa.op;
*args++ = oa.arg;
}

View File

@ -34,6 +34,9 @@
M(tf_g) \
M(tf_b) \
M(tf_a) \
M(tf13_r) \
M(tf13_g) \
M(tf13_b) \
M(table_8_r) \
M(table_8_g) \
M(table_8_b) \

View File

@ -239,6 +239,12 @@ SI ATTR F NS(apply_transfer_function_)(const skcms_TransferFunction* tf, F x) {
}
#define apply_transfer_function NS(apply_transfer_function_)
SI ATTR F NS(apply_tf13_)(const skcms_TF13* tf, F x) {
F sign = (F)if_then_else(x < 0, -F1, F1);
return x*(x*(x*tf->A + sign*tf->B) + (1 - tf->A - tf->B) );
}
#define apply_tf13 NS(apply_tf13_)
// Strided loads and stores of N values, starting from p.
#if N == 1
#define LOAD_3(T, p) (T)(p)[0]
@ -840,6 +846,10 @@ static void NS(exec_ops)(const Op* ops, const void** args,
case Op_tf_b:{ b = apply_transfer_function(*args++, b); } break;
case Op_tf_a:{ a = apply_transfer_function(*args++, a); } break;
case Op_tf13_r:{ r = apply_tf13(*args++, r); } break;
case Op_tf13_g:{ g = apply_tf13(*args++, g); } break;
case Op_tf13_b:{ b = apply_tf13(*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;

View File

@ -1 +1 @@
fe14a6aff9d05024284bbf576a93919c3cf8e9c4
e8bc22664f84326c18feeb0444f573e8a0c75f42