/* * 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 #include #include #include /* ================= 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); } /** Element-wise vector subtraction a - b */ static inline struct weston_vec3f weston_v3f_sub_v3f(struct weston_vec3f a, struct weston_vec3f b) { return WESTON_VEC3F(a.x - b.x, a.y - b.y, a.z - b.z); } /** Element-wise vector sum a + b */ static inline struct weston_vec3f weston_v3f_add_v3f(struct weston_vec3f a, struct weston_vec3f b) { return WESTON_VEC3F(a.x + b.x, a.y + b.y, a.z + b.z); } /** * 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 addition A + B */ static inline struct weston_mat3f weston_m3f_add_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 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