gl-renderer: Use clip_vertex struct for boxes in clipper API

Carry on the common vertex representation front by making boxes use
the clip_vertex struct.

A new function clip_quad_box32() is added to clearly separate the main
function taking a clip_vertex struct from the utility function taking
a pixman_box32 struct.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2023-05-25 12:06:50 +02:00 committed by Pekka Paalanen
parent b8063dbb13
commit bf222f1897
5 changed files with 77 additions and 53 deletions

View file

@ -135,13 +135,17 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
/* Find axis-aligned bounding box. */
if (!quad->axis_aligned) {
quad->bbox.x1 = quad->bbox.x2 = quad->polygon[0].x;
quad->bbox.y1 = quad->bbox.y2 = quad->polygon[0].y;
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.x1 = MIN(quad->bbox.x1, quad->polygon[i].x);
quad->bbox.x2 = MAX(quad->bbox.x2, quad->polygon[i].x);
quad->bbox.y1 = MIN(quad->bbox.y1, quad->polygon[i].y);
quad->bbox.y2 = MAX(quad->bbox.y2, quad->polygon[i].y);
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);
}
}
}
@ -295,7 +299,7 @@ redraw_handler(struct widget *widget, void *data)
int n;
rect_to_quad(&g->quad, &cliptest->view, &quad);
n = clip_quad(&quad, &g->surf, v);
n = clip_quad_box32(&quad, &g->surf, v);
widget_get_allocation(cliptest->widget, &allocation);
@ -589,7 +593,7 @@ benchmark(void)
for (i = 0; i < N; i++) {
geometry_set_phi(&geom, (float)i / 360.0f);
rect_to_quad(&geom.quad, &view, &quad);
clip_quad(&quad, &geom.surf, v);
clip_quad_box32(&quad, &geom.surf, v);
}
t = read_timer();

View file

@ -496,13 +496,17 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev,
/* Find axis-aligned bounding box. */
if (!quad->axis_aligned) {
quad->bbox.x1 = quad->bbox.x2 = quad->polygon[0].x;
quad->bbox.y1 = quad->bbox.y2 = quad->polygon[0].y;
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.x1 = MIN(quad->bbox.x1, quad->polygon[i].x);
quad->bbox.x2 = MAX(quad->bbox.x2, quad->polygon[i].x);
quad->bbox.y1 = MIN(quad->bbox.y1, quad->polygon[i].y);
quad->bbox.y2 = MAX(quad->bbox.y2, quad->polygon[i].y);
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);
}
}
}
@ -606,7 +610,7 @@ texture_region(struct weston_paint_node *pnode,
* To do this, we first calculate the (up to eight) points at the
* intersection of the edges of the quad and the surface rect.
*/
n = clip_quad(&quad, &surf_rects[j], v);
n = clip_quad_box32(&quad, &surf_rects[j], v);
if (n >= 3) {
v += n;
vtxcnt[nvtx++] = n;

View file

@ -112,25 +112,25 @@ clip_append_vertex(struct clip_context *ctx, float x, float y)
static enum path_transition
path_transition_left_edge(struct clip_context *ctx, float x, float y)
{
return ((ctx->prev.x >= ctx->clip.x1) << 1) | (x >= ctx->clip.x1);
return ((ctx->prev.x >= ctx->box[0].x) << 1) | (x >= ctx->box[0].x);
}
static enum path_transition
path_transition_right_edge(struct clip_context *ctx, float x, float y)
{
return ((ctx->prev.x < ctx->clip.x2) << 1) | (x < ctx->clip.x2);
return ((ctx->prev.x < ctx->box[1].x) << 1) | (x < ctx->box[1].x);
}
static enum path_transition
path_transition_top_edge(struct clip_context *ctx, float x, float y)
{
return ((ctx->prev.y >= ctx->clip.y1) << 1) | (y >= ctx->clip.y1);
return ((ctx->prev.y >= ctx->box[0].y) << 1) | (y >= ctx->box[0].y);
}
static enum path_transition
path_transition_bottom_edge(struct clip_context *ctx, float x, float y)
{
return ((ctx->prev.y < ctx->clip.y2) << 1) | (y < ctx->clip.y2);
return ((ctx->prev.y < ctx->box[1].y) << 1) | (y < ctx->box[1].y);
}
static void
@ -223,7 +223,7 @@ clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
for (i = 0; i < src->n; i++) {
trans = path_transition_left_edge(ctx, src->pos[i].x, src->pos[i].y);
clip_polygon_leftright(ctx, trans, src->pos[i].x, src->pos[i].y,
ctx->clip.x1);
ctx->box[0].x);
}
return ctx->vertices - dst;
}
@ -242,7 +242,7 @@ clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
for (i = 0; i < src->n; i++) {
trans = path_transition_right_edge(ctx, src->pos[i].x, src->pos[i].y);
clip_polygon_leftright(ctx, trans, src->pos[i].x, src->pos[i].y,
ctx->clip.x2);
ctx->box[1].x);
}
return ctx->vertices - dst;
}
@ -261,7 +261,7 @@ clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
for (i = 0; i < src->n; i++) {
trans = path_transition_top_edge(ctx, src->pos[i].x, src->pos[i].y);
clip_polygon_topbottom(ctx, trans, src->pos[i].x, src->pos[i].y,
ctx->clip.y1);
ctx->box[0].y);
}
return ctx->vertices - dst;
}
@ -280,7 +280,7 @@ clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
for (i = 0; i < src->n; i++) {
trans = path_transition_bottom_edge(ctx, src->pos[i].x, src->pos[i].y);
clip_polygon_topbottom(ctx, trans, src->pos[i].x, src->pos[i].y,
ctx->clip.y2);
ctx->box[1].y);
}
return ctx->vertices - dst;
}
@ -322,27 +322,23 @@ clip_transformed(struct clip_context *ctx,
}
int
clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect,
struct clip_vertex *vertices)
clip_quad(struct gl_quad *quad,
const struct clip_vertex box[2],
struct clip_vertex *restrict vertices)
{
struct clip_context ctx = {
.clip.x1 = surf_rect->x1,
.clip.y1 = surf_rect->y1,
.clip.x2 = surf_rect->x2,
.clip.y2 = surf_rect->y2,
};
struct clip_context ctx;
int i, n;
/* Simple case: quad edges are parallel to surface rect edges, there
* will be either four or zero edges. We just need to clip the quad to
* the surface rect bounds and test for non-zero area:
/* Simple case: quad edges are parallel to clipping box edges, there
* will be either four or zero edges. We just need to clamp the quad
* edges to the clipping box edges and test for non-zero area:
*/
if (quad->axis_aligned) {
for (i = 0; i < 4; i++) {
vertices[i].x = CLIP(quad->polygon[i].x,
ctx.clip.x1, ctx.clip.x2);
box[0].x, box[1].x);
vertices[i].y = CLIP(quad->polygon[i].y,
ctx.clip.y1, ctx.clip.y2);
box[0].y, box[1].y);
}
if ((vertices[0].x != vertices[1].x) &&
(vertices[0].y != vertices[2].y))
@ -352,10 +348,10 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect,
}
/* Transformed case: first, simple bounding box check to discard early a
* quad that does not intersect with the rect:
* quad that does not intersect with the clipping box:
*/
if ((quad->bbox.x1 >= ctx.clip.x2) || (quad->bbox.x2 <= ctx.clip.x1) ||
(quad->bbox.y1 >= ctx.clip.y2) || (quad->bbox.y2 <= ctx.clip.y1))
if ((quad->bbox[0].x >= box[1].x) || (quad->bbox[1].x <= box[0].x) ||
(quad->bbox[0].y >= box[1].y) || (quad->bbox[1].y <= box[0].y))
return 0;
/* Then, use a general polygon clipping algorithm to clip the quad with
@ -364,6 +360,7 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect,
* https://www.codeguru.com/cplusplus/polygon-clipping/
* but without looking at any of that code.
*/
memcpy(&ctx.box, box, 2 * sizeof *box);
n = clip_transformed(&ctx, quad->polygon, 4, vertices);
if (n < 3)
@ -371,3 +368,16 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect,
return n;
}
int
clip_quad_box32(struct gl_quad *quad,
const struct pixman_box32 *box,
struct clip_vertex *restrict vertices)
{
struct clip_vertex box_vertices[2] = {
{ box->x1, box->y1 },
{ box->x2, box->y2 }
};
return clip_quad(quad, box_vertices, vertices);
}

