weston/include/libweston/linalg-3.h
Pekka Paalanen 120b88aa0a color: run vec3 through weston_color_curve_sample()
Future development will need to evaluate pipelines with curves and
matrices. Such pipelines naturally operate on vec3, as matrices cannot
be operated one channel at a time. Make weston_color_curve_sample()
operate on arrays of vec3.

Its currently only caller, weston_color_curve_to_3x1D_LUT(), is modified
to employ a temporary array for the API impedance mismatch. This
workaround will be removed later as weston_color_curve_to_3x1D_LUT()
itself will be converted to operate on vec3 arrays.

weston_v3f_array_to_planar() documentation was generated with AI.

weston_color_curve_sample() is restructured a little bit, attempting to
make it simpler to read.

color-operations.h gets the #includes needed to make it self-standing.

Assisted-by: Github Copilot (Claude Sonnet 3.5)
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00

228 lines
5.6 KiB
C

/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <math.h>
#include <libweston/linalg-types.h>
/* ================= 3-vectors and 3x3 matrices ============== */
/** Construct a column vector from elements */
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
/** Construct the [0, 0, 0]^T vector */
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
/** Construct matrix from elements a{row}{column} */
#define WESTON_MAT3F(a00, a01, a02, \
a10, a11, a12, \
a20, a21, a22) \
((struct weston_mat3f){ .colmaj = { \
a00, a10, a20, \
a01, a11, a21, \
a02, a12, a22, \
}})
/** Construct the identity 3x3 matrix */
#define WESTON_MAT3F_IDENTITY \
((struct weston_mat3f){ .colmaj = { \
1.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 1.0f, \
}})
/** Construct a diagonal matrix */
static inline struct weston_mat3f
weston_m3f_diag(struct weston_vec3f d)
{
return WESTON_MAT3F(
d.x, 0.0f, 0.0f,
0.0f, d.y, 0.0f,
0.0f, 0.0f, d.z);
}
/** Copy the top-left 3x3 from 4x4 */
static inline struct weston_mat3f
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
{
return WESTON_MAT3F(
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
);
}
/** Drop w from vec4f */
static inline struct weston_vec3f
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
{
return WESTON_VEC3F(v.x, v.y, v.z);
}
/** 3-vector dot product */
static inline float
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
/**
* Convert an array of vec3f into planar format
*
* Takes an array of RGB triplets and converts it into a planar format where all R
* values come first, then all G values, then all B values.
*
* \param planar The destination array for planar data, must have space for 3 * len floats
* \param arr Array of RGB triplets as vec3f structs
* \param len Number of RGB triplets in the array
*/
static inline void
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
planar[i ] = arr[i].r;
planar[i + len] = arr[i].g;
planar[i + 2 * len] = arr[i].b;
}
}
/** Clamp each element to the range [a, b], replacing NaN with a. */
static inline struct weston_vec3f
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
{
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
v.y >= a ? (v.y <= b ? v.y : b) : a,
v.z >= a ? (v.z <= b ? v.z : b) : a);
}
/**
* Matrix infinity-norm
*
* http://www.netlib.org/lapack/lug/node75.html
*/
static inline float
weston_m3f_inf_norm(struct weston_mat3f M)
{
unsigned row;
double infnorm = -1.0;
for (row = 0; row < 3; row++) {
unsigned col;
double sum = 0.0;
for (col = 0; col < 3; col++)
sum += fabsf(M.col[col].el[row]);
if (infnorm < sum)
infnorm = sum;
}
return infnorm;
}
/** Transpose 3x3 matrix */
static inline struct weston_mat3f
weston_m3f_transpose(struct weston_mat3f M)
{
struct weston_mat3f R;
unsigned i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
R.col[j].el[i] = M.col[i].el[j];
return R;
}
/** Matrix-vector multiplication A * b */
static inline struct weston_vec3f
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
{
struct weston_vec3f result;
unsigned r;
for (r = 0; r < 3; r++) {
struct weston_vec3f row =
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
result.el[r] = weston_v3f_dot_v3f(row, b);
}
return result;
}
/** Matrix multiplication A * B */
static inline struct weston_mat3f
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f result;
unsigned c;
for (c = 0; c < 3; c++)
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
return result;
}
/** Element-wise matrix subtraction A - B */
static inline struct weston_mat3f
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
return R;
}
/** Element-wise scalar multiplication */
static inline struct weston_mat3f
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = scalar * M.colmaj[i];
return R;
}
bool
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
#ifdef __cplusplus
}
#endif