gl-renderer: Assume axis alignment using node's valid_transform

Assume axis alignment using node's valid_transform boolean instead of
relying on the transform flags of the weston_view struct. This is more
reliable since matrix flags could erroneously hang around after a
series of transforms. Additionally, nodes with standard output
transforms like translations, flips and rotations by 90° can now take
the fast axis aligned path.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-04-09 15:02:53 +01:00 committed by Marius Vlad
parent 287b3f1758
commit d4fe0a42fd
2 changed files with 17 additions and 41 deletions

View File

@ -69,6 +69,7 @@ struct geometry {
float s; /* sin phi */ float s; /* sin phi */
float c; /* cos phi */ float c; /* cos phi */
float phi; float phi;
bool axis_aligned;
}; };
struct weston_surface { struct weston_surface {
@ -76,11 +77,6 @@ struct weston_surface {
struct weston_view { struct weston_view {
struct weston_surface *surface; struct weston_surface *surface;
struct {
int enabled;
struct weston_matrix matrix;
} transform;
struct geometry *geometry; struct geometry *geometry;
}; };
@ -130,21 +126,17 @@ global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
} }
} }
static bool
node_axis_aligned(const struct weston_view *view)
{
return !view->transform.enabled ||
(view->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
}
/* ---------------------- copied ends -----------------------*/ /* ---------------------- copied ends -----------------------*/
static void static void
geometry_set_phi(struct geometry *g, float phi) geometry_set_phi(struct geometry *g, float phi)
{ {
float integer;
g->phi = phi; g->phi = phi;
g->s = sin(phi); g->s = sin(phi);
g->c = cos(phi); g->c = cos(phi);
g->axis_aligned = fabs(modff(g->c, &integer)) < 0.0001f;
} }
static void static void
@ -245,7 +237,7 @@ draw_box(cairo_t *cr, pixman_box32_t *box, struct weston_view *view)
static void static void
draw_geometry(cairo_t *cr, struct weston_view *view, draw_geometry(cairo_t *cr, struct weston_view *view,
struct clipper_vertex *v, int n) struct clipper_vertex *v, int n, struct clipper_quad *quad)
{ {
struct geometry *g = view->geometry; struct geometry *g = view->geometry;
float cx, cy; float cx, cy;
@ -255,7 +247,7 @@ draw_geometry(cairo_t *cr, struct weston_view *view,
cairo_fill(cr); cairo_fill(cr);
weston_view_from_global_float(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); cairo_arc(cr, cx, cy, 1.5, 0.0, 2.0 * M_PI);
if (view->transform.enabled == 0) if (!quad->axis_aligned)
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.8); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.8);
cairo_fill(cr); cairo_fill(cr);
@ -286,8 +278,7 @@ redraw_handler(struct widget *widget, void *data)
int n; int n;
global_to_surface(&g->quad, &cliptest->view, transformed_v); global_to_surface(&g->quad, &cliptest->view, transformed_v);
clipper_quad_init(&quad, transformed_v, clipper_quad_init(&quad, transformed_v, g->axis_aligned);
node_axis_aligned(&cliptest->view));
n = clipper_quad_clip_box32(&quad, &g->surf, v); n = clipper_quad_clip_box32(&quad, &g->surf, v);
widget_get_allocation(cliptest->widget, &allocation); widget_get_allocation(cliptest->widget, &allocation);
@ -322,7 +313,7 @@ redraw_handler(struct widget *widget, void *data)
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD); CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 5.0); cairo_set_font_size(cr, 5.0);
draw_geometry(cr, &cliptest->view, v, n); draw_geometry(cr, &cliptest->view, v, n, &quad);
cairo_pop_group_to_source(cr); cairo_pop_group_to_source(cr);
cairo_paint(cr); cairo_paint(cr);
@ -401,8 +392,6 @@ axis_handler(struct widget *widget, struct input *input, uint32_t time,
geometry_set_phi(geom, geom->phi + geometry_set_phi(geom, geom->phi +
(M_PI / 12.0) * wl_fixed_to_double(value)); (M_PI / 12.0) * wl_fixed_to_double(value));
cliptest->view.transform.enabled = 1;
cliptest->view.transform.matrix.type = WESTON_MATRIX_TRANSFORM_ROTATE;
widget_schedule_redraw(cliptest->widget); widget_schedule_redraw(cliptest->widget);
} }
@ -452,20 +441,12 @@ key_handler(struct window *window, struct input *input, uint32_t time,
break; break;
case XKB_KEY_n: case XKB_KEY_n:
geometry_set_phi(g, g->phi + (M_PI / 24.0)); geometry_set_phi(g, g->phi + (M_PI / 24.0));
cliptest->view.transform.enabled = 1;
cliptest->view.transform.matrix.type =
WESTON_MATRIX_TRANSFORM_ROTATE;
break; break;
case XKB_KEY_m: case XKB_KEY_m:
geometry_set_phi(g, g->phi - (M_PI / 24.0)); geometry_set_phi(g, g->phi - (M_PI / 24.0));
cliptest->view.transform.enabled = 1;
cliptest->view.transform.matrix.type =
WESTON_MATRIX_TRANSFORM_ROTATE;
break; break;
case XKB_KEY_r: case XKB_KEY_r:
geometry_set_phi(g, 0.0); geometry_set_phi(g, 0.0);
cliptest->view.transform.enabled = 0;
cliptest->view.transform.matrix.type = 0;
break; break;
default: default:
return; return;
@ -500,8 +481,6 @@ cliptest_create(struct display *display)
cliptest = xzalloc(sizeof *cliptest); cliptest = xzalloc(sizeof *cliptest);
cliptest->view.surface = &cliptest->surface; cliptest->view.surface = &cliptest->surface;
cliptest->view.geometry = &cliptest->geometry; cliptest->view.geometry = &cliptest->geometry;
cliptest->view.transform.enabled = 0;
cliptest->view.transform.matrix.type = 0;
geometry_init(&cliptest->geometry); geometry_init(&cliptest->geometry);
geometry_init(&cliptest->ui.geometry); geometry_init(&cliptest->ui.geometry);
@ -574,16 +553,13 @@ benchmark(void)
geometry_set_phi(&geom, 0.0); geometry_set_phi(&geom, 0.0);
view.surface = &surface; view.surface = &surface;
view.transform.enabled = 1;
view.transform.matrix.type = WESTON_MATRIX_TRANSFORM_ROTATE;
view.geometry = &geom; view.geometry = &geom;
reset_timer(); reset_timer();
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
geometry_set_phi(&geom, (float)i / 360.0f); geometry_set_phi(&geom, (float)i / 360.0f);
global_to_surface(&geom.quad, &view, transformed_v); global_to_surface(&geom.quad, &view, transformed_v);
clipper_quad_init(&quad, transformed_v, clipper_quad_init(&quad, transformed_v, geom.axis_aligned);
node_axis_aligned(&view));
clipper_quad_clip_box32(&quad, &geom.surf, v); clipper_quad_clip_box32(&quad, &geom.surf, v);
} }
t = read_timer(); t = read_timer();

