gl-renderer: Add init_quad() to clipper

Extract quad bounding box initialization from the GL renderer and move
it to a dedicated initialization function in the clipper. It's used by
both the renderer and the clipping test client, which further reduces
code duplication.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2023-05-25 12:58:04 +02:00 committed by Pekka Paalanen
parent f74c5a4102
commit 2d0d0175d2
4 changed files with 70 additions and 60 deletions

View file

@ -23,9 +23,9 @@
*/
/* cliptest:
* For debugging the rect_to_quad() and clip_quad() functions. An arbitrary
* quad (red) is transformed from global coordinate space to surface
* coordinate space and clipped to an axis-aligned rect (blue).
* For debugging the quad clipper. An arbitrary quad (red) is transformed
* from global coordinate space to surface coordinate space and clipped to
* an axis-aligned rect (blue).
*
* controls:
* surface rect position: mouse left drag, keys: w a s d
@ -111,8 +111,8 @@ weston_coord_global_to_surface(struct weston_view *view, struct weston_coord_glo
/* Keep this in sync with what is in gl-renderer.c! */
static void
rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
struct gl_quad *quad)
global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
struct clip_vertex polygon[4], bool *axis_aligned)
{
struct weston_coord_global rect_g[4] = {
{ .c = weston_coord(rect->x1, rect->y1) },
@ -123,31 +123,14 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
struct weston_coord rect_s;
int i;
/* Transform rect to surface space. */
for (i = 0; i < 4; i++) {
rect_s = weston_coord_global_to_surface(ev, rect_g[i]).c;
quad->polygon[i].x = (float)rect_s.x;
quad->polygon[i].y = (float)rect_s.y;
polygon[i].x = (float)rect_s.x;
polygon[i].y = (float)rect_s.y;
}
quad->axis_aligned = !ev->transform.enabled ||
*axis_aligned = !ev->transform.enabled ||
(ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
/* Find axis-aligned bounding box. */
if (!quad->axis_aligned) {
quad->bbox[0].x = quad->bbox[1].x = quad->polygon[0].x;
quad->bbox[0].y = quad->bbox[1].y = quad->polygon[0].y;
for (i = 1; i < 4; i++) {
quad->bbox[0].x = MIN(quad->bbox[0].x,
quad->polygon[i].x);
quad->bbox[1].x = MAX(quad->bbox[1].x,
quad->polygon[i].x);
quad->bbox[0].y = MIN(quad->bbox[0].y,
quad->polygon[i].y);
quad->bbox[1].y = MAX(quad->bbox[1].y,
quad->polygon[i].y);
}
}
}
/* ---------------------- copied ends -----------------------*/
@ -295,10 +278,13 @@ redraw_handler(struct widget *widget, void *data)
cairo_t *cr;
cairo_surface_t *surface;
struct gl_quad quad;
struct clip_vertex v[8];
struct clip_vertex transformed_v[4], v[8];
bool axis_aligned;
int n;
rect_to_quad(&g->quad, &cliptest->view, &quad);
global_to_surface(&g->quad, &cliptest->view, transformed_v,
&axis_aligned);
init_quad(&quad, transformed_v, axis_aligned);
n = clip_quad_box32(&quad, &g->surf, v);
widget_get_allocation(cliptest->widget, &allocation);
@ -567,7 +553,8 @@ benchmark(void)
struct weston_view view;
struct geometry geom;
struct gl_quad quad;
struct clip_vertex v[8];
struct clip_vertex transformed_v[4], v[8];
bool axis_aligned;
int i;
double t;
const int N = 1000000;
@ -592,7 +579,9 @@ benchmark(void)
reset_timer();
for (i = 0; i < N; i++) {
geometry_set_phi(&geom, (float)i / 360.0f);
rect_to_quad(&geom.quad, &view, &quad);
global_to_surface(&geom.quad, &view, transformed_v,
&axis_aligned);
init_quad(&quad, transformed_v, axis_aligned);
clip_quad_box32(&quad, &geom.surf, v);
}
t = read_timer();

View file

@ -472,8 +472,8 @@ timeline_submit_render_sync(struct gl_renderer *gr,
}
static void
rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
struct gl_quad *quad)
global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
struct clip_vertex polygon[4], bool *axis_aligned)
{
struct weston_coord_global rect_g[4] = {
{ .c = weston_coord(rect->x1, rect->y1) },
@ -484,31 +484,14 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
struct weston_coord rect_s;
int i;
/* Transform rect to surface space. */
for (i = 0; i < 4; i++) {
rect_s = weston_coord_global_to_surface(ev, rect_g[i]).c;
quad->polygon[i].x = (float)rect_s.x;
quad->polygon[i].y = (float)rect_s.y;
polygon[i].x = (float)rect_s.x;
polygon[i].y = (float)rect_s.y;
}
quad->axis_aligned = !ev->transform.enabled ||
*axis_aligned = !ev->transform.enabled ||
(ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
/* Find axis-aligned bounding box. */
if (!quad->axis_aligned) {
quad->bbox[0].x = quad->bbox[1].x = quad->polygon[0].x;
quad->bbox[0].y = quad->bbox[1].y = quad->polygon[0].y;
for (i = 1; i < 4; i++) {
quad->bbox[0].x = MIN(quad->bbox[0].x,
quad->polygon[i].x);
quad->bbox[1].x = MAX(quad->bbox[1].x,
quad->polygon[i].x);
quad->bbox[0].y = MIN(quad->bbox[0].y,
quad->polygon[i].y);
quad->bbox[1].y = MAX(quad->bbox[1].y,
quad->polygon[i].y);
}
}
}
static bool
@ -572,7 +555,8 @@ texture_region(struct weston_paint_node *pnode,
pixman_box32_t *rects, *surf_rects;
pixman_box32_t *raw_rects;
int i, j, nrects, nsurf, raw_nrects;
bool used_band_compression;
bool used_band_compression, axis_aligned;
struct clip_vertex polygon[4];
struct gl_quad quad;
raw_rects = pixman_region32_rectangles(region, &raw_nrects);
@ -593,7 +577,8 @@ texture_region(struct weston_paint_node *pnode,
vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
for (i = 0; i < nrects; i++) {
rect_to_quad(&rects[i], ev, &quad);
global_to_surface(&rects[i], ev, polygon, &axis_aligned);
init_quad(&quad, polygon, axis_aligned);
for (j = 0; j < nsurf; j++) {
int n;

View file

@ -329,6 +329,30 @@ clip_transformed(const struct clip_vertex *polygon,
return n;
}
void
init_quad(struct gl_quad *quad,
const struct clip_vertex polygon[4],
bool axis_aligned)
{
int i;
memcpy(quad->polygon, polygon, 4 * sizeof *polygon);
quad->axis_aligned = axis_aligned;
if (axis_aligned)
return;
/* Find axis-aligned bounding box. */
quad->bbox[0].x = quad->bbox[1].x = polygon[0].x;
quad->bbox[0].y = quad->bbox[1].y = polygon[0].y;
for (i = 1; i < 4; i++) {
quad->bbox[0].x = MIN(quad->bbox[0].x, polygon[i].x);
quad->bbox[1].x = MAX(quad->bbox[1].x, polygon[i].x);
quad->bbox[0].y = MIN(quad->bbox[0].y, polygon[i].y);
quad->bbox[1].y = MAX(quad->bbox[1].y, polygon[i].y);
}
}
int
clip_quad(struct gl_quad *quad,
const struct clip_vertex box[2],

View file

@ -49,13 +49,25 @@ clip_transformed(const struct clip_vertex *polygon,
struct clip_vertex *restrict vertices);
/*
* Compute the boundary vertices of the intersection of an arbitrary
* quadrilateral stored into a 'quad' clipping context and a clipping
* 'box'. 'box' points to an array of 2 vertices where the values of the 1st
* vertex are less than or equal to the values of the 2nd vertex. The vertices
* are written to 'vertices', and the return value is the number of vertices.
* Vertices are produced in clockwise winding order. Guarantees to produce
* either zero vertices, or 3-8 vertices with non-zero polygon area.
* Initialize a 'quad' clipping context. 'polygon' points to an array of 4
* vertices defining a convex quadrilateral of any winding order. Call
* 'clip_quad()' to clip an initialized 'quad' to a clipping box. Clipping is
* faster if 'polygon' is an axis-aligned rectangle with edges parallel to the
* axes of the coordinate space. 'axis_aligned' indicates whether 'polygon'
* respects the conditions above.
*/
void
init_quad(struct gl_quad *quad,
const struct clip_vertex polygon[4],
bool axis_aligned);
/*
* Compute the boundary vertices of the intersection of a convex quadrilateral
* stored into a 'quad' clipping context and a clipping 'box'. 'box' points to
* an array of 2 vertices where the values of the 1st vertex are less than or
* equal to the values of the 2nd vertex. Either 0 or [3, 8] resulting vertices,
* with the same winding order than the 'polygon' passed to 'init_quad()', are
* written to 'vertices'. The return value is the number of vertices created.
*/
int
clip_quad(struct gl_quad *quad,