From 3fefb5ba4468c7995abd3c4e878c526e386b224e Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 24 Mar 2025 17:56:34 +0200 Subject: [PATCH] libweston, clients, tests: implement weston_matrix in terms of weston_mat4f This converts weston_matrix and weston_vector to use linalg-types internally. All direct accesses to members had to be converted everywhere, mostly in the simplest form possible which leaves some trivially reducable code around. The intention is that we can now gradually migrate away from weston_matrix in the future. Look like one trailing space got accidentally annihilated in compositor.c. Signed-off-by: Pekka Paalanen --- clients/calibrator.c | 16 +-- clients/simple-dmabuf-egl.c | 4 +- clients/simple-egl.c | 10 +- clients/touch-calibrator.c | 18 +-- clients/window.c | 5 +- include/libweston/matrix.h | 5 +- ivi-shell/ivi-layout.c | 36 +++--- libweston/compositor.c | 18 +-- libweston/pixman-renderer.c | 18 +-- libweston/renderer-gl/gl-renderer.c | 18 +-- libweston/renderer-gl/gl-shaders.c | 4 +- shared/matrix.c | 194 ++++------------------------ tests/color_util.c | 4 +- tests/lcms_util.c | 33 +++-- tests/matrix-test.c | 80 +++--------- tests/matrix-transform-test.c | 41 +++--- 16 files changed, 164 insertions(+), 340 deletions(-) diff --git a/clients/calibrator.c b/clients/calibrator.c index be65d9bdc..b98a676b3 100644 --- a/clients/calibrator.c +++ b/clients/calibrator.c @@ -117,11 +117,11 @@ finish_calibration (struct calibrator *calibrator) */ memset(&m, 0, sizeof(m)); for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) { - m.d[i] = calibrator->tests[i].clicked_x; - m.d[i + 4] = calibrator->tests[i].clicked_y; - m.d[i + 8] = 1; + m.M.col[0].el[i] = calibrator->tests[i].clicked_x; + m.M.col[1].el[i] = calibrator->tests[i].clicked_y; + m.M.col[2].el[i] = 1; } - m.d[15] = 1; + m.M.col[3].el[3] = 1; weston_matrix_invert(&inverse, &m); @@ -129,8 +129,8 @@ finish_calibration (struct calibrator *calibrator) memset(&y_calib, 0, sizeof(y_calib)); for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) { - x_calib.f[i] = calibrator->tests[i].drawn_x; - y_calib.f[i] = calibrator->tests[i].drawn_y; + x_calib.v.el[i] = calibrator->tests[i].drawn_x; + y_calib.v.el[i] = calibrator->tests[i].drawn_y; } /* Multiples into the vector */ @@ -138,8 +138,8 @@ finish_calibration (struct calibrator *calibrator) weston_matrix_transform(&inverse, &y_calib); printf ("Calibration values: %f %f %f %f %f %f\n", - x_calib.f[0], x_calib.f[1], x_calib.f[2], - y_calib.f[0], y_calib.f[1], y_calib.f[2]); + x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2], + y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]); exit(0); } diff --git a/clients/simple-dmabuf-egl.c b/clients/simple-dmabuf-egl.c index 9989497e7..92c63ac87 100644 --- a/clients/simple-dmabuf-egl.c +++ b/clients/simple-dmabuf-egl.c @@ -815,7 +815,7 @@ render(struct window *window, struct buffer *buffer) glUniform1f(window->gl.offset_uniform, offset); glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE, - (GLfloat *) reflection.d); + (GLfloat *) reflection.M.colmaj); glClearColor(0.0,0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); @@ -864,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer) glUniform1f(window->gl.offset_uniform, offset); glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE, - (GLfloat *) reflection.d); + (GLfloat *) reflection.M.colmaj); glClearColor(0.6, 0.6, 0.6, 1.0); glClear(GL_COLOR_BUFFER_BIT); diff --git a/clients/simple-egl.c b/clients/simple-egl.c index fadeac34c..8308fe6a5 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -940,10 +940,10 @@ redraw(struct window *window) angle = ((time - window->initial_frame_time) / speed_div) % 360 * M_PI / 180.0; } - rotation.d[0] = cos(angle); - rotation.d[2] = sin(angle); - rotation.d[8] = -sin(angle); - rotation.d[10] = cos(angle); + rotation.M.col[0].el[0] = cos(angle); + rotation.M.col[0].el[2] = sin(angle); + rotation.M.col[2].el[0] = -sin(angle); + rotation.M.col[2].el[2] = cos(angle); switch (window->buffer_transform) { case WL_OUTPUT_TRANSFORM_FLIPPED: @@ -982,7 +982,7 @@ redraw(struct window *window) glViewport(0, 0, window->buffer_size.width, window->buffer_size.height); glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE, - (GLfloat *) rotation.d); + (GLfloat *) rotation.M.colmaj); if (window->opaque || window->fullscreen) glClearColor(0.0, 0.0, 0.0, 1); diff --git a/clients/touch-calibrator.c b/clients/touch-calibrator.c index 49dd9206b..374ae492e 100644 --- a/clients/touch-calibrator.c +++ b/clients/touch-calibrator.c @@ -330,9 +330,9 @@ compute_calibration(struct calibrator *cal, float *result) */ weston_matrix_init(&m); for (i = 0; i < 3; i++) { - m.d[i + 0] = cal->samples[i].touched.x; - m.d[i + 4] = cal->samples[i].touched.y; - m.d[i + 8] = 1.0f; + m.M.col[0].el[i] = cal->samples[i].touched.x; + m.M.col[1].el[i] = cal->samples[i].touched.y; + m.M.col[2].el[i] = 1.0f; } m.type = WESTON_MATRIX_TRANSFORM_OTHER; @@ -342,20 +342,20 @@ compute_calibration(struct calibrator *cal, float *result) } for (i = 0; i < 3; i++) { - x_calib.f[i] = cal->samples[i].drawn_cal.x; - y_calib.f[i] = cal->samples[i].drawn_cal.y; + x_calib.v.el[i] = cal->samples[i].drawn_cal.x; + y_calib.v.el[i] = cal->samples[i].drawn_cal.y; } - x_calib.f[3] = 0.0f; - y_calib.f[3] = 0.0f; + x_calib.v.el[3] = 0.0f; + y_calib.v.el[3] = 0.0f; /* Multiples into the vector */ weston_matrix_transform(&inverse, &x_calib); weston_matrix_transform(&inverse, &y_calib); for (i = 0; i < 3; i++) - result[i] = x_calib.f[i]; + result[i] = x_calib.v.el[i]; for (i = 0; i < 3; i++) - result[i + 3] = y_calib.f[i]; + result[i + 3] = y_calib.v.el[i]; return 0; } diff --git a/clients/window.c b/clients/window.c index 9d0aaf964..104bb3991 100644 --- a/clients/window.c +++ b/clients/window.c @@ -1842,8 +1842,9 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr) surface->allocation.width, surface->allocation.height, surface->buffer_scale); - cairo_matrix_init(&m, matrix.d[0], matrix.d[1], matrix.d[4], - matrix.d[5], matrix.d[12], matrix.d[13]); + cairo_matrix_init(&m, matrix.M.col[0].x, matrix.M.col[0].y, + matrix.M.col[1].x, matrix.M.col[1].y, + matrix.M.col[3].x, matrix.M.col[3].y); cairo_transform(cr, &m); } diff --git a/include/libweston/matrix.h b/include/libweston/matrix.h index c309db48d..ce4af304b 100644 --- a/include/libweston/matrix.h +++ b/include/libweston/matrix.h @@ -31,6 +31,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -44,12 +45,12 @@ enum weston_matrix_transform_type { }; struct weston_matrix { - float d[16]; + struct weston_mat4f M; unsigned int type; }; struct weston_vector { - float f[4]; + struct weston_vec4f v; }; /** Arbitrary coordinates in any space */ diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c index a50ed5a9e..20388ea55 100644 --- a/ivi-shell/ivi-layout.c +++ b/ivi-shell/ivi-layout.c @@ -463,33 +463,33 @@ calc_inverse_matrix_transform(const struct weston_matrix *matrix, } /* The vectors and matrices involved will always produce f[3] == 1.0. */ - top_left.f[0] = rect_input->x; - top_left.f[1] = rect_input->y; - top_left.f[2] = 0.0f; - top_left.f[3] = 1.0f; + top_left.v.el[0] = rect_input->x; + top_left.v.el[1] = rect_input->y; + top_left.v.el[2] = 0.0f; + top_left.v.el[3] = 1.0f; - bottom_right.f[0] = rect_input->x + rect_input->width; - bottom_right.f[1] = rect_input->y + rect_input->height; - bottom_right.f[2] = 0.0f; - bottom_right.f[3] = 1.0f; + bottom_right.v.el[0] = rect_input->x + rect_input->width; + bottom_right.v.el[1] = rect_input->y + rect_input->height; + bottom_right.v.el[2] = 0.0f; + bottom_right.v.el[3] = 1.0f; weston_matrix_transform(&m, &top_left); weston_matrix_transform(&m, &bottom_right); - if (top_left.f[0] < bottom_right.f[0]) { - rect_output->x = floorf(top_left.f[0]); - rect_output->width = ceilf(bottom_right.f[0] - rect_output->x); + if (top_left.v.el[0] < bottom_right.v.el[0]) { + rect_output->x = floor(top_left.v.el[0]); + rect_output->width = ceil(bottom_right.v.el[0] - rect_output->x); } else { - rect_output->x = floorf(bottom_right.f[0]); - rect_output->width = ceilf(top_left.f[0] - rect_output->x); + rect_output->x = floor(bottom_right.v.el[0]); + rect_output->width = ceil(top_left.v.el[0] - rect_output->x); } - if (top_left.f[1] < bottom_right.f[1]) { - rect_output->y = floorf(top_left.f[1]); - rect_output->height = ceilf(bottom_right.f[1] - rect_output->y); + if (top_left.v.el[1] < bottom_right.v.el[1]) { + rect_output->y = floor(top_left.v.el[1]); + rect_output->height = ceil(bottom_right.v.el[1] - rect_output->y); } else { - rect_output->y = floorf(bottom_right.f[1]); - rect_output->height = ceilf(top_left.f[1] - rect_output->y); + rect_output->y = floor(bottom_right.v.el[1]); + rect_output->height = ceil(top_left.v.el[1] - rect_output->y); } ivi_rectangle_intersect(rect_output, boundingbox, rect_output); diff --git a/libweston/compositor.c b/libweston/compositor.c index 819fb9530..2fcbf6bf0 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -1798,14 +1798,14 @@ weston_view_update_transform_disable(struct weston_view *view) /* Otherwise identity matrix, but with x and y translation. */ view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE; - view->transform.position.matrix.d[12] = view->geometry.pos_offset.x; - view->transform.position.matrix.d[13] = view->geometry.pos_offset.y; + view->transform.position.matrix.M.col[3].x = view->geometry.pos_offset.x; + view->transform.position.matrix.M.col[3].y = view->geometry.pos_offset.y; view->transform.matrix = view->transform.position.matrix; view->transform.inverse = view->transform.position.matrix; - view->transform.inverse.d[12] = -view->geometry.pos_offset.x; - view->transform.inverse.d[13] = -view->geometry.pos_offset.y; + view->transform.inverse.M.col[3].x = -view->geometry.pos_offset.x; + view->transform.inverse.M.col[3].y = -view->geometry.pos_offset.y; pixman_region32_init_rect(&view->transform.boundingbox, 0, 0, @@ -1850,8 +1850,8 @@ weston_view_update_transform_enable(struct weston_view *view) /* Otherwise identity matrix, but with x and y translation. */ view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE; - view->transform.position.matrix.d[12] = view->geometry.pos_offset.x; - view->transform.position.matrix.d[13] = view->geometry.pos_offset.y; + view->transform.position.matrix.M.col[3].x = view->geometry.pos_offset.x; + view->transform.position.matrix.M.col[3].y = view->geometry.pos_offset.y; weston_matrix_init(matrix); wl_list_for_each(tform, &view->geometry.transformation_list, link) @@ -1889,8 +1889,8 @@ weston_view_update_transform_enable(struct weston_view *view) &view->transform.opaque, &view->geometry.scissor); pixman_region32_translate(&view->transform.opaque, - matrix->d[12], - matrix->d[13]); + matrix->M.col[3].x, + matrix->M.col[3].y); } } else if (view->alpha == 1.0 && matrix->type < WESTON_MATRIX_TRANSFORM_ROTATE && @@ -10751,7 +10751,7 @@ weston_output_finish_frame_from_timer(struct weston_output *output) } /** Retrieve the backend type of as described in enum - * weston_compositor_backend. + * weston_compositor_backend. * * Note that the backend must be loaded, with weston_compositor_load_backend * diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index ec7ddf5e6..84031b703 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -152,15 +152,15 @@ weston_matrix_to_pixman_transform(pixman_transform_t *pt, { /* Pixman supports only 2D transform matrix, but Weston uses 3D, * * so we're omitting Z coordinate here. */ - pt->matrix[0][0] = pixman_double_to_fixed(wm->d[0]); - pt->matrix[0][1] = pixman_double_to_fixed(wm->d[4]); - pt->matrix[0][2] = pixman_double_to_fixed(wm->d[12]); - pt->matrix[1][0] = pixman_double_to_fixed(wm->d[1]); - pt->matrix[1][1] = pixman_double_to_fixed(wm->d[5]); - pt->matrix[1][2] = pixman_double_to_fixed(wm->d[13]); - pt->matrix[2][0] = pixman_double_to_fixed(wm->d[3]); - pt->matrix[2][1] = pixman_double_to_fixed(wm->d[7]); - pt->matrix[2][2] = pixman_double_to_fixed(wm->d[15]); + pt->matrix[0][0] = pixman_double_to_fixed(wm->M.col[0].x); + pt->matrix[0][1] = pixman_double_to_fixed(wm->M.col[1].x); + pt->matrix[0][2] = pixman_double_to_fixed(wm->M.col[3].x); + pt->matrix[1][0] = pixman_double_to_fixed(wm->M.col[0].y); + pt->matrix[1][1] = pixman_double_to_fixed(wm->M.col[1].y); + pt->matrix[1][2] = pixman_double_to_fixed(wm->M.col[3].y); + pt->matrix[2][0] = pixman_double_to_fixed(wm->M.col[0].w); + pt->matrix[2][1] = pixman_double_to_fixed(wm->M.col[1].w); + pt->matrix[2][2] = pixman_double_to_fixed(wm->M.col[3].w); } static bool diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 96155b98f..d19ca5d04 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -43,6 +43,8 @@ #include #endif +#include + #include "linux-sync-file.h" #include "timeline.h" @@ -2343,12 +2345,12 @@ blit_shadow_to_output(struct weston_output *output, .input_is_premult = true, }, .projection = { - .d = { /* transpose */ - 2.0f, 0.0f, 0.0f, 0.0f, - 0.0f, go->y_flip * 2.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -go->y_flip, 0.0f, 1.0f - }, + .M = WESTON_MAT4F( + 2.0, 0.0, 0.0, -1.0, + 0.0, go->y_flip * 2.0, 0.0, -go->y_flip, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ), .type = WESTON_MATRIX_TRANSFORM_SCALE | WESTON_MATRIX_TRANSFORM_TRANSLATE, }, @@ -3926,9 +3928,9 @@ gl_renderer_surface_copy_content(struct weston_surface *surface, glViewport(0, 0, cw, ch); set_blend_state(gr, false); if (buffer->buffer_origin == ORIGIN_TOP_LEFT) - ARRAY_COPY(sconf.projection.d, projmat_normal); + ARRAY_COPY(sconf.projection.M.colmaj, projmat_normal); else - ARRAY_COPY(sconf.projection.d, projmat_yinvert); + ARRAY_COPY(sconf.projection.M.colmaj, projmat_yinvert); sconf.projection.type = WESTON_MATRIX_TRANSFORM_SCALE | WESTON_MATRIX_TRANSFORM_TRANSLATE; diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index eeaad86e2..5332d1fb3 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -663,11 +663,11 @@ gl_shader_load_config(struct gl_renderer *gr, int i, j; glUniformMatrix4fv(shader->proj_uniform, - 1, GL_FALSE, sconf->projection.d); + 1, GL_FALSE, sconf->projection.M.colmaj); if (shader->surface_to_buffer_uniform != -1) glUniformMatrix4fv(shader->surface_to_buffer_uniform, - 1, GL_FALSE, sconf->surface_to_buffer.d); + 1, GL_FALSE, sconf->surface_to_buffer.M.colmaj); if (shader->color_uniform != -1) glUniform4fv(shader->color_uniform, 1, sconf->unicolor); diff --git a/shared/matrix.c b/shared/matrix.c index b78ff38ae..9d1819cbb 100644 --- a/shared/matrix.c +++ b/shared/matrix.c @@ -48,66 +48,37 @@ WL_EXPORT void weston_matrix_init(struct weston_matrix *matrix) { - static const struct weston_matrix identity = { - .d = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, - .type = 0, - }; - - memcpy(matrix, &identity, sizeof identity); + matrix->M = WESTON_MAT4F_IDENTITY; + matrix->type = 0; } /* m <- n * m, that is, m is multiplied on the LEFT. */ WL_EXPORT void weston_matrix_multiply(struct weston_matrix *m, const struct weston_matrix *n) { - struct weston_matrix tmp; - const float *row, *column; - int i, j, k; - - for (i = 0; i < 4; i++) { - row = m->d + i * 4; - for (j = 0; j < 4; j++) { - tmp.d[4 * i + j] = 0; - column = n->d + j; - for (k = 0; k < 4; k++) - tmp.d[4 * i + j] += row[k] * column[k * 4]; - } - } - tmp.type = m->type | n->type; - memcpy(m, &tmp, sizeof tmp); + m->M = weston_m4f_mul_m4f(n->M, m->M); + m->type |= n->type; } WL_EXPORT void weston_matrix_translate(struct weston_matrix *matrix, float x, float y, float z) { - struct weston_matrix translate = { - .d = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }, - .type = WESTON_MATRIX_TRANSFORM_TRANSLATE, - }; - - weston_matrix_multiply(matrix, &translate); + matrix->M = weston_m4f_mul_m4f(weston_m4f_translation(x, y, z), matrix->M); + matrix->type = WESTON_MATRIX_TRANSFORM_TRANSLATE; } WL_EXPORT void weston_matrix_scale(struct weston_matrix *matrix, float x, float y,float z) { - struct weston_matrix scale = { - .d = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 }, - .type = WESTON_MATRIX_TRANSFORM_SCALE, - }; - - weston_matrix_multiply(matrix, &scale); + matrix->M = weston_m4f_mul_m4f(weston_m4f_scaling(x, y, z), matrix->M); + matrix->type = WESTON_MATRIX_TRANSFORM_SCALE; } WL_EXPORT void weston_matrix_rotate_xy(struct weston_matrix *matrix, float cos, float sin) { - struct weston_matrix translate = { - .d = { cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, - .type = WESTON_MATRIX_TRANSFORM_ROTATE, - }; - - weston_matrix_multiply(matrix, &translate); + matrix->M = weston_m4f_mul_m4f(weston_m4f_rotation_xy(cos, sin), matrix->M); + matrix->type = WESTON_MATRIX_TRANSFORM_ROTATE; } /* v <- m * v */ @@ -115,16 +86,7 @@ WL_EXPORT void weston_matrix_transform(const struct weston_matrix *matrix, struct weston_vector *v) { - int i, j; - struct weston_vector t; - - for (i = 0; i < 4; i++) { - t.f[i] = 0; - for (j = 0; j < 4; j++) - t.f[i] += v->f[j] * matrix->d[i + j * 4]; - } - - *v = t; + v->v = weston_m4f_mul_v4f(matrix->M, v->v); } WL_EXPORT struct weston_coord @@ -132,17 +94,29 @@ weston_matrix_transform_coord(const struct weston_matrix *matrix, struct weston_coord c) { struct weston_coord out; - struct weston_vector t = { { c.x, c.y, 0.0, 1.0 } }; + struct weston_vector t = { .v.el = { c.x, c.y, 0.0, 1.0 } }; weston_matrix_transform(matrix, &t); - assert(fabsf(t.f[3]) > 1e-6); + assert(fabsf(t.v.el[3]) > 1e-6); - out.x = t.f[0] / t.f[3]; - out.y = t.f[1] / t.f[3]; + out.x = t.v.el[0] / t.v.el[3]; + out.y = t.v.el[1] / t.v.el[3]; return out; } +WL_EXPORT int +weston_matrix_invert(struct weston_matrix *inverse, + const struct weston_matrix *matrix) +{ + if (weston_m4f_invert(&inverse->M, matrix->M)) { + inverse->type = matrix->type; + return 0; + } + + return -1; +} + static inline void swap_rows(double *a, double *b) { @@ -177,118 +151,6 @@ find_pivot(double *column, unsigned k) return p; } -/* - * reference: Gene H. Golub and Charles F. van Loan. Matrix computations. - * 3rd ed. The Johns Hopkins University Press. 1996. - * LU decomposition, forward and back substitution: Chapter 3. - */ - -static int -matrix_invert(double *A, unsigned *p, const struct weston_matrix *matrix) -{ - unsigned i, j, k; - unsigned pivot; - double pv; - - for (i = 0; i < 4; ++i) - p[i] = i; - for (i = 16; i--; ) - A[i] = matrix->d[i]; - - /* LU decomposition with partial pivoting */ - for (k = 0; k < 4; ++k) { - pivot = find_pivot(&A[k * 4], k); - if (pivot != k) { - swap_unsigned(&p[k], &p[pivot]); - swap_rows(&A[k], &A[pivot]); - } - - pv = A[k * 4 + k]; - if (fabs(pv) < 1e-9) - return -1; /* zero pivot, not invertible */ - - for (i = k + 1; i < 4; ++i) { - A[i + k * 4] /= pv; - - for (j = k + 1; j < 4; ++j) - A[i + j * 4] -= A[i + k * 4] * A[k + j * 4]; - } - } - - return 0; -} - -static void -inverse_transform(const double *LU, const unsigned *p, float *v) -{ - /* Solve A * x = v, when we have P * A = L * U. - * P * A * x = P * v => L * U * x = P * v - * Let U * x = b, then L * b = P * v. - */ - double b[4]; - unsigned j; - - /* Forward substitution, column version, solves L * b = P * v */ - /* The diagonal of L is all ones, and not explicitly stored. */ - b[0] = v[p[0]]; - b[1] = (double)v[p[1]] - b[0] * LU[1 + 0 * 4]; - b[2] = (double)v[p[2]] - b[0] * LU[2 + 0 * 4]; - b[3] = (double)v[p[3]] - b[0] * LU[3 + 0 * 4]; - b[2] -= b[1] * LU[2 + 1 * 4]; - b[3] -= b[1] * LU[3 + 1 * 4]; - b[3] -= b[2] * LU[3 + 2 * 4]; - - /* backward substitution, column version, solves U * y = b */ -#if 1 - /* hand-unrolled, 25% faster for whole function */ - b[3] /= LU[3 + 3 * 4]; - b[0] -= b[3] * LU[0 + 3 * 4]; - b[1] -= b[3] * LU[1 + 3 * 4]; - b[2] -= b[3] * LU[2 + 3 * 4]; - - b[2] /= LU[2 + 2 * 4]; - b[0] -= b[2] * LU[0 + 2 * 4]; - b[1] -= b[2] * LU[1 + 2 * 4]; - - b[1] /= LU[1 + 1 * 4]; - b[0] -= b[1] * LU[0 + 1 * 4]; - - b[0] /= LU[0 + 0 * 4]; -#else - for (j = 3; j > 0; --j) { - unsigned k; - b[j] /= LU[j + j * 4]; - for (k = 0; k < j; ++k) - b[k] -= b[j] * LU[k + j * 4]; - } - - b[0] /= LU[0 + 0 * 4]; -#endif - - /* the result */ - for (j = 0; j < 4; ++j) - v[j] = b[j]; -} - -WL_EXPORT int -weston_matrix_invert(struct weston_matrix *inverse, - const struct weston_matrix *matrix) -{ - double LU[16]; /* column-major */ - unsigned perm[4]; /* permutation */ - unsigned c; - - if (matrix_invert(LU, perm, matrix) < 0) - return -1; - - weston_matrix_init(inverse); - for (c = 0; c < 4; ++c) - inverse_transform(LU, perm, &inverse->d[c * 4]); - inverse->type = matrix->type; - - return 0; -} - static bool m4f_LU_decompose(double *restrict LU, unsigned *restrict p, struct weston_mat4f M) { @@ -521,7 +383,7 @@ get_el(const struct weston_matrix *matrix, int row, int col) assert(row >= 0 && row <= 3); assert(col >= 0 && col <= 3); - return matrix->d[col * 4 + row]; + return matrix->M.col[col].el[row]; } static bool diff --git a/tests/color_util.c b/tests/color_util.c index d18800935..413da9860 100644 --- a/tests/color_util.c +++ b/tests/color_util.c @@ -366,7 +366,7 @@ weston_matrix_from_lcmsMAT3(struct weston_matrix *w, const struct lcmsMAT3 *m) for (c = 0; c < 3; c++) { for (r = 0; r < 3; r++) - w->d[c * 4 + r] = m->v[c].n[r]; + w->M.col[c].el[r] = m->v[c].n[r]; } } @@ -377,7 +377,7 @@ lcmsMAT3_from_weston_matrix(struct lcmsMAT3 *m, const struct weston_matrix *w) for (c = 0; c < 3; c++) { for (r = 0; r < 3; r++) - m->v[c].n[r] = w->d[c * 4 + r]; + m->v[c].n[r] = w->M.col[c].el[r]; } } diff --git a/tests/lcms_util.c b/tests/lcms_util.c index 3fe606329..5f2060970 100644 --- a/tests/lcms_util.c +++ b/tests/lcms_util.c @@ -32,6 +32,7 @@ #include #include +#include #include "shared/helpers.h" #include "color_util.h" #include "lcms_util.h" @@ -281,11 +282,9 @@ roundtrip_verification(cmsPipeline *DToB, cmsPipeline *BToD, float tolerance) test_assert_f32_lt(stat.two_norm.max, tolerance); } -static const struct weston_vector ZEROS = { - .f = { 0.0, 0.0, 0.0, 1.0 } -}; +static const struct weston_vector ZEROS = { .v = WESTON_VEC4F_ZERO }; static const struct weston_vector PCS_BLACK = { - .f = { + .v.el = { cmsPERCEPTUAL_BLACK_X, cmsPERCEPTUAL_BLACK_Y, cmsPERCEPTUAL_BLACK_Z, @@ -310,19 +309,19 @@ static cmsInt32Number transform_sampler(const float src[], float dst[], void *cargo) { const struct transform_sampler_context *tsc = cargo; - struct weston_vector stmp = { .f = { src[0], src[1], src[2], 1.0 } }; - struct weston_vector dtmp = { .f = { 0.0, 0.0, 0.0, 1.0 } }; + struct weston_vector stmp = { .v.el = { src[0], src[1], src[2], 1.0 } }; + struct weston_vector dtmp = { .v.el = { 0.0, 0.0, 0.0, 1.0 } }; if (tsc->dir == BPC_DIR_BTOD) weston_matrix_transform(&tsc->bpc, &stmp); - cmsDoTransform(tsc->t, stmp.f, dtmp.f, 1); + cmsDoTransform(tsc->t, stmp.v.el, dtmp.v.el, 1); if (tsc->dir == BPC_DIR_DTOB) weston_matrix_transform(&tsc->bpc, &dtmp); for (int i = 0; i < 3; i++) - dst[i] = dtmp.f[i]; + dst[i] = dtmp.v.el[i]; return 1; /* Success. */ } @@ -346,17 +345,17 @@ ComputeBlackPointCompensation(struct weston_matrix *m, // a = (bpout - D50) / (bpin - D50) // b = - D50* (bpout - bpin) / (bpin - D50) - tx = src_bp->f[0] - cmsD50_XYZ()->X; - ty = src_bp->f[1] - cmsD50_XYZ()->Y; - tz = src_bp->f[2] - cmsD50_XYZ()->Z; + tx = src_bp->v.x - cmsD50_XYZ()->X; + ty = src_bp->v.y - cmsD50_XYZ()->Y; + tz = src_bp->v.z - cmsD50_XYZ()->Z; - ax = (dst_bp->f[0] - cmsD50_XYZ()->X) / tx; - ay = (dst_bp->f[1] - cmsD50_XYZ()->Y) / ty; - az = (dst_bp->f[2] - cmsD50_XYZ()->Z) / tz; + ax = (dst_bp->v.x - cmsD50_XYZ()->X) / tx; + ay = (dst_bp->v.y - cmsD50_XYZ()->Y) / ty; + az = (dst_bp->v.z - cmsD50_XYZ()->Z) / tz; - bx = - cmsD50_XYZ()-> X * (dst_bp->f[0] - src_bp->f[0]) / tx; - by = - cmsD50_XYZ()-> Y * (dst_bp->f[1] - src_bp->f[1]) / ty; - bz = - cmsD50_XYZ()-> Z * (dst_bp->f[2] - src_bp->f[2]) / tz; + bx = - cmsD50_XYZ()-> X * (dst_bp->v.x - src_bp->v.x) / tx; + by = - cmsD50_XYZ()-> Y * (dst_bp->v.y - src_bp->v.y) / ty; + bz = - cmsD50_XYZ()-> Z * (dst_bp->v.z - src_bp->v.z) / tz; /* * [ax, 0, 0, bx ] diff --git a/tests/matrix-test.c b/tests/matrix-test.c index 2b8bd30b2..1e93a8c51 100644 --- a/tests/matrix-test.c +++ b/tests/matrix-test.c @@ -27,51 +27,16 @@ #include #include +#include #include "weston-test-client-helper.h" #include "weston-test-assert.h" -/* - * A helper to lay out a matrix in the natural writing order in code - * instead of needing to transpose in your mind every time you read it. - * The matrix is laid out as written: - * ⎡ a11 a12 a13 a14 ⎤ - * ⎢ a21 a22 a23 a24 ⎥ - * ⎢ a31 a32 a33 a34 ⎥ - * ⎣ a41 a42 a43 a44 ⎦ - * where the first digit is row and the second digit is column. - * - * The type field is set to the most pessimistic case possible so that if - * weston_matrix_invert() ever gets special-case code paths, we don't take - * them. - */ -#define MAT(a11, a12, a13, a14, \ - a21, a22, a23, a24, \ - a31, a32, a33, a34, \ - a41, a42, a43, a44) ((struct weston_matrix) \ - { \ - .d[0] = a11, .d[4] = a12, .d[ 8] = a13, .d[12] = a14, \ - .d[1] = a21, .d[5] = a22, .d[ 9] = a23, .d[13] = a24, \ - .d[2] = a31, .d[6] = a32, .d[10] = a33, .d[14] = a34, \ - .d[3] = a41, .d[7] = a42, .d[11] = a43, .d[15] = a44, \ - .type = WESTON_MATRIX_TRANSFORM_TRANSLATE | \ - WESTON_MATRIX_TRANSFORM_SCALE | \ - WESTON_MATRIX_TRANSFORM_ROTATE | \ - WESTON_MATRIX_TRANSFORM_OTHER, \ - }) - -static const struct weston_matrix IDENTITY = - MAT(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); +static const struct weston_matrix IDENTITY = { .M = WESTON_MAT4F_IDENTITY }; static void subtract_matrix(struct weston_matrix *from, const struct weston_matrix *what) { - unsigned i; - - for (i = 0; i < ARRAY_LENGTH(from->d); i++) - from->d[i] -= what->d[i]; + from->M = weston_m4f_sub_m4f(from->M, what->M); } static void @@ -81,7 +46,7 @@ print_matrix(const struct weston_matrix *m) for (r = 0; r < 4; ++r) { for (c = 0; c < 4; ++c) - testlog(" %14.6e", m->d[r + c * 4]); + testlog(" %14.6e", m->M.col[c].el[r]); testlog("\n"); } } @@ -93,21 +58,7 @@ print_matrix(const struct weston_matrix *m) static double matrix_inf_norm(const struct weston_matrix *mat) { - unsigned row; - double infnorm = -1.0; - - for (row = 0; row < 4; row++) { - unsigned col; - double sum = 0.0; - - for (col = 0; col < 4; col++) - sum += fabs(mat->d[col * 4 + row]); - - if (infnorm < sum) - infnorm = sum; - } - - return infnorm; + return weston_m4f_inf_norm(mat->M); } struct test_matrix { @@ -128,7 +79,8 @@ struct test_matrix { static const struct test_matrix matrices[] = { /* A very trivial case. */ { - .M = MAT(1, 0, 0, 0, + .M.M = WESTON_MAT4F( + 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4), @@ -179,7 +131,8 @@ static const struct test_matrix matrices[] = { * https://gitlab.freedesktop.org/pq/fourbyfour */ { - .M = MAT(1, 0, 0, 1980, + .M.M = WESTON_MAT4F( + 1, 0, 0, 1980, 0, 1, 0, 1080, 0, 0, 1, 0, 0, 0, 0, 1), @@ -199,7 +152,8 @@ static const struct test_matrix matrices[] = { /* cond = 1e3 */ { - .M = MAT(-4.12798022231678357619e-02, -7.93301899046665176529e-02, 2.49367040174418935772e-01, -2.22400462135059429070e-01, + .M.M = WESTON_MAT4F( + -4.12798022231678357619e-02, -7.93301899046665176529e-02, 2.49367040174418935772e-01, -2.22400462135059429070e-01, 2.02416121867255743849e-01, -2.25754422240346010187e-02, -2.91283152417864787953e-01, 1.49354988316431153139e-01, 6.18473094065821293874e-01, 5.81511312950217934548e-02, -1.18363610818063924590e+00, 8.00087538947595322547e-01, 1.25723127083294305972e-01, 7.72723720984487272290e-02, -3.76023220287807879991e-01, 2.82473279931768073148e-01), @@ -208,7 +162,8 @@ static const struct test_matrix matrices[] = { /* cond = 1e3, abs det = 15 */ { - .M = MAT(6.84154939885726509630e+00, -6.87241565273813304060e+00, -2.56772939909334070308e+01, -2.52185055099662420730e+01, + .M.M = WESTON_MAT4F( + 6.84154939885726509630e+00, -6.87241565273813304060e+00, -2.56772939909334070308e+01, -2.52185055099662420730e+01, 2.04511561406330022450e+00, -3.67551043874248994925e+00, -1.96421641406619129633e+00, -2.40644091603848320204e+00, 5.83631095663641819016e+00, -9.31051765621826277197e+00, -1.80402129629135217215e+01, -1.78475057662460052654e+01, -9.88588496379959025262e+00, 1.49790516545410774540e+01, 2.64975800675967363418e+01, 2.65795891678410747261e+01), @@ -217,7 +172,8 @@ static const struct test_matrix matrices[] = { /* cond = 700, abs det = 1e-6, invertible regardless of det */ { - .M = MAT(1.32125189257677579449e-03, -1.67411409720826992453e-01, 1.07940907587735196449e-01, -1.22163309792902186057e-01, + .M.M = WESTON_MAT4F( + 1.32125189257677579449e-03, -1.67411409720826992453e-01, 1.07940907587735196449e-01, -1.22163309792902186057e-01, -5.42113793774764013422e-02, 5.30455105336593901733e-01, -2.59607412684229155175e-01, 4.36480803188117993940e-01, 2.88175168292948129939e-03, -1.85262537685181277736e-01, 1.46265858042118279680e-01, -9.41398969709369287662e-02, -2.88900393087768159184e-03, 1.57987202530630227448e-01, -1.20781192010860280450e-01, 8.95194304475115387731e-02), @@ -226,7 +182,8 @@ static const struct test_matrix matrices[] = { /* cond = 1e6, this is a little more challenging */ { - .M = MAT(-4.41851445093878913983e-01, -5.16386185043831491548e-01, 2.86186055948129847160e-01, -5.79440137716940473211e-01, + .M.M = WESTON_MAT4F( + -4.41851445093878913983e-01, -5.16386185043831491548e-01, 2.86186055948129847160e-01, -5.79440137716940473211e-01, 2.49798696238173301154e-01, 2.84965614532234345901e-01, -1.65729639683955931595e-01, 3.12568045963485974248e-01, 3.15253213984537428161e-01, 3.71270066781250074328e-01, -2.02675623845341434937e-01, 4.19969870491003371971e-01, 5.60818677658178832424e-01, 6.45373659426444201692e-01, -3.68902466471524526082e-01, 7.13785795079988516498e-01), @@ -235,7 +192,8 @@ static const struct test_matrix matrices[] = { /* cond = 15, abs det = 1e-9, should be well invertible */ { - .M = MAT(-5.37536200142514660589e-05, 7.92552373388843642288e-03, -3.90554524958281433500e-03, 2.68892064500873568395e-03, + .M.M = WESTON_MAT4F( + -5.37536200142514660589e-05, 7.92552373388843642288e-03, -3.90554524958281433500e-03, 2.68892064500873568395e-03, -9.72329428437283989350e-03, 8.32075145342783470404e-03, 6.52648485926096092596e-03, 1.06707947887298994737e-03, 1.04453728969657322345e-02, -1.03627268579679666927e-02, -3.56835980207569763989e-03, -3.95935925157862422114e-03, 5.37160838929722633805e-03, 6.13466744624343262009e-05, -1.23695935407398946090e-04, 8.21231194921675112380e-04), diff --git a/tests/matrix-transform-test.c b/tests/matrix-transform-test.c index 6c94e70d8..2a07ec6a8 100644 --- a/tests/matrix-transform-test.c +++ b/tests/matrix-transform-test.c @@ -34,6 +34,7 @@ #include #include "libweston-internal.h" #include "libweston/matrix.h" +#include #include "weston-test-client-helper.h" #include "weston-test-assert.h" @@ -382,40 +383,40 @@ simple_transform_vector(struct weston_output *output, struct weston_vector in) switch (output->transform) { case WL_OUTPUT_TRANSFORM_NORMAL: - out.f[0] = (-output->pos.c.x + in.f[0]) * scale; - out.f[1] = (-output->pos.c.y + in.f[1]) * scale; + out.v.el[0] = (-output->pos.c.x + in.v.el[0]) * scale; + out.v.el[1] = (-output->pos.c.y + in.v.el[1]) * scale; break; case WL_OUTPUT_TRANSFORM_FLIPPED: - out.f[0] = (output->pos.c.x + output->width - in.f[0]) * scale; - out.f[1] = (-output->pos.c.y + in.f[1]) * scale; + out.v.el[0] = (output->pos.c.x + output->width - in.v.el[0]) * scale; + out.v.el[1] = (-output->pos.c.y + in.v.el[1]) * scale; break; case WL_OUTPUT_TRANSFORM_90: - out.f[0] = (-output->pos.c.y + in.f[1]) * scale; - out.f[1] = (output->pos.c.x + output->width - in.f[0]) * scale; + out.v.el[0] = (-output->pos.c.y + in.v.el[1]) * scale; + out.v.el[1] = (output->pos.c.x + output->width - in.v.el[0]) * scale; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - out.f[0] = (-output->pos.c.y + in.f[1]) * scale; - out.f[1] = (-output->pos.c.x + in.f[0]) * scale; + out.v.el[0] = (-output->pos.c.y + in.v.el[1]) * scale; + out.v.el[1] = (-output->pos.c.x + in.v.el[0]) * scale; break; case WL_OUTPUT_TRANSFORM_180: - out.f[0] = (output->pos.c.x + output->width - in.f[0]) * scale; - out.f[1] = (output->pos.c.y + output->height - in.f[1]) * scale; + out.v.el[0] = (output->pos.c.x + output->width - in.v.el[0]) * scale; + out.v.el[1] = (output->pos.c.y + output->height - in.v.el[1]) * scale; break; case WL_OUTPUT_TRANSFORM_FLIPPED_180: - out.f[0] = (-output->pos.c.x + in.f[0]) * scale; - out.f[1] = (output->pos.c.y + output->height - in.f[1]) * scale; + out.v.el[0] = (-output->pos.c.x + in.v.el[0]) * scale; + out.v.el[1] = (output->pos.c.y + output->height - in.v.el[1]) * scale; break; case WL_OUTPUT_TRANSFORM_270: - out.f[0] = (output->pos.c.y + output->height - in.f[1]) * scale; - out.f[1] = (-output->pos.c.x + in.f[0]) * scale; + out.v.el[0] = (output->pos.c.y + output->height - in.v.el[1]) * scale; + out.v.el[1] = (-output->pos.c.x + in.v.el[0]) * scale; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - out.f[0] = (output->pos.c.y + output->height - in.f[1]) * scale; - out.f[1] = (output->pos.c.x + output->width - in.f[0]) * scale; + out.v.el[0] = (output->pos.c.y + output->height - in.v.el[1]) * scale; + out.v.el[1] = (output->pos.c.x + output->width - in.v.el[0]) * scale; break; } - out.f[2] = 0; - out.f[3] = 1; + out.v.el[2] = 0; + out.v.el[3] = 1; return out; } @@ -426,7 +427,7 @@ output_test_all_transforms(struct weston_output *output, { int i; int transform; - struct weston_vector t = { { 7.0, 13.0, 0.0, 1.0 } }; + struct weston_vector t = { .v = WESTON_VEC4F(7.0, 13.0, 0.0, 1.0) }; struct weston_vector v, sv; for (transform = WL_OUTPUT_TRANSFORM_NORMAL; @@ -443,7 +444,7 @@ output_test_all_transforms(struct weston_output *output, weston_matrix_transform(&output->matrix, &v); sv = simple_transform_vector(output, t); for (i = 0; i < 4; i++) - test_assert_f32_eq (sv.f[i], v.f[i]); + test_assert_f32_eq(sv.v.el[i], v.v.el[i]); } }