View file

@ -35,18 +35,13 @@ struct clip_vertex {
struct gl_quad {
struct clip_vertex polygon[4];
struct { float x1, y1, x2, y2; } bbox; /* Valid if !axis_aligned. */
struct clip_vertex bbox[2]; /* Valid if !axis_aligned. */
bool axis_aligned;
};
struct clip_context {
struct clip_vertex prev;
struct {
float x1, y1;
float x2, y2;
} clip;
struct clip_vertex box[2];
struct clip_vertex *vertices;
};
@ -61,14 +56,25 @@ clip_transformed(struct clip_context *ctx,
/*
* Compute the boundary vertices of the intersection of an arbitrary
* quadrilateral 'quad' and the axis-aligned rectangle 'surf_rect'. The vertices
* 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.
*/
int
clip_quad(struct gl_quad *quad,
pixman_box32_t *surf_rect,
struct clip_vertex *vertices);
const struct clip_vertex box[2],
struct clip_vertex *restrict vertices);
/*
* Utility function calling 'clip_quad' but taking a pixman_box32 pointer as
* clipping box.
*/
int
clip_quad_box32(struct gl_quad *quad,
const struct pixman_box32* box,
struct clip_vertex *restrict vertices);
#endif

View file

@ -46,10 +46,10 @@
static void
populate_clip_context (struct clip_context *ctx)
{
ctx->clip.x1 = BOUNDING_BOX_LEFT_X;
ctx->clip.y1 = BOUNDING_BOX_BOTTOM_Y;
ctx->clip.x2 = BOUNDING_BOX_RIGHT_X;
ctx->clip.y2 = BOUNDING_BOX_TOP_Y;
ctx->box[0].x = BOUNDING_BOX_LEFT_X;
ctx->box[0].y = BOUNDING_BOX_BOTTOM_Y;
ctx->box[1].x = BOUNDING_BOX_RIGHT_X;
ctx->box[1].y = BOUNDING_BOX_TOP_Y;
}
static int