From e87eb19877cd705820231b0abfc687b8bcb4bb77 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 2 Oct 2025 16:00:16 +0300 Subject: [PATCH] color,gl-renderer: handle neg. in linpow/powlin We can handle the mirroring for negative input without conditional this way. Maybe it's faster, maybe it's not, but I like this style better. In color-operations we need only one call to the elementary function rather than two. This helps a lot with code clarity, when we get a vec3 at a time to handle in the future, doing three trivial calls instead of six with an if-else hassle. fragment.glsl sheds one layer of function wrapping, which is nice. Signed-off-by: Pekka Paalanen --- libweston/color-operations.c | 24 ++++++-------- libweston/renderer-gl/fragment.glsl | 50 +++++++++-------------------- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/libweston/color-operations.c b/libweston/color-operations.c index 7628ba554..47b96a436 100644 --- a/libweston/color-operations.c +++ b/libweston/color-operations.c @@ -51,9 +51,11 @@ static float linpow(float x, const union weston_color_curve_parametric_chan_data *p) { /* See WESTON_COLOR_CURVE_PARAMETRIC_TYPE_LINPOW for details about LINPOW. */ + /* LINPOW uses mirroring for negative input values. */ + float abs_x = fabsf(x); - if (x >= p->d) - return pow((p->a * x) + p->b, p->g); + if (abs_x >= p->d) + return copysign(pow((p->a * abs_x) + p->b, p->g), x); return p->c * x; } @@ -70,11 +72,7 @@ sample_linpow(const union weston_color_curve_parametric_chan_data *p, if (clamp_input) x = ensure_unorm(x); - /* LINPOW uses mirroring for negative input values. */ - if (x < 0.0) - out[i] = -linpow(-x, p); - else - out[i] = linpow(x, p); + out[i] = linpow(x, p); } } @@ -82,9 +80,11 @@ static float powlin(float x, const union weston_color_curve_parametric_chan_data *p) { /* See WESTON_COLOR_CURVE_PARAMETRIC_TYPE_POWLIN for details about POWLIN. */ + /* POWLIN uses mirroring for negative input values. */ + float abs_x = fabsf(x); - if (x >= p->d) - return p->a * pow(x, p->g) + p->b; + if (abs_x >= p->d) + return copysign(p->a * pow(abs_x, p->g) + p->b, x); return p->c * x; } @@ -101,11 +101,7 @@ sample_powlin(const union weston_color_curve_parametric_chan_data *p, if (clamp_input) x = ensure_unorm(x); - /* POWLIN uses mirroring for negative input values. */ - if (x < 0.0) - out[i] = -powlin(-x, p); - else - out[i] = powlin(x, p); + out[i] = powlin(x, p); } } diff --git a/libweston/renderer-gl/fragment.glsl b/libweston/renderer-gl/fragment.glsl index e02329d75..b4b8d9d88 100644 --- a/libweston/renderer-gl/fragment.glsl +++ b/libweston/renderer-gl/fragment.glsl @@ -298,67 +298,49 @@ unpack_params(const parametric_curve_t par, compile_const int chan) } float -linpow(float x, const gabcd_t p) +linpow(const gabcd_t p, float x) { /* See WESTON_COLOR_CURVE_PARAMETRIC_TYPE_LINPOW for details about LINPOW. */ - - if (x >= p.d) - return pow((p.a * x) + p.b, p.g); - - return p.c * x; -} - -float -sample_linpow(const gabcd_t p, float x) -{ if (p.clamp) x = clamp(x, 0.0, 1.0); /* We use mirroring for negative input values. */ - if (x < 0.0) - return -linpow(-x, p); + float abs_x = abs(x); + if (abs_x >= p.d) + return sign(x) * pow((p.a * abs_x) + p.b, p.g); - return linpow(x, p); + return p.c * x; } vec3 sample_linpow_vec3(const parametric_curve_t par, vec3 color) { - return vec3(sample_linpow(unpack_params(par, 0), color.r), - sample_linpow(unpack_params(par, 1), color.g), - sample_linpow(unpack_params(par, 2), color.b)); + return vec3(linpow(unpack_params(par, 0), color.r), + linpow(unpack_params(par, 1), color.g), + linpow(unpack_params(par, 2), color.b)); } float -powlin(float x, const gabcd_t p) +powlin(const gabcd_t p, float x) { /* See WESTON_COLOR_CURVE_PARAMETRIC_TYPE_POWLIN for details about POWLIN. */ - - if (x >= p.d) - return p.a * pow(x, p.g) + p.b; - - return p.c * x; -} - -float -sample_powlin(const gabcd_t p, float x) -{ if (p.clamp) x = clamp(x, 0.0, 1.0); /* We use mirroring for negative input values. */ - if (x < 0.0) - return -powlin(-x, p); + float abs_x = abs(x); + if (abs_x >= p.d) + return sign(x) * (p.a * pow(abs_x, p.g) + p.b); - return powlin(x, p); + return p.c * x; } vec3 sample_powlin_vec3(const parametric_curve_t par, vec3 color) { - return vec3(sample_powlin(unpack_params(par, 0), color.r), - sample_powlin(unpack_params(par, 1), color.g), - sample_powlin(unpack_params(par, 2), color.b)); + return vec3(powlin(unpack_params(par, 0), color.r), + powlin(unpack_params(par, 1), color.g), + powlin(unpack_params(par, 2), color.b)); } float