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 <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2022-02-09 12:38:20 -06:00
parent fe4d5711bf
commit e1b4ad7d0b
5 changed files with 182 additions and 0 deletions

View File

@ -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);

View File

@ -27,6 +27,7 @@
#ifndef WESTON_MATRIX_H
#define WESTON_MATRIX_H
#include <assert.h>
#include <stdbool.h>
#include <wayland-server-protocol.h>
@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)
{