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:
parent
b8063dbb13
commit
bf222f1897
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user