From e1b4ad7d0bd6f3dbefd018549c8ba997d4cef034 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Wed, 9 Feb 2022 12:38:20 -0600 Subject: [PATCH] matrix: Introduce weston_coord All through weston we have code that passes int x, y or float x, y or wl_fixed_t x, y pairs. These pairs are frequently converted to/from wl_fixed_t and other types. We also have struct vec2d and struct weston_geometry which also contain coordinate pairs. Let's create a family of coordinate vector structures for coordinate pairs and use it anywhere we sensibly can. This has a few benefits - it helps remove intermediate conversion between fixed/float/int types. It lets us roll the homogenous coordinate normalization bits into helper functions instead of needing them open coded throughout the source. Possibly most importantly, it also allows us to do some compile time validation of what coordinate space we're working in. Signed-off-by: Derek Foreman --- include/libweston/libweston.h | 12 +++++ include/libweston/matrix.h | 83 +++++++++++++++++++++++++++++++++++ libweston/backend.h | 5 +++ libweston/compositor.c | 66 ++++++++++++++++++++++++++++ shared/matrix.c | 16 +++++++ 5 files changed, 182 insertions(+) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 31765a706..42d8a6eeb 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1811,6 +1811,18 @@ void weston_view_to_global_float(struct weston_view *view, float sx, float sy, float *x, float *y); +struct weston_coord_global __attribute__ ((warn_unused_result)) +weston_coord_surface_to_global(const struct weston_view *view, + struct weston_coord_surface coord); + +struct weston_coord_surface __attribute__ ((warn_unused_result)) +weston_coord_global_to_surface(const struct weston_view *view, + struct weston_coord_global coord); + +struct weston_coord_buffer __attribute__ ((warn_unused_result)) +weston_coord_surface_to_buffer(const struct weston_surface *surface, + struct weston_coord_surface coord); + void weston_view_from_global(struct weston_view *view, int32_t x, int32_t y, int32_t *vx, int32_t *vy); diff --git a/include/libweston/matrix.h b/include/libweston/matrix.h index ffa5b7557..842d96886 100644 --- a/include/libweston/matrix.h +++ b/include/libweston/matrix.h @@ -27,6 +27,7 @@ #ifndef WESTON_MATRIX_H #define WESTON_MATRIX_H +#include #include #include @@ -51,6 +52,28 @@ struct weston_vector { float f[4]; }; +/** Arbitrary coordinates in any space */ +struct weston_coord { + double x; + double y; +}; + +/** Coordinates in some weston_buffer (physical pixels) */ +struct weston_coord_buffer { + struct weston_coord c; +}; + +/** Coordinates in the global compositor space (logical pixels) */ +struct weston_coord_global { + struct weston_coord c; +}; + +/** surface-local coordinates on a specific surface */ +struct weston_coord_surface { + struct weston_coord c; + const struct weston_surface *coordinate_space_id; +}; + void weston_matrix_init(struct weston_matrix *matrix); void @@ -66,6 +89,10 @@ void weston_matrix_transform(const struct weston_matrix *matrix, struct weston_vector *v); +struct weston_coord +weston_matrix_transform_coord(const struct weston_matrix *matrix, + struct weston_coord coord); + int weston_matrix_invert(struct weston_matrix *inverse, const struct weston_matrix *matrix); @@ -83,6 +110,62 @@ weston_matrix_init_transform(struct weston_matrix *matrix, int x, int y, int width, int height, int scale); +static inline struct weston_coord __attribute__ ((warn_unused_result)) +weston_coord_from_fixed(wl_fixed_t x, wl_fixed_t y) +{ + struct weston_coord out; + + out.x = wl_fixed_to_double(x); + out.y = wl_fixed_to_double(y); + return out; +} + +static inline struct weston_coord __attribute__ ((warn_unused_result)) +weston_coord(double x, double y) +{ + return (struct weston_coord){ .x = x, .y = y }; +} + +static inline struct weston_coord_surface __attribute__ ((warn_unused_result)) +weston_coord_surface(double x, double y, const struct weston_surface *surface) +{ + struct weston_coord_surface out; + + assert(surface); + + out.c = weston_coord(x, y); + out.coordinate_space_id = surface; + + return out; +} + +static inline struct weston_coord_surface __attribute__ ((warn_unused_result)) +weston_coord_surface_from_fixed(wl_fixed_t x, wl_fixed_t y, + const struct weston_surface *surface) +{ + struct weston_coord_surface out; + + assert(surface); + + out.c.x = wl_fixed_to_double(x); + out.c.y = wl_fixed_to_double(y); + out.coordinate_space_id = surface; + + return out; +} + +static inline struct weston_coord __attribute__ ((warn_unused_result)) +weston_coord_add(struct weston_coord a, struct weston_coord b) +{ + return weston_coord(a.x + b.x, a.y + b.y); +} + +static inline struct weston_coord __attribute__ ((warn_unused_result)) +weston_coord_sub(struct weston_coord a, struct weston_coord b) +{ + return weston_coord(a.x - b.x, a.y - b.y); +} + #ifdef __cplusplus } #endif diff --git a/libweston/backend.h b/libweston/backend.h index a3afb32f3..3f8caff0a 100644 --- a/libweston/backend.h +++ b/libweston/backend.h @@ -165,6 +165,11 @@ int weston_output_mode_set_native(struct weston_output *output, struct weston_mode *mode, int32_t scale); + +struct weston_coord_global +weston_coord_global_from_output_point(double x, double y, + const struct weston_output *output); + void weston_output_transform_coordinate(struct weston_output *output, double device_x, double device_y, diff --git a/libweston/compositor.c b/libweston/compositor.c index 46d62ef07..4c1a99285 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -678,6 +678,46 @@ weston_view_to_global_float(struct weston_view *view, *y = v.f[1] / v.f[3]; } +WL_EXPORT struct weston_coord_global +weston_coord_surface_to_global(const struct weston_view *view, + struct weston_coord_surface coord) +{ + struct weston_coord_global out; + + assert(!view->transform.dirty); + assert(view->surface == coord.coordinate_space_id); + + out.c = weston_matrix_transform_coord(&view->transform.matrix, + coord.c); + return out; +} + +WL_EXPORT struct weston_coord_surface +weston_coord_global_to_surface(const struct weston_view *view, + struct weston_coord_global coord) +{ + struct weston_coord_surface out; + + assert(!view->transform.dirty); + out.c = weston_matrix_transform_coord(&view->transform.inverse, + coord.c); + out.coordinate_space_id = view->surface; + return out; +} + +WL_EXPORT struct weston_coord_buffer +weston_coord_surface_to_buffer(const struct weston_surface *surface, + struct weston_coord_surface coord) +{ + struct weston_coord_buffer tmp; + + assert(surface == coord.coordinate_space_id); + + tmp.c = weston_matrix_transform_coord(&surface->surface_to_buffer_matrix, + coord.c); + return tmp; +} + WL_EXPORT pixman_box32_t weston_matrix_transform_rect(struct weston_matrix *matrix, pixman_box32_t rect) @@ -6421,6 +6461,32 @@ weston_compositor_add_output(struct weston_compositor *compositor, weston_view_geometry_dirty(view); } +/** Create a weston_coord_global from a point and a weston_output + * + * \param x x coordinate on the output + * \param y y coordinate on the output + * \param output the weston_output object + * \return coordinate in global space corresponding to x, y on the output + * + * Transforms coordinates from the device coordinate space (physical pixel + * units) to the global coordinate space (logical pixel units). This takes + * into account output transform and scale. + * + * \ingroup output + * \internal + */ +WL_EXPORT struct weston_coord_global +weston_coord_global_from_output_point(double x, double y, + const struct weston_output *output) +{ + struct weston_coord c; + struct weston_coord_global tmp; + + c = weston_coord(x, y); + tmp.c = weston_matrix_transform_coord(&output->inverse_matrix, c); + return tmp; +} + /** Transform device coordinates into global coordinates * * \param output the weston_output object diff --git a/shared/matrix.c b/shared/matrix.c index f41abe763..472f299a0 100644 --- a/shared/matrix.c +++ b/shared/matrix.c @@ -126,6 +126,22 @@ weston_matrix_transform(const struct weston_matrix *matrix, *v = t; } +WL_EXPORT struct weston_coord +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 } }; + + weston_matrix_transform(matrix, &t); + + assert(fabsf(t.f[3]) > 1e-6); + + out.x = t.f[0] / t.f[3]; + out.y = t.f[1] / t.f[3]; + return out; +} + static inline void swap_rows(double *a, double *b) {