View File

@ -1419,13 +1419,6 @@ global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
} }
} }
static bool
node_axis_aligned(const struct weston_view *view)
{
return !view->transform.enabled ||
(view->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
}
/* Transform damage 'region' in global coordinates to damage 'quads' in surface /* Transform damage 'region' in global coordinates to damage 'quads' in surface
* coordinates. 'quads' and 'nquads' are output arguments set if 'quads' is * coordinates. 'quads' and 'nquads' are output arguments set if 'quads' is
* NULL, no transformation happens otherwise. Caller must free 'quads' if * NULL, no transformation happens otherwise. Caller must free 'quads' if
@ -1456,8 +1449,15 @@ transform_damage(const struct weston_paint_node *pnode,
*quads = quads_alloc = malloc(nrects * sizeof *quads_alloc); *quads = quads_alloc = malloc(nrects * sizeof *quads_alloc);
*nquads = nrects; *nquads = nrects;
/* All the damage rects are axis-aligned in global space. This implies
* that all the horizontal and vertical edges are respectively parallel
* to each other. Because affine transformations preserve parallelism we
* can safely assume that if the node's output matrix is affine and
* stores standard output transforms (translations, flips and rotations
* by 90°), then all the transformed quads are axis-aligned in surface
* space. */
view = pnode->view; view = pnode->view;
axis_aligned = node_axis_aligned(view); axis_aligned = pnode->valid_transform;
for (i = 0; i < nrects; i++) { for (i = 0; i < nrects; i++) {
global_to_surface(&rects[i], view, polygon); global_to_surface(&rects[i], view, polygon);
clipper_quad_init(&quads_alloc[i], polygon, axis_aligned); clipper_quad_init(&quads_alloc[i], polygon, axis_aligned);