clipping: Use struct weston_coord in vertex clipping code

Remove the independent x, y floats from the clipping code and replace them
with struct weston_cord. This includes the polygon8 structure as well.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2022-02-09 11:17:42 -06:00 committed by Pekka Paalanen
parent f7609553a9
commit 10e70bf23c
6 changed files with 265 additions and 199 deletions

View File

@ -51,6 +51,7 @@
#include <wayland-client.h>
#include "libweston/vertex-clipping.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "window.h"
@ -65,7 +66,11 @@ struct geometry {
float phi;
};
struct weston_surface {
};
struct weston_view {
struct weston_surface *surface;
struct {
int enabled;
} transform;
@ -74,8 +79,8 @@ struct weston_view {
};
static void
weston_view_to_global_float(struct weston_view *view,
float sx, float sy, float *x, float *y)
weston_view_to_global_double(struct weston_view *view,
double sx, double sy, double *x, double *y)
{
struct geometry *g = view->geometry;
@ -84,12 +89,21 @@ weston_view_to_global_float(struct weston_view *view,
*y = -g->s * sx + g->c * sy;
}
static struct weston_coord_global
weston_coord_surface_to_global(struct weston_view *view, struct weston_coord_surface pos)
{
double gx, gy;
struct weston_coord_global g_pos;
weston_view_to_global_double(view, pos.c.x, pos.c.y, &gx, &gy);
g_pos.c = weston_coord(gx, gy);
return g_pos;
}
/* ---------------------- copied begins -----------------------*/
/* Keep this in sync with what is in gl-renderer.c! */
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) > (b)) ? (b) : (a))
/*
* Compute the boundary vertices of the intersection of the global coordinate
* aligned rectangle 'rect', and an arbitrary quadrilateral produced from
@ -101,17 +115,22 @@ weston_view_to_global_float(struct weston_view *view,
*/
static int
calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
pixman_box32_t *surf_rect, struct weston_coord *e)
{
struct clip_context ctx;
int i, n;
GLfloat min_x, max_x, min_y, max_y;
struct polygon8 surf = {
{ surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
{ surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
4
struct weston_surface *es = ev->surface;
struct weston_coord_surface tmp[4] = {
weston_coord_surface(surf_rect->x1, surf_rect->y1, es),
weston_coord_surface(surf_rect->x2, surf_rect->y1, es),
weston_coord_surface(surf_rect->x2, surf_rect->y2, es),
weston_coord_surface(surf_rect->x1, surf_rect->y2, es),
};
struct polygon8 surf;
surf.n = 4;
ctx.clip.x1 = rect->x1;
ctx.clip.y1 = rect->y1;
@ -120,18 +139,17 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
/* transform surface to screen space: */
for (i = 0; i < surf.n; i++)
weston_view_to_global_float(ev, surf.x[i], surf.y[i],
&surf.x[i], &surf.y[i]);
surf.pos[i] = weston_coord_surface_to_global(ev, tmp[i]).c;
/* find bounding box: */
min_x = max_x = surf.x[0];
min_y = max_y = surf.y[0];
min_x = max_x = surf.pos[0].x;
min_y = max_y = surf.pos[0].y;
for (i = 1; i < surf.n; i++) {
min_x = min(min_x, surf.x[i]);
max_x = max(max_x, surf.x[i]);
min_y = min(min_y, surf.y[i]);
max_y = max(max_y, surf.y[i]);
min_x = MIN(min_x, surf.pos[i].x);
max_x = MAX(max_x, surf.pos[i].x);
min_y = MIN(min_y, surf.pos[i].y);
max_y = MAX(max_y, surf.pos[i].y);
}
/* First, simple bounding box check to discard early transformed
@ -146,7 +164,7 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
* vertices to the clip rect bounds:
*/
if (!ev->transform.enabled)
return clip_simple(&ctx, &surf, ex, ey);
return clip_simple(&ctx, &surf, e);
/* Transformed case: use a general polygon clipping algorithm to
* clip the surface rectangle with each side of 'rect'.
@ -154,7 +172,7 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *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, &surf, ex, ey);
n = clip_transformed(&ctx, &surf, e);
if (n < 3)
return 0;
@ -162,7 +180,6 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
return n;
}
/* ---------------------- copied ends -----------------------*/
static void
@ -206,35 +223,36 @@ struct cliptest {
struct ui_state ui;
struct geometry geometry;
struct weston_surface surface;
struct weston_view view;
};
static void
draw_polygon_closed(cairo_t *cr, GLfloat *x, GLfloat *y, int n)
draw_polygon_closed(cairo_t *cr, struct weston_coord *pos, int n)
{
int i;
cairo_move_to(cr, x[0], y[0]);
cairo_move_to(cr, pos[0].x, pos[0].y);
for (i = 1; i < n; i++)
cairo_line_to(cr, x[i], y[i]);
cairo_line_to(cr, x[0], y[0]);
cairo_line_to(cr, pos[i].x, pos[i].y);
cairo_line_to(cr, pos[0].x, pos[0].y);
}
static void
draw_polygon_labels(cairo_t *cr, GLfloat *x, GLfloat *y, int n)
draw_polygon_labels(cairo_t *cr, struct weston_coord *pos, int n)
{
char str[16];
int i;
for (i = 0; i < n; i++) {
snprintf(str, 16, "%d", i);
cairo_move_to(cr, x[i], y[i]);
cairo_move_to(cr, pos[i].x, pos[i].y);
cairo_show_text(cr, str);
}
}
static void
draw_coordinates(cairo_t *cr, double ox, double oy, GLfloat *x, GLfloat *y, int n)
draw_coordinates(cairo_t *cr, double ox, double oy, struct weston_coord *pos, int n)
{
char str[64];
int i;
@ -242,7 +260,7 @@ draw_coordinates(cairo_t *cr, double ox, double oy, GLfloat *x, GLfloat *y, int
cairo_font_extents(cr, &ext);
for (i = 0; i < n; i++) {
snprintf(str, 64, "%d: %14.9f, %14.9f", i, x[i], y[i]);
snprintf(str, 64, "%d: %14.9f, %14.9f", i, pos[i].x, pos[i].y);
cairo_move_to(cr, ox, oy + ext.height * (i + 1));
cairo_show_text(cr, str);
}
@ -251,34 +269,34 @@ draw_coordinates(cairo_t *cr, double ox, double oy, GLfloat *x, GLfloat *y, int
static void
draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view)
{
GLfloat x[4], y[4];
struct weston_coord pos[4];
if (view) {
weston_view_to_global_float(view, box->x1, box->y1, &x[0], &y[0]);
weston_view_to_global_float(view, box->x2, box->y1, &x[1], &y[1]);
weston_view_to_global_float(view, box->x2, box->y2, &x[2], &y[2]);
weston_view_to_global_float(view, box->x1, box->y2, &x[3], &y[3]);
weston_view_to_global_double(view, box->x1, box->y1, &pos[0].x, &pos[0].y);
weston_view_to_global_double(view, box->x2, box->y1, &pos[1].x, &pos[1].y);
weston_view_to_global_double(view, box->x2, box->y2, &pos[2].x, &pos[2].y);
weston_view_to_global_double(view, box->x1, box->y2, &pos[3].x, &pos[3].y);
} else {
x[0] = box->x1; y[0] = box->y1;
x[1] = box->x2; y[1] = box->y1;
x[2] = box->x2; y[2] = box->y2;
x[3] = box->x1; y[3] = box->y2;
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);
}
draw_polygon_closed(cr, x, y, 4);
draw_polygon_closed(cr, pos, 4);
}
static void
draw_geometry(cairo_t *cr, struct weston_view *view,
GLfloat *ex, GLfloat *ey, int n)
struct weston_coord *e, int n)
{
struct geometry *g = view->geometry;
float cx, cy;
double cx, cy;
draw_box(cr, &g->surf, view);
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4);
cairo_fill(cr);
weston_view_to_global_float(view, g->surf.x1 - 4, g->surf.y1 - 4, &cx, &cy);
weston_view_to_global_double(view, g->surf.x1 - 4, g->surf.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);
@ -289,12 +307,12 @@ draw_geometry(cairo_t *cr, struct weston_view *view,
cairo_fill(cr);
if (n) {
draw_polygon_closed(cr, ex, ey, n);
draw_polygon_closed(cr, e, 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, ex, ey, n);
draw_polygon_labels(cr, e, n);
}
}
@ -306,11 +324,10 @@ redraw_handler(struct widget *widget, void *data)
struct rectangle allocation;
cairo_t *cr;
cairo_surface_t *surface;
GLfloat ex[8];
GLfloat ey[8];
struct weston_coord e[8];
int n;
n = calculate_edges(&cliptest->view, &g->clip, &g->surf, ex, ey);
n = calculate_edges(&cliptest->view, &g->clip, &g->surf, e);
widget_get_allocation(cliptest->widget, &allocation);
@ -344,7 +361,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, ex, ey, n);
draw_geometry(cr, &cliptest->view, e, n);
cairo_pop_group_to_source(cr);
cairo_paint(cr);
@ -352,7 +369,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, ex, ey, n);
draw_coordinates(cr, 10.0, 10.0, e, n);
cairo_destroy(cr);
@ -514,6 +531,7 @@ cliptest_create(struct display *display)
struct cliptest *cliptest;
cliptest = xzalloc(sizeof *cliptest);
cliptest->view.surface = &cliptest->surface;
cliptest->view.geometry = &cliptest->geometry;
cliptest->view.transform.enabled = 0;
geometry_init(&cliptest->geometry);
@ -566,9 +584,10 @@ read_timer(void)
static int
benchmark(void)
{
struct weston_surface surface;
struct weston_view view;
struct geometry geom;
GLfloat ex[8], ey[8];
struct weston_coord e[8];
int i;
double t;
const int N = 1000000;
@ -585,13 +604,14 @@ benchmark(void)
geometry_set_phi(&geom, 0.0);
view.surface = &surface;
view.transform.enabled = 1;
view.geometry = &geom;
reset_timer();
for (i = 0; i < N; i++) {
geometry_set_phi(&geom, (float)i / 360.0f);
calculate_edges(&view, &geom.clip, &geom.surf, ex, ey);
calculate_edges(&view, &geom.clip, &geom.surf, e);
}
t = read_timer();

View File

@ -264,7 +264,7 @@ demo_clients = [
{ 'basename': 'clickdot' },
{
'basename': 'cliptest',
'dep_objs': dep_vertex_clipping
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
},
{ 'basename': 'confine' },
{

View File

@ -411,17 +411,22 @@ timeline_submit_render_sync(struct gl_renderer *gr,
*/
static int
calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
pixman_box32_t *surf_rect, struct weston_coord *e)
{
struct clip_context ctx;
int i, n;
GLfloat min_x, max_x, min_y, max_y;
struct polygon8 surf = {
{ surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
{ surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
4
struct weston_surface *es = ev->surface;
struct weston_coord_surface tmp[4] = {
weston_coord_surface(surf_rect->x1, surf_rect->y1, es),
weston_coord_surface(surf_rect->x2, surf_rect->y1, es),
weston_coord_surface(surf_rect->x2, surf_rect->y2, es),
weston_coord_surface(surf_rect->x1, surf_rect->y2, es),
};
struct polygon8 surf;
surf.n = 4;
ctx.clip.x1 = rect->x1;
ctx.clip.y1 = rect->y1;
@ -429,25 +434,18 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
ctx.clip.y2 = rect->y2;
/* transform surface to screen space: */
for (i = 0; i < surf.n; i++) {
struct weston_coord_global cg;
struct weston_coord_surface cs;
cs = weston_coord_surface(surf.x[i], surf.y[i], ev->surface);
cg = weston_coord_surface_to_global(ev, cs);
surf.x[i] = cg.c.x;
surf.y[i] = cg.c.y;
}
for (i = 0; i < surf.n; i++)
surf.pos[i] = weston_coord_surface_to_global(ev, tmp[i]).c;
/* find bounding box: */
min_x = max_x = surf.x[0];
min_y = max_y = surf.y[0];
min_x = max_x = surf.pos[0].x;
min_y = max_y = surf.pos[0].y;
for (i = 1; i < surf.n; i++) {
min_x = MIN(min_x, surf.x[i]);
max_x = MAX(max_x, surf.x[i]);
min_y = MIN(min_y, surf.y[i]);
max_y = MAX(max_y, surf.y[i]);
min_x = MIN(min_x, surf.pos[i].x);
max_x = MAX(max_x, surf.pos[i].x);
min_y = MIN(min_y, surf.pos[i].y);
max_y = MAX(max_y, surf.pos[i].y);
}
/* First, simple bounding box check to discard early transformed
@ -462,7 +460,7 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
* vertices to the clip rect bounds:
*/
if (!ev->transform.enabled)
return clip_simple(&ctx, &surf, ex, ey);
return clip_simple(&ctx, &surf, e);
/* Transformed case: use a general polygon clipping algorithm to
* clip the surface rectangle with each side of 'rect'.
@ -470,7 +468,7 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *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, &surf, ex, ey);
n = clip_transformed(&ctx, &surf, e);
if (n < 3)
return 0;
@ -566,7 +564,7 @@ texture_region(struct weston_paint_node *pnode,
pixman_box32_t *rect = &rects[i];
for (j = 0; j < nsurf; j++) {
pixman_box32_t *surf_rect = &surf_rects[j];
GLfloat ex[8], ey[8]; /* edge points in screen space */
struct weston_coord e[8]; /* edge points in screen space */
int n;
/* The transformed surface, after clipping to the clip region,
@ -583,28 +581,31 @@ texture_region(struct weston_paint_node *pnode,
* form the intersection of the clip rect and the transformed
* surface.
*/
n = calculate_edges(ev, rect, surf_rect, ex, ey);
n = calculate_edges(ev, rect, surf_rect, e);
if (n < 3)
continue;
/* emit edge points: */
for (k = 0; k < n; k++) {
struct weston_coord_global cg;
struct weston_coord_surface cs;
struct weston_coord_buffer cb;
struct weston_coord_global pos_g;
struct weston_coord_surface pos_s;
struct weston_coord_buffer pos_b;
pos_g.c = e[k];
cg.c = weston_coord(ex[k], ey[k]);
cs = weston_coord_global_to_surface(ev, cg);
/* position: */
*(v++) = ex[k];
*(v++) = ey[k];
*(v++) = pos_g.c.x;
*(v++) = pos_g.c.y;
/* texcoord: */
cb = weston_coord_surface_to_buffer(ev->surface, cs);
*(v++) = cb.c.x * inv_width;
pos_s = weston_coord_global_to_surface(ev, pos_g);
pos_b = weston_coord_surface_to_buffer(ev->surface, pos_s);
*(v++) = pos_b.c.x * inv_width;
if (buffer->buffer_origin == ORIGIN_TOP_LEFT) {
*(v++) = cb.c.y * inv_height;
*(v++) = pos_b.c.y * inv_height;
} else {
*(v++) = (buffer->height - cb.c.y) * inv_height;
*(v++) = (buffer->height - pos_b.c.y) * inv_height;
}
}

View File

@ -103,8 +103,8 @@ enum path_transition {
static void
clip_append_vertex(struct clip_context *ctx, float x, float y)
{
*ctx->vertices.x++ = x;
*ctx->vertices.y++ = y;
*ctx->vertices = weston_coord(x, y);
ctx->vertices++;
}
static enum path_transition
@ -195,17 +195,16 @@ clip_polygon_topbottom(struct clip_context *ctx,
static void
clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src,
float *dst_x, float *dst_y)
struct weston_coord *dst)
{
ctx->prev.x = src->x[src->n - 1];
ctx->prev.y = src->y[src->n - 1];
ctx->vertices.x = dst_x;
ctx->vertices.y = dst_y;
ctx->prev.x = src->pos[src->n - 1].x;
ctx->prev.y = src->pos[src->n - 1].y;
ctx->vertices = dst;
}
static int
clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
float *dst_x, float *dst_y)
struct weston_coord *dst)
{
enum path_transition trans;
int i;
@ -213,18 +212,18 @@ clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
if (src->n < 2)
return 0;
clip_context_prepare(ctx, src, dst_x, dst_y);
clip_context_prepare(ctx, src, dst);
for (i = 0; i < src->n; i++) {
trans = path_transition_left_edge(ctx, src->x[i], src->y[i]);
clip_polygon_leftright(ctx, trans, src->x[i], src->y[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);
}
return ctx->vertices.x - dst_x;
return ctx->vertices - dst;
}
static int
clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
float *dst_x, float *dst_y)
struct weston_coord *dst)
{
enum path_transition trans;
int i;
@ -232,18 +231,18 @@ clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
if (src->n < 2)
return 0;
clip_context_prepare(ctx, src, dst_x, dst_y);
clip_context_prepare(ctx, src, dst);
for (i = 0; i < src->n; i++) {
trans = path_transition_right_edge(ctx, src->x[i], src->y[i]);
clip_polygon_leftright(ctx, trans, src->x[i], src->y[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);
}
return ctx->vertices.x - dst_x;
return ctx->vertices - dst;
}
static int
clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
float *dst_x, float *dst_y)
struct weston_coord *dst)
{
enum path_transition trans;
int i;
@ -251,18 +250,18 @@ clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
if (src->n < 2)
return 0;
clip_context_prepare(ctx, src, dst_x, dst_y);
clip_context_prepare(ctx, src, dst);
for (i = 0; i < src->n; i++) {
trans = path_transition_top_edge(ctx, src->x[i], src->y[i]);
clip_polygon_topbottom(ctx, trans, src->x[i], src->y[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);
}
return ctx->vertices.x - dst_x;
return ctx->vertices - dst;
}
static int
clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
float *dst_x, float *dst_y)
struct weston_coord *dst)
{
enum path_transition trans;
int i;
@ -270,25 +269,24 @@ clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
if (src->n < 2)
return 0;
clip_context_prepare(ctx, src, dst_x, dst_y);
clip_context_prepare(ctx, src, dst);
for (i = 0; i < src->n; i++) {
trans = path_transition_bottom_edge(ctx, src->x[i], src->y[i]);
clip_polygon_topbottom(ctx, trans, src->x[i], src->y[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);
}
return ctx->vertices.x - dst_x;
return ctx->vertices - dst;
}
WESTON_EXPORT_FOR_TESTS int
clip_simple(struct clip_context *ctx,
struct polygon8 *surf,
float *ex,
float *ey)
struct weston_coord *e)
{
int i;
for (i = 0; i < surf->n; i++) {
ex[i] = CLIP(surf->x[i], ctx->clip.x1, ctx->clip.x2);
ey[i] = CLIP(surf->y[i], ctx->clip.y1, ctx->clip.y2);
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);
}
return surf->n;
}
@ -296,31 +294,28 @@ clip_simple(struct clip_context *ctx,
WESTON_EXPORT_FOR_TESTS int
clip_transformed(struct clip_context *ctx,
struct polygon8 *surf,
float *ex,
float *ey)
struct weston_coord *e)
{
struct polygon8 polygon;
int i, n;
polygon.n = clip_polygon_left(ctx, surf, polygon.x, polygon.y);
surf->n = clip_polygon_right(ctx, &polygon, surf->x, surf->y);
polygon.n = clip_polygon_top(ctx, surf, polygon.x, polygon.y);
surf->n = clip_polygon_bottom(ctx, &polygon, surf->x, surf->y);
polygon.n = clip_polygon_left(ctx, surf, polygon.pos);
surf->n = clip_polygon_right(ctx, &polygon, surf->pos);
polygon.n = clip_polygon_top(ctx, surf, polygon.pos);
surf->n = clip_polygon_bottom(ctx, &polygon, surf->pos);
/* Get rid of duplicate vertices */
ex[0] = surf->x[0];
ey[0] = surf->y[0];
e[0] = surf->pos[0];
n = 1;
for (i = 1; i < surf->n; i++) {
if (float_difference(ex[n - 1], surf->x[i]) == 0.0f &&
float_difference(ey[n - 1], surf->y[i]) == 0.0f)
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)
continue;
ex[n] = surf->x[i];
ey[n] = surf->y[i];
e[n] = surf->pos[i];
n++;
}
if (float_difference(ex[n - 1], surf->x[0]) == 0.0f &&
float_difference(ey[n - 1], surf->y[0]) == 0.0f)
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)
n--;
return n;

View File

@ -25,9 +25,10 @@
#ifndef _WESTON_VERTEX_CLIPPING_H
#define _WESTON_VERTEX_CLIPPING_H
#include <libweston/matrix.h>
struct polygon8 {
float x[8];
float y[8];
struct weston_coord pos[8];
int n;
};
@ -42,10 +43,7 @@ struct clip_context {
float x2, y2;
} clip;
struct {
float *x;
float *y;
} vertices;
struct weston_coord *vertices;
};
float
@ -54,13 +52,11 @@ float_difference(float a, float b);
int
clip_simple(struct clip_context *ctx,
struct polygon8 *surf,
float *ex,
float *ey);
struct weston_coord *e);
int
clip_transformed(struct clip_context *ctx,
struct polygon8 *surf,
float *ex,
float *ey);\
struct weston_coord *e);
#endif

