From 49053a2aa2c631f202f29b548fd16bdcc6fe9a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Wed, 8 Mar 2023 10:43:06 +0100 Subject: [PATCH] gl-renderer: Store clipped vertices directly into the vertex buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move vertex clipper back to single-precision floating point intermediates. Since positions are sent down the graphics hardware as single-precision values, this prevents useless conversions between single and double precision values and lets compilers fit twice as much data into vector registers. It also removes a copy by letting the clipper store vertices directly into the vertex buffer. This is mostly reverting the conversion to double-precision that happened along with the switch to the weston_coord struct for vertex coordinates (commit 10e70bf23c0a9845aa8865216763e7e29ef390f3). Signed-off-by: Loïc Molinari --- clients/cliptest.c | 78 +++++++++++++++-------------- libweston/renderer-gl/gl-renderer.c | 44 ++++++++-------- libweston/vertex-clipping.c | 33 ++++++------ libweston/vertex-clipping.h | 19 +++---- tests/vertex-clip-test.c | 6 +-- 5 files changed, 91 insertions(+), 89 deletions(-) diff --git a/clients/cliptest.c b/clients/cliptest.c index 8c68e94f2..7627d8156 100644 --- a/clients/cliptest.c +++ b/clients/cliptest.c @@ -54,6 +54,7 @@ #include #include +#include "libweston/matrix.h" #include "libweston/vertex-clipping.h" #include "shared/helpers.h" #include "shared/xalloc.h" @@ -83,8 +84,8 @@ struct weston_view { }; static void -weston_view_from_global_double(struct weston_view *view, - double x, double y, double *sx, double *sy) +weston_view_from_global_float(struct weston_view *view, + float x, float y, float *sx, float *sy) { struct geometry *g = view->geometry; @@ -96,10 +97,10 @@ weston_view_from_global_double(struct weston_view *view, static struct weston_coord_surface weston_coord_global_to_surface(struct weston_view *view, struct weston_coord_global g_pos) { - double sx, sy; + float sx, sy; struct weston_coord_surface pos; - weston_view_from_global_double(view, g_pos.c.x, g_pos.c.y, &sx, &sy); + weston_view_from_global_float(view, g_pos.c.x, g_pos.c.y, &sx, &sy); pos.c = weston_coord(sx, sy); return pos; @@ -112,19 +113,22 @@ static void rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, struct gl_quad *quad) { - struct weston_coord_global tmp[4] = { + struct weston_coord_global rect_g[4] = { { .c = weston_coord(rect->x1, rect->y1) }, { .c = weston_coord(rect->x2, rect->y1) }, { .c = weston_coord(rect->x2, rect->y2) }, { .c = weston_coord(rect->x1, rect->y2) }, }; + struct weston_coord rect_s; int i; /* Transform rect to surface space. */ quad->vertices.n = 4; - for (i = 0; i < quad->vertices.n; i++) - quad->vertices.pos[i] = - weston_coord_global_to_surface(ev, tmp[i]).c; + for (i = 0; i < quad->vertices.n; i++) { + rect_s = weston_coord_global_to_surface(ev, rect_g[i]).c; + quad->vertices.pos[i].x = (float)rect_s.x; + quad->vertices.pos[i].y = (float)rect_s.y; + } /* Find axis-aligned bounding box. */ quad->bbox.x1 = quad->bbox.x2 = quad->vertices.pos[0].x; @@ -142,13 +146,13 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, /* * Compute the boundary vertices of the intersection of an arbitrary * quadrilateral 'quad' and the axis-aligned rectangle 'surf_rect'. The vertices - * are written to 'e', 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. + * 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. */ static int clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, - struct weston_coord *e) + struct clip_vertex *vertices) { struct clip_context ctx = { .clip.x1 = surf_rect->x1, @@ -170,7 +174,7 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, * rect bounds: */ if (quad->axis_aligned) - return clip_simple(&ctx, &quad->vertices, e); + return clip_simple(&ctx, &quad->vertices, vertices); /* Transformed case: use a general polygon clipping algorithm to * clip the quad with each side of the surface rect. @@ -178,7 +182,7 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm * but without looking at any of that code. */ - n = clip_transformed(&ctx, &quad->vertices, e); + n = clip_transformed(&ctx, &quad->vertices, vertices); if (n < 3) return 0; @@ -234,7 +238,7 @@ struct cliptest { }; static void -draw_polygon_closed(cairo_t *cr, struct weston_coord *pos, int n) +draw_polygon_closed(cairo_t *cr, struct clip_vertex *pos, int n) { int i; @@ -245,7 +249,7 @@ draw_polygon_closed(cairo_t *cr, struct weston_coord *pos, int n) } static void -draw_polygon_labels(cairo_t *cr, struct weston_coord *pos, int n) +draw_polygon_labels(cairo_t *cr, struct clip_vertex *pos, int n) { char str[16]; int i; @@ -258,7 +262,7 @@ draw_polygon_labels(cairo_t *cr, struct weston_coord *pos, int n) } static void -draw_coordinates(cairo_t *cr, double ox, double oy, struct weston_coord *pos, int n) +draw_coordinates(cairo_t *cr, double ox, double oy, struct clip_vertex *pos, int n) { char str[64]; int i; @@ -275,18 +279,18 @@ draw_coordinates(cairo_t *cr, double ox, double oy, struct weston_coord *pos, in static void draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view) { - struct weston_coord pos[4]; + struct clip_vertex pos[4]; if (view) { - weston_view_from_global_double(view, box->x1, box->y1, &pos[0].x, &pos[0].y); - weston_view_from_global_double(view, box->x2, box->y1, &pos[1].x, &pos[1].y); - weston_view_from_global_double(view, box->x2, box->y2, &pos[2].x, &pos[2].y); - weston_view_from_global_double(view, box->x1, box->y2, &pos[3].x, &pos[3].y); + weston_view_from_global_float(view, box->x1, box->y1, &pos[0].x, &pos[0].y); + weston_view_from_global_float(view, box->x2, box->y1, &pos[1].x, &pos[1].y); + weston_view_from_global_float(view, box->x2, box->y2, &pos[2].x, &pos[2].y); + weston_view_from_global_float(view, box->x1, box->y2, &pos[3].x, &pos[3].y); } else { - pos[0] = weston_coord(box->x1, box->y1); - pos[1] = weston_coord(box->x2, box->y1); - pos[2] = weston_coord(box->x2, box->y2); - pos[3] = weston_coord(box->x1, box->y2); + pos[0].x = box->x1; pos[0].y = box->y1; + pos[1].x = box->x2; pos[1].y = box->y1; + pos[2].x = box->x2; pos[2].y = box->y2; + pos[3].x = box->x1; pos[3].y = box->y2; } draw_polygon_closed(cr, pos, 4); @@ -294,15 +298,15 @@ draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view) static void draw_geometry(cairo_t *cr, struct weston_view *view, - struct weston_coord *e, int n) + struct clip_vertex *v, int n) { struct geometry *g = view->geometry; - double cx, cy; + float cx, cy; draw_box(cr, &g->quad, view); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4); cairo_fill(cr); - weston_view_from_global_double(view, g->quad.x1 - 4, g->quad.y1 - 4, &cx, &cy); + weston_view_from_global_float(view, g->quad.x1 - 4, g->quad.y1 - 4, &cx, &cy); cairo_arc(cr, cx, cy, 1.5, 0.0, 2.0 * M_PI); if (view->transform.enabled == 0) cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.8); @@ -313,12 +317,12 @@ draw_geometry(cairo_t *cr, struct weston_view *view, cairo_fill(cr); if (n) { - draw_polygon_closed(cr, e, n); + draw_polygon_closed(cr, v, n); cairo_set_source_rgb(cr, 0.0, 1.0, 0.0); cairo_stroke(cr); cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.5); - draw_polygon_labels(cr, e, n); + draw_polygon_labels(cr, v, n); } } @@ -331,11 +335,11 @@ redraw_handler(struct widget *widget, void *data) cairo_t *cr; cairo_surface_t *surface; struct gl_quad quad; - struct weston_coord e[8]; + struct clip_vertex v[8]; int n; rect_to_quad(&g->quad, &cliptest->view, &quad); - n = clip_quad(&quad, &g->surf, e); + n = clip_quad(&quad, &g->surf, v); widget_get_allocation(cliptest->widget, &allocation); @@ -369,7 +373,7 @@ redraw_handler(struct widget *widget, void *data) cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cr, 5.0); - draw_geometry(cr, &cliptest->view, e, n); + draw_geometry(cr, &cliptest->view, v, n); cairo_pop_group_to_source(cr); cairo_paint(cr); @@ -377,7 +381,7 @@ redraw_handler(struct widget *widget, void *data) cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 12.0); - draw_coordinates(cr, 10.0, 10.0, e, n); + draw_coordinates(cr, 10.0, 10.0, v, n); cairo_destroy(cr); @@ -596,7 +600,7 @@ benchmark(void) struct weston_view view; struct geometry geom; struct gl_quad quad; - struct weston_coord e[8]; + struct clip_vertex v[8]; int i; double t; const int N = 1000000; @@ -621,7 +625,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, e); + clip_quad(&quad, &geom.surf, v); } t = read_timer(); diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index bc3e9d487..c1c8a83b3 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -442,19 +442,22 @@ static void rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, struct gl_quad *quad) { - struct weston_coord_global tmp[4] = { + struct weston_coord_global rect_g[4] = { { .c = weston_coord(rect->x1, rect->y1) }, { .c = weston_coord(rect->x2, rect->y1) }, { .c = weston_coord(rect->x2, rect->y2) }, { .c = weston_coord(rect->x1, rect->y2) }, }; + struct weston_coord rect_s; int i; /* Transform rect to surface space. */ quad->vertices.n = 4; - for (i = 0; i < quad->vertices.n; i++) - quad->vertices.pos[i] = - weston_coord_global_to_surface(ev, tmp[i]).c; + for (i = 0; i < quad->vertices.n; i++) { + rect_s = weston_coord_global_to_surface(ev, rect_g[i]).c; + quad->vertices.pos[i].x = (float)rect_s.x; + quad->vertices.pos[i].y = (float)rect_s.y; + } /* Find axis-aligned bounding box. */ quad->bbox.x1 = quad->bbox.x2 = quad->vertices.pos[0].x; @@ -472,13 +475,13 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, /* * Compute the boundary vertices of the intersection of an arbitrary * quadrilateral 'quad' and the axis-aligned rectangle 'surf_rect'. The vertices - * are written to 'e', 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. + * 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. */ static int clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, - struct weston_coord *e) + struct clip_vertex *vertices) { struct clip_context ctx = { .clip.x1 = surf_rect->x1, @@ -500,7 +503,7 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, * rect bounds: */ if (quad->axis_aligned) - return clip_simple(&ctx, &quad->vertices, e); + return clip_simple(&ctx, &quad->vertices, vertices); /* Transformed case: use a general polygon clipping algorithm to * clip the quad with each side of the surface rect. @@ -508,7 +511,7 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm * but without looking at any of that code. */ - n = clip_transformed(&ctx, &quad->vertices, e); + n = clip_transformed(&ctx, &quad->vertices, vertices); if (n < 3) return 0; @@ -572,11 +575,11 @@ texture_region(struct weston_paint_node *pnode, struct weston_compositor *ec = pnode->surface->compositor; struct weston_view *ev = pnode->view; struct gl_renderer *gr = get_renderer(ec); - GLfloat *v; + struct clip_vertex *v; unsigned int *vtxcnt, nvtx = 0; pixman_box32_t *rects, *surf_rects; pixman_box32_t *raw_rects; - int i, j, k, nrects, nsurf, raw_nrects; + int i, j, nrects, nsurf, raw_nrects; bool used_band_compression; struct gl_quad quad; @@ -594,13 +597,12 @@ texture_region(struct weston_paint_node *pnode, /* worst case we can have 8 vertices per rect (ie. clipped into * an octagon): */ - v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 2 * sizeof *v); + v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * sizeof *v); vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt); for (i = 0; i < nrects; i++) { rect_to_quad(&rects[i], ev, &quad); for (j = 0; j < nsurf; j++) { - struct weston_coord e[8]; int n; /* The transformed quad, after clipping to the surface rect, can @@ -616,17 +618,11 @@ 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], e); - if (n < 3) - continue; - - /* emit edge points: */ - for (k = 0; k < n; k++) { - *(v++) = e[k].x; - *(v++) = e[k].y; + n = clip_quad(&quad, &surf_rects[j], v); + if (n >= 3) { + v += n; + vtxcnt[nvtx++] = n; } - - vtxcnt[nvtx++] = n; } } diff --git a/libweston/vertex-clipping.c b/libweston/vertex-clipping.c index c0c2f51ee..aed20a216 100644 --- a/libweston/vertex-clipping.c +++ b/libweston/vertex-clipping.c @@ -103,7 +103,8 @@ enum path_transition { static void clip_append_vertex(struct clip_context *ctx, float x, float y) { - *ctx->vertices = weston_coord(x, y); + ctx->vertices->x = x; + ctx->vertices->y = y; ctx->vertices++; } @@ -195,7 +196,7 @@ clip_polygon_topbottom(struct clip_context *ctx, static void clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src, - struct weston_coord *dst) + struct clip_vertex *dst) { ctx->prev.x = src->pos[src->n - 1].x; ctx->prev.y = src->pos[src->n - 1].y; @@ -204,7 +205,7 @@ clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src, static int clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src, - struct weston_coord *dst) + struct clip_vertex *dst) { enum path_transition trans; int i; @@ -223,7 +224,7 @@ clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src, static int clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src, - struct weston_coord *dst) + struct clip_vertex *dst) { enum path_transition trans; int i; @@ -242,7 +243,7 @@ clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src, static int clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src, - struct weston_coord *dst) + struct clip_vertex *dst) { enum path_transition trans; int i; @@ -261,7 +262,7 @@ clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src, static int clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src, - struct weston_coord *dst) + struct clip_vertex *dst) { enum path_transition trans; int i; @@ -281,12 +282,12 @@ clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src, WESTON_EXPORT_FOR_TESTS int clip_simple(struct clip_context *ctx, struct polygon8 *surf, - struct weston_coord *e) + struct clip_vertex *restrict vertices) { int i; for (i = 0; i < surf->n; i++) { - e[i].x = CLIP(surf->pos[i].x, ctx->clip.x1, ctx->clip.x2); - e[i].y = CLIP(surf->pos[i].y, ctx->clip.y1, ctx->clip.y2); + vertices[i].x = CLIP(surf->pos[i].x, ctx->clip.x1, ctx->clip.x2); + vertices[i].y = CLIP(surf->pos[i].y, ctx->clip.y1, ctx->clip.y2); } return surf->n; } @@ -294,7 +295,7 @@ clip_simple(struct clip_context *ctx, WESTON_EXPORT_FOR_TESTS int clip_transformed(struct clip_context *ctx, struct polygon8 *surf, - struct weston_coord *e) + struct clip_vertex *restrict vertices) { struct polygon8 polygon; int i, n; @@ -305,17 +306,17 @@ clip_transformed(struct clip_context *ctx, surf->n = clip_polygon_bottom(ctx, &polygon, surf->pos); /* Get rid of duplicate vertices */ - e[0] = surf->pos[0]; + vertices[0] = surf->pos[0]; n = 1; for (i = 1; i < surf->n; i++) { - if (float_difference(e[n - 1].x, surf->pos[i].x) == 0.0f && - float_difference(e[n - 1].y, surf->pos[i].y) == 0.0f) + if (float_difference(vertices[n - 1].x, surf->pos[i].x) == 0.0f && + float_difference(vertices[n - 1].y, surf->pos[i].y) == 0.0f) continue; - e[n] = surf->pos[i]; + vertices[n] = surf->pos[i]; n++; } - if (float_difference(e[n - 1].x, surf->pos[0].x) == 0.0f && - float_difference(e[n - 1].y, surf->pos[0].y) == 0.0f) + if (float_difference(vertices[n - 1].x, surf->pos[0].x) == 0.0f && + float_difference(vertices[n - 1].y, surf->pos[0].y) == 0.0f) n--; return n; diff --git a/libweston/vertex-clipping.h b/libweston/vertex-clipping.h index 9ffb4d4f4..d4bbba508 100644 --- a/libweston/vertex-clipping.h +++ b/libweston/vertex-clipping.h @@ -25,10 +25,14 @@ #ifndef _WESTON_VERTEX_CLIPPING_H #define _WESTON_VERTEX_CLIPPING_H -#include +#include + +struct clip_vertex { + float x, y; +}; struct polygon8 { - struct weston_coord pos[8]; + struct clip_vertex pos[8]; int n; }; @@ -39,17 +43,14 @@ struct gl_quad { }; struct clip_context { - struct { - float x; - float y; - } prev; + struct clip_vertex prev; struct { float x1, y1; float x2, y2; } clip; - struct weston_coord *vertices; + struct clip_vertex *vertices; }; float @@ -58,11 +59,11 @@ float_difference(float a, float b); int clip_simple(struct clip_context *ctx, struct polygon8 *surf, - struct weston_coord *e); + struct clip_vertex *restrict vertices); int clip_transformed(struct clip_context *ctx, struct polygon8 *surf, - struct weston_coord *e); + struct clip_vertex *restrict vertices); #endif diff --git a/tests/vertex-clip-test.c b/tests/vertex-clip-test.c index 8cde2702a..8b3a13c60 100644 --- a/tests/vertex-clip-test.c +++ b/tests/vertex-clip-test.c @@ -60,7 +60,7 @@ populate_clip_context (struct clip_context *ctx) static int clip_polygon (struct clip_context *ctx, struct polygon8 *polygon, - struct weston_coord *pos) + struct clip_vertex *pos) { populate_clip_context(ctx); return clip_transformed(ctx, polygon, pos); @@ -241,7 +241,7 @@ TEST_P(clip_polygon_n_vertices_emitted, test_data) struct vertex_clip_test_data *tdata = data; struct clip_context ctx; struct polygon8 polygon; - struct weston_coord vertices[8]; + struct clip_vertex vertices[8]; deep_copy_polygon8(&tdata->surface, &polygon); int emitted = clip_polygon(&ctx, &polygon, vertices); @@ -253,7 +253,7 @@ TEST_P(clip_polygon_expected_vertices, test_data) struct vertex_clip_test_data *tdata = data; struct clip_context ctx; struct polygon8 polygon; - struct weston_coord vertices[8]; + struct clip_vertex vertices[8]; deep_copy_polygon8(&tdata->surface, &polygon); int emitted = clip_polygon(&ctx, &polygon, vertices); int i = 0;