From b8063dbb13f73bf39c9d4cde528e8436e849837f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Thu, 25 May 2023 10:50:42 +0200 Subject: [PATCH] gl-renderer: Remove polygon8 struct from clipper API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass a clip_vertex struct and a size to clip_transformed() instead of a polygon8 struct to simplify the clipper API by sticking to a common vertex representation. Simmplify vertex-clip test since clip_transformed() now works on a copy of the polygon (commit edd5d1cc0912ce4f8d29eaef96ebf5a79b9a7b67). Signed-off-by: Loïc Molinari --- clients/cliptest.c | 25 +-- libweston/renderer-gl/gl-renderer.c | 25 +-- libweston/vertex-clipping.c | 22 +- libweston/vertex-clipping.h | 11 +- tests/vertex-clip-test.c | 309 +++++++++++++--------------- 5 files changed, 182 insertions(+), 210 deletions(-) diff --git a/clients/cliptest.c b/clients/cliptest.c index 9923a9119..0ef8791e8 100644 --- a/clients/cliptest.c +++ b/clients/cliptest.c @@ -124,11 +124,10 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, int i; /* Transform rect to surface space. */ - quad->vertices.n = 4; - for (i = 0; i < quad->vertices.n; i++) { + for (i = 0; i < 4; 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; + quad->polygon[i].x = (float)rect_s.x; + quad->polygon[i].y = (float)rect_s.y; } quad->axis_aligned = !ev->transform.enabled || @@ -136,17 +135,13 @@ 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->vertices.pos[0].x; - quad->bbox.y1 = quad->bbox.y2 = quad->vertices.pos[0].y; - for (i = 1; i < quad->vertices.n; i++) { - quad->bbox.x1 = MIN(quad->bbox.x1, - quad->vertices.pos[i].x); - quad->bbox.x2 = MAX(quad->bbox.x2, - quad->vertices.pos[i].x); - quad->bbox.y1 = MIN(quad->bbox.y1, - quad->vertices.pos[i].y); - quad->bbox.y2 = MAX(quad->bbox.y2, - quad->vertices.pos[i].y); + quad->bbox.x1 = quad->bbox.x2 = quad->polygon[0].x; + quad->bbox.y1 = quad->bbox.y2 = 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); } } } diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 964a15a78..2ee131d0a 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -485,11 +485,10 @@ rect_to_quad(pixman_box32_t *rect, struct weston_view *ev, int i; /* Transform rect to surface space. */ - quad->vertices.n = 4; - for (i = 0; i < quad->vertices.n; i++) { + for (i = 0; i < 4; 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; + quad->polygon[i].x = (float)rect_s.x; + quad->polygon[i].y = (float)rect_s.y; } quad->axis_aligned = !ev->transform.enabled || @@ -497,17 +496,13 @@ 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->vertices.pos[0].x; - quad->bbox.y1 = quad->bbox.y2 = quad->vertices.pos[0].y; - for (i = 1; i < quad->vertices.n; i++) { - quad->bbox.x1 = MIN(quad->bbox.x1, - quad->vertices.pos[i].x); - quad->bbox.x2 = MAX(quad->bbox.x2, - quad->vertices.pos[i].x); - quad->bbox.y1 = MIN(quad->bbox.y1, - quad->vertices.pos[i].y); - quad->bbox.y2 = MAX(quad->bbox.y2, - quad->vertices.pos[i].y); + quad->bbox.x1 = quad->bbox.x2 = quad->polygon[0].x; + quad->bbox.y1 = quad->bbox.y2 = 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); } } } diff --git a/libweston/vertex-clipping.c b/libweston/vertex-clipping.c index fac81b518..749a50f6d 100644 --- a/libweston/vertex-clipping.c +++ b/libweston/vertex-clipping.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "shared/helpers.h" #include "vertex-clipping.h" @@ -194,6 +195,11 @@ clip_polygon_topbottom(struct clip_context *ctx, ctx->prev.y = y; } +struct polygon8 { + struct clip_vertex pos[8]; + int n; +}; + static void clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src, struct clip_vertex *dst) @@ -281,12 +287,18 @@ clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src, WESTON_EXPORT_FOR_TESTS int clip_transformed(struct clip_context *ctx, - const struct polygon8 *surf, + const struct clip_vertex *polygon, + size_t polygon_len, struct clip_vertex *restrict vertices) { - struct polygon8 p = *surf, tmp; + struct polygon8 p, tmp; int i, n; + if (polygon_len > 8) + return -1; + + memcpy(p.pos, polygon, polygon_len * sizeof *polygon); + p.n = polygon_len; tmp.n = clip_polygon_left(ctx, &p, tmp.pos); p.n = clip_polygon_right(ctx, &tmp, p.pos); tmp.n = clip_polygon_top(ctx, &p, tmp.pos); @@ -327,9 +339,9 @@ clip_quad(struct gl_quad *quad, pixman_box32_t *surf_rect, */ if (quad->axis_aligned) { for (i = 0; i < 4; i++) { - vertices[i].x = CLIP(quad->vertices.pos[i].x, + vertices[i].x = CLIP(quad->polygon[i].x, ctx.clip.x1, ctx.clip.x2); - vertices[i].y = CLIP(quad->vertices.pos[i].y, + vertices[i].y = CLIP(quad->polygon[i].y, ctx.clip.y1, ctx.clip.y2); } if ((vertices[0].x != vertices[1].x) && @@ -352,7 +364,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. */ - n = clip_transformed(&ctx, &quad->vertices, vertices); + n = clip_transformed(&ctx, quad->polygon, 4, vertices); if (n < 3) return 0; diff --git a/libweston/vertex-clipping.h b/libweston/vertex-clipping.h index 666d952ce..39b4f32df 100644 --- a/libweston/vertex-clipping.h +++ b/libweston/vertex-clipping.h @@ -25,6 +25,7 @@ #ifndef _WESTON_VERTEX_CLIPPING_H #define _WESTON_VERTEX_CLIPPING_H +#include #include #include @@ -32,13 +33,8 @@ struct clip_vertex { float x, y; }; -struct polygon8 { - struct clip_vertex pos[8]; - int n; -}; - struct gl_quad { - struct polygon8 vertices; + struct clip_vertex polygon[4]; struct { float x1, y1, x2, y2; } bbox; /* Valid if !axis_aligned. */ bool axis_aligned; }; @@ -59,7 +55,8 @@ float_difference(float a, float b); int clip_transformed(struct clip_context *ctx, - const struct polygon8 *surf, + const struct clip_vertex *polygon, + size_t polygon_len, struct clip_vertex *restrict vertices); /* diff --git a/tests/vertex-clip-test.c b/tests/vertex-clip-test.c index 8b3a13c60..3e0ae1ec2 100644 --- a/tests/vertex-clip-test.c +++ b/tests/vertex-clip-test.c @@ -25,12 +25,7 @@ #include "config.h" -#include -#include - #include "weston-test-runner.h" - -#include "shared/helpers.h" #include "vertex-clipping.h" #define BOUNDING_BOX_TOP_Y 100.0f @@ -59,212 +54,190 @@ populate_clip_context (struct clip_context *ctx) static int clip_polygon (struct clip_context *ctx, - struct polygon8 *polygon, - struct clip_vertex *pos) + struct clip_vertex *polygon, + int n, + struct clip_vertex *vertices) { populate_clip_context(ctx); - return clip_transformed(ctx, polygon, pos); + return clip_transformed(ctx, polygon, n, vertices); } -struct vertex_clip_test_data -{ - struct polygon8 surface; - struct polygon8 expected; +struct vertex_clip_test_data { + struct clip_vertex polygon[8]; + struct clip_vertex clipped[8]; + int polygon_n; + int clipped_n; }; -const struct vertex_clip_test_data test_data[] = -{ +const struct vertex_clip_test_data test_data[] = { /* All inside */ { - { - .pos = { - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 + .polygon = { + { INSIDE_X1, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, }, - { - .pos = { - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 - } + .clipped = { + { INSIDE_X1, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, + }, + .polygon_n = 4, + .clipped_n = 4, }, + /* Top outside */ { - { - .pos = { - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = OUTSIDE_Y2 }, - { .x = INSIDE_X1, .y = OUTSIDE_Y2 }, - }, - .n = 4 + .polygon = { + { INSIDE_X1, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, OUTSIDE_Y2 }, + { INSIDE_X1, OUTSIDE_Y2 }, }, - { - .pos = { - { .x = INSIDE_X1, .y = BOUNDING_BOX_TOP_Y }, - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = BOUNDING_BOX_TOP_Y }, - }, - .n = 4 - } + .clipped = { + { INSIDE_X1, BOUNDING_BOX_TOP_Y }, + { INSIDE_X1, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, BOUNDING_BOX_TOP_Y }, + }, + .polygon_n = 4, + .clipped_n = 4, }, + /* Bottom outside */ { - { - .pos = { - { .x = INSIDE_X1, .y = OUTSIDE_Y1 }, - { .x = INSIDE_X2, .y = OUTSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 + .polygon = { + { INSIDE_X1, OUTSIDE_Y1 }, + { INSIDE_X2, OUTSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, }, - { - .pos = { - { .x = INSIDE_X1, .y = BOUNDING_BOX_BOTTOM_Y }, - { .x = INSIDE_X2, .y = BOUNDING_BOX_BOTTOM_Y }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 - } + .clipped = { + { INSIDE_X1, BOUNDING_BOX_BOTTOM_Y }, + { INSIDE_X2, BOUNDING_BOX_BOTTOM_Y }, + { INSIDE_X2, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, + }, + .polygon_n = 4, + .clipped_n = 4, }, + /* Left outside */ { - { - .pos = { - { .x = OUTSIDE_X1, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = OUTSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 + .polygon = { + { OUTSIDE_X1, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y2 }, + { OUTSIDE_X1, INSIDE_Y2 }, }, - { - .pos = { - { .x = BOUNDING_BOX_LEFT_X, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y1 }, - { .x = INSIDE_X2, .y = INSIDE_Y2 }, - { .x = BOUNDING_BOX_LEFT_X, .y = INSIDE_Y2 }, - }, - .n = 4 - } + .clipped = { + { BOUNDING_BOX_LEFT_X, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y1 }, + { INSIDE_X2, INSIDE_Y2 }, + { BOUNDING_BOX_LEFT_X, INSIDE_Y2 }, + }, + .polygon_n = 4, + .clipped_n = 4, }, + /* Right outside */ { - { - .pos = { - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = OUTSIDE_X2, .y = INSIDE_Y1 }, - { .x = OUTSIDE_X2, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 + .polygon = { + { INSIDE_X1, INSIDE_Y1 }, + { OUTSIDE_X2, INSIDE_Y1 }, + { OUTSIDE_X2, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, }, - { - .pos = { - { .x = INSIDE_X1, .y = INSIDE_Y1 }, - { .x = BOUNDING_BOX_RIGHT_X, .y = INSIDE_Y1 }, - { .x = BOUNDING_BOX_RIGHT_X, .y = INSIDE_Y2 }, - { .x = INSIDE_X1, .y = INSIDE_Y2 }, - }, - .n = 4 - } + .clipped = { + { INSIDE_X1, INSIDE_Y1 }, + { BOUNDING_BOX_RIGHT_X, INSIDE_Y1 }, + { BOUNDING_BOX_RIGHT_X, INSIDE_Y2 }, + { INSIDE_X1, INSIDE_Y2 }, + }, + .polygon_n = 4, + .clipped_n = 4, }, - /* Diamond extending from bounding box edges, clip to bounding box */ - { - { - .pos = { - { .x = BOUNDING_BOX_LEFT_X - 25, .y = BOUNDING_BOX_BOTTOM_Y + 25 }, - { .x = BOUNDING_BOX_LEFT_X + 25, .y = BOUNDING_BOX_TOP_Y + 25 }, - { .x = BOUNDING_BOX_RIGHT_X + 25, .y = BOUNDING_BOX_TOP_Y - 25 }, - { .x = BOUNDING_BOX_RIGHT_X - 25, .y = BOUNDING_BOX_BOTTOM_Y - 25 }, - }, - .n = 4 - }, - { - .pos = { - { .x = BOUNDING_BOX_LEFT_X, .y = BOUNDING_BOX_BOTTOM_Y }, - { .x = BOUNDING_BOX_LEFT_X, .y = BOUNDING_BOX_TOP_Y }, - { .x = BOUNDING_BOX_RIGHT_X, .y = BOUNDING_BOX_TOP_Y }, - { .x = BOUNDING_BOX_RIGHT_X, .y = BOUNDING_BOX_BOTTOM_Y }, - }, - .n = 4 - } - }, - /* Diamond inside of bounding box edges, clip t bounding box, 8 resulting vertices */ - { - { - .pos = { - { .x = BOUNDING_BOX_LEFT_X - 12.5, .y = BOUNDING_BOX_BOTTOM_Y + 25 }, - { .x = BOUNDING_BOX_LEFT_X + 25, .y = BOUNDING_BOX_TOP_Y + 12.5 }, - { .x = BOUNDING_BOX_RIGHT_X + 12.5, .y = BOUNDING_BOX_TOP_Y - 25 }, - { .x = BOUNDING_BOX_RIGHT_X - 25, .y = BOUNDING_BOX_BOTTOM_Y - 12.5 }, - }, - .n = 4 - }, - { - .pos = { - { .x = BOUNDING_BOX_LEFT_X + 12.5, .y = BOUNDING_BOX_BOTTOM_Y }, - { .x = BOUNDING_BOX_LEFT_X, .y = BOUNDING_BOX_BOTTOM_Y + 12.5 }, - { .x = BOUNDING_BOX_LEFT_X, .y = BOUNDING_BOX_TOP_Y - 12.5 }, - { .x = BOUNDING_BOX_LEFT_X + 12.5, .y = BOUNDING_BOX_TOP_Y }, - { .x = BOUNDING_BOX_RIGHT_X - 12.5, .y = BOUNDING_BOX_TOP_Y }, - { .x = BOUNDING_BOX_RIGHT_X, .y = BOUNDING_BOX_TOP_Y - 12.5 }, - { .x = BOUNDING_BOX_RIGHT_X, .y = BOUNDING_BOX_BOTTOM_Y + 12.5}, - { .x = BOUNDING_BOX_RIGHT_X - 12.5, .y = BOUNDING_BOX_BOTTOM_Y }, - }, - .n = 8 - } - } -}; -/* clip_polygon modifies the source operand and the test data must - * be const, so we need to deep copy it */ -static void -deep_copy_polygon8(const struct polygon8 *src, struct polygon8 *dst) -{ - dst->n = src->n; - ARRAY_COPY(dst->pos, src->pos); -} + /* Diamond extending from bounding box edges */ + { + .polygon = { + { BOUNDING_BOX_LEFT_X - 25, BOUNDING_BOX_BOTTOM_Y + 25 }, + { BOUNDING_BOX_LEFT_X + 25, BOUNDING_BOX_TOP_Y + 25 }, + { BOUNDING_BOX_RIGHT_X + 25, BOUNDING_BOX_TOP_Y - 25 }, + { BOUNDING_BOX_RIGHT_X - 25, BOUNDING_BOX_BOTTOM_Y - 25 }, + }, + .clipped = { + { BOUNDING_BOX_LEFT_X, BOUNDING_BOX_BOTTOM_Y }, + { BOUNDING_BOX_LEFT_X, BOUNDING_BOX_TOP_Y }, + { BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_TOP_Y }, + { BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_BOTTOM_Y }, + }, + .polygon_n = 4, + .clipped_n = 4, + }, + + /* Diamond inside of bounding box edges */ + { + .polygon = { + { BOUNDING_BOX_LEFT_X - 12.5, BOUNDING_BOX_BOTTOM_Y + 25 }, + { BOUNDING_BOX_LEFT_X + 25, BOUNDING_BOX_TOP_Y + 12.5 }, + { BOUNDING_BOX_RIGHT_X + 12.5, BOUNDING_BOX_TOP_Y - 25 }, + { BOUNDING_BOX_RIGHT_X - 25, BOUNDING_BOX_BOTTOM_Y - 12.5 }, + }, + .clipped = { + { BOUNDING_BOX_LEFT_X + 12.5, BOUNDING_BOX_BOTTOM_Y }, + { BOUNDING_BOX_LEFT_X, BOUNDING_BOX_BOTTOM_Y + 12.5 }, + { BOUNDING_BOX_LEFT_X, BOUNDING_BOX_TOP_Y - 12.5 }, + { BOUNDING_BOX_LEFT_X + 12.5, BOUNDING_BOX_TOP_Y }, + { BOUNDING_BOX_RIGHT_X - 12.5, BOUNDING_BOX_TOP_Y }, + { BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_TOP_Y - 12.5 }, + { BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_BOTTOM_Y + 12.5 }, + { BOUNDING_BOX_RIGHT_X - 12.5, BOUNDING_BOX_BOTTOM_Y }, + }, + .polygon_n = 4, + .clipped_n = 8, + }, +}; TEST_P(clip_polygon_n_vertices_emitted, test_data) { struct vertex_clip_test_data *tdata = data; struct clip_context ctx; - struct polygon8 polygon; - struct clip_vertex vertices[8]; - deep_copy_polygon8(&tdata->surface, &polygon); - int emitted = clip_polygon(&ctx, &polygon, vertices); + struct clip_vertex clipped[8]; + int clipped_n; - assert(emitted == tdata->expected.n); + clipped_n = clip_polygon(&ctx, tdata->polygon, tdata->polygon_n, + clipped); + + assert(clipped_n == tdata->clipped_n); } TEST_P(clip_polygon_expected_vertices, test_data) { struct vertex_clip_test_data *tdata = data; struct clip_context ctx; - struct polygon8 polygon; - struct clip_vertex vertices[8]; - deep_copy_polygon8(&tdata->surface, &polygon); - int emitted = clip_polygon(&ctx, &polygon, vertices); - int i = 0; + struct clip_vertex clipped[8]; + int clipped_n, i; - for (; i < emitted; ++i) - { - assert(vertices[i].x == tdata->expected.pos[i].x); - assert(vertices[i].y == tdata->expected.pos[i].y); + clipped_n = clip_polygon(&ctx, tdata->polygon, tdata->polygon_n, + clipped); + + for (i = 0; i < clipped_n; i++) { + assert(clipped[i].x == tdata->clipped[i].x); + assert(clipped[i].y == tdata->clipped[i].y); } } +TEST(clip_transformed_size_too_high) +{ + struct clip_context ctx; + struct clip_vertex polygon[8] = {}; + + assert(clip_transformed(&ctx, polygon, 9, NULL) == -1); +} + TEST(float_difference_different) { assert(float_difference(1.0f, 0.0f) == 1.0f);