View File

@ -60,11 +60,10 @@ populate_clip_context (struct clip_context *ctx)
static int
clip_polygon (struct clip_context *ctx,
struct polygon8 *polygon,
float *vertices_x,
float *vertices_y)
struct weston_coord *pos)
{
populate_clip_context(ctx);
return clip_transformed(ctx, polygon, vertices_x, vertices_y);
return clip_transformed(ctx, polygon, pos);
}
struct vertex_clip_test_data
@ -78,94 +77,152 @@ const struct vertex_clip_test_data test_data[] =
/* All inside */
{
{
{ INSIDE_X1, INSIDE_X2, INSIDE_X2, INSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
},
{
{ INSIDE_X1, INSIDE_X2, INSIDE_X2, INSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
}
},
/* Top outside */
{
{
{ INSIDE_X1, INSIDE_X2, INSIDE_X2, INSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, OUTSIDE_Y2, OUTSIDE_Y2 },
4
.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
},
{
{ INSIDE_X1, INSIDE_X1, INSIDE_X2, INSIDE_X2 },
{ BOUNDING_BOX_TOP_Y, INSIDE_Y1, INSIDE_Y1, BOUNDING_BOX_TOP_Y },
4
.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
}
},
/* Bottom outside */
{
{
{ INSIDE_X1, INSIDE_X2, INSIDE_X2, INSIDE_X1 },
{ OUTSIDE_Y1, OUTSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
},
{
{ INSIDE_X1, INSIDE_X2, INSIDE_X2, INSIDE_X1 },
{ BOUNDING_BOX_BOTTOM_Y, BOUNDING_BOX_BOTTOM_Y, INSIDE_Y2, INSIDE_Y2 },
4
.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
}
},
/* Left outside */
{
{
{ OUTSIDE_X1, INSIDE_X2, INSIDE_X2, OUTSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
},
{
{ BOUNDING_BOX_LEFT_X, INSIDE_X2, INSIDE_X2, BOUNDING_BOX_LEFT_X },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
}
},
/* Right outside */
{
{
{ INSIDE_X1, OUTSIDE_X2, OUTSIDE_X2, INSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
},
{
{ INSIDE_X1, BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_RIGHT_X, INSIDE_X1 },
{ INSIDE_Y1, INSIDE_Y1, INSIDE_Y2, INSIDE_Y2 },
4
.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
}
},
/* Diamond extending from bounding box edges, clip to bounding box */
{
{
{ BOUNDING_BOX_LEFT_X - 25, BOUNDING_BOX_LEFT_X + 25, BOUNDING_BOX_RIGHT_X + 25, BOUNDING_BOX_RIGHT_X - 25 },
{ BOUNDING_BOX_BOTTOM_Y + 25, BOUNDING_BOX_TOP_Y + 25, BOUNDING_BOX_TOP_Y - 25, BOUNDING_BOX_BOTTOM_Y - 25 },
4
.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
},
{
{ BOUNDING_BOX_LEFT_X, BOUNDING_BOX_LEFT_X, BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_RIGHT_X },
{ BOUNDING_BOX_BOTTOM_Y, BOUNDING_BOX_TOP_Y, BOUNDING_BOX_TOP_Y, BOUNDING_BOX_BOTTOM_Y },
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 */
{
{
{ BOUNDING_BOX_LEFT_X - 12.5, BOUNDING_BOX_LEFT_X + 25, BOUNDING_BOX_RIGHT_X + 12.5, BOUNDING_BOX_RIGHT_X - 25 },
{ BOUNDING_BOX_BOTTOM_Y + 25, BOUNDING_BOX_TOP_Y + 12.5, BOUNDING_BOX_TOP_Y - 25, BOUNDING_BOX_BOTTOM_Y - 12.5 },
4
.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
},
{
{ BOUNDING_BOX_LEFT_X + 12.5, BOUNDING_BOX_LEFT_X, BOUNDING_BOX_LEFT_X, BOUNDING_BOX_LEFT_X + 12.5,
BOUNDING_BOX_RIGHT_X - 12.5, BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_RIGHT_X, BOUNDING_BOX_RIGHT_X - 12.5 },
{ BOUNDING_BOX_BOTTOM_Y, BOUNDING_BOX_BOTTOM_Y + 12.5, BOUNDING_BOX_TOP_Y - 12.5, BOUNDING_BOX_TOP_Y,
BOUNDING_BOX_TOP_Y, BOUNDING_BOX_TOP_Y - 12.5, BOUNDING_BOX_BOTTOM_Y + 12.5, BOUNDING_BOX_BOTTOM_Y },
8
.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
}
}
};
@ -176,8 +233,7 @@ static void
deep_copy_polygon8(const struct polygon8 *src, struct polygon8 *dst)
{
dst->n = src->n;
ARRAY_COPY(dst->x, src->x);
ARRAY_COPY(dst->y, src->y);
ARRAY_COPY(dst->pos, src->pos);
}
TEST_P(clip_polygon_n_vertices_emitted, test_data)
@ -185,10 +241,9 @@ TEST_P(clip_polygon_n_vertices_emitted, test_data)
struct vertex_clip_test_data *tdata = data;
struct clip_context ctx;
struct polygon8 polygon;
float vertices_x[8];
float vertices_y[8];
struct weston_coord vertices[8];
deep_copy_polygon8(&tdata->surface, &polygon);
int emitted = clip_polygon(&ctx, &polygon, vertices_x, vertices_y);
int emitted = clip_polygon(&ctx, &polygon, vertices);
assert(emitted == tdata->expected.n);
}
@ -198,16 +253,15 @@ TEST_P(clip_polygon_expected_vertices, test_data)
struct vertex_clip_test_data *tdata = data;
struct clip_context ctx;
struct polygon8 polygon;
float vertices_x[8];
float vertices_y[8];
struct weston_coord vertices[8];
deep_copy_polygon8(&tdata->surface, &polygon);
int emitted = clip_polygon(&ctx, &polygon, vertices_x, vertices_y);
int emitted = clip_polygon(&ctx, &polygon, vertices);
int i = 0;
for (; i < emitted; ++i)
{
assert(vertices_x[i] == tdata->expected.x[i]);
assert(vertices_y[i] == tdata->expected.y[i]);
assert(vertices[i].x == tdata->expected.pos[i].x);
assert(vertices[i].y == tdata->expected.pos[i].y);
}
}