From 3dc300eceb5c79ef3b820ece72fceb2deee96581 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Mon, 16 Mar 2026 13:30:46 -0500 Subject: [PATCH] compositor: Store the output destination and buffer source rects in pnode Instead of having the drm backend calculate these per frame, let's store them in the paint node when they change. Signed-off-by: Derek Foreman --- libweston/backend-drm/state-helpers.c | 82 +++----------------------- libweston/compositor.c | 85 +++++++++++++++++++++++++++ libweston/libweston-internal.h | 9 +++ 3 files changed, 102 insertions(+), 74 deletions(-) diff --git a/libweston/backend-drm/state-helpers.c b/libweston/backend-drm/state-helpers.c index 52c95a88d..cca1a80f5 100644 --- a/libweston/backend-drm/state-helpers.c +++ b/libweston/backend-drm/state-helpers.c @@ -227,13 +227,6 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state, struct weston_paint_node *pnode, uint64_t zpos) { - struct drm_output *output = state->handle->output; - struct weston_view *ev = pnode->view; - struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; - pixman_region32_t dest_rect; - pixman_box32_t *box; - struct weston_coord corners[2]; - float sxf1, syf1, sxf2, syf2, swidth, sheight; uint16_t min_alpha = state->plane->alpha_min; uint16_t max_alpha = state->plane->alpha_max; @@ -246,75 +239,16 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state, assert(pnode->simple_transform); state->rotation = drm_rotation_from_output_transform(state->plane, pnode->transform); - box = pixman_region32_extents(&ev->transform.boundingbox); - - /* First calculate the destination co-ordinates by taking the - * area of the view which is visible on this output, performing any - * transforms to account for output rotation and scale as necessary. */ - pixman_region32_init(&dest_rect); - pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox, - &output->base.region); - weston_region_global_to_output(&dest_rect, &output->base, &dest_rect); - - box = pixman_region32_extents(&dest_rect); - - state->dest_x = box->x1; - state->dest_y = box->y1; - state->dest_w = box->x2 - box->x1; - state->dest_h = box->y2 - box->y1; - - /* Now calculate the source rectangle, by transforming the destination - * rectangle by the output to buffer matrix. */ - corners[0] = weston_matrix_transform_coord( - &pnode->output_to_buffer_matrix, - weston_coord(box->x1, box->y1)); - corners[1] = weston_matrix_transform_coord( - &pnode->output_to_buffer_matrix, - weston_coord(box->x2, box->y2)); - sxf1 = corners[0].x; - syf1 = corners[0].y; - sxf2 = corners[1].x; - syf2 = corners[1].y; - pixman_region32_fini(&dest_rect); - - /* Make sure that our post-transform coordinates are in the - * right order. - */ - if (sxf1 > sxf2) { - float temp = sxf1; - - sxf1 = sxf2; - sxf2 = temp; - } - if (syf1 > syf2) { - float temp = syf1; - - syf1 = syf2; - syf2 = temp; - } - - /* Clamp our source co-ordinates to surface bounds; it's possible - * for intermediate translations to give us slightly incorrect - * co-ordinates if we have, for example, multiple zooming - * transformations. View bounding boxes are also explicitly rounded - * greedily. */ - if (sxf1 < 0.0) - sxf1 = 0.0; - if (syf1 < 0.0) - syf1 = 0.0; - - swidth = sxf2 - sxf1; - sheight = syf2 - syf1; - if (swidth > buffer->width - sxf1) - swidth = buffer->width - sxf1; - if (sheight > buffer->height - syf1) - sheight = buffer->height - syf1; + state->dest_x = pnode->output_dest.x; + state->dest_y = pnode->output_dest.y; + state->dest_w = pnode->output_dest.width; + state->dest_h = pnode->output_dest.height; /* Convert to U16.16 KMS fixed-point encoding. */ - state->src_x = wl_fixed_from_double(sxf1) << 8; - state->src_y = wl_fixed_from_double(syf1) << 8; - state->src_w = wl_fixed_from_double(swidth) << 8; - state->src_h = wl_fixed_from_double(sheight) << 8; + state->src_x = wl_fixed_from_double(pnode->buffer_source_x) << 8; + state->src_y = wl_fixed_from_double(pnode->buffer_source_y) << 8; + state->src_w = wl_fixed_from_double(pnode->buffer_source_width) << 8; + state->src_h = wl_fixed_from_double(pnode->buffer_source_height) << 8; /* apply zpos if available */ state->zpos = zpos; diff --git a/libweston/compositor.c b/libweston/compositor.c index a6c4e5cdc..240883860 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -195,6 +195,89 @@ get_placeholder_color(struct weston_paint_node *pnode, color->a = 1.0; } +/* If we have a simple transform, we can compute an output destination + * rectangle and a buffer source rectangle that backends can use for plane + * setup. + */ +static void +paint_node_update_rectangles(struct weston_paint_node *pnode) +{ + struct weston_view *view = pnode->view; + struct weston_output *output = pnode->output; + struct weston_surface *surface = pnode->surface; + struct weston_buffer *buffer = surface->buffer_ref.buffer; + pixman_region32_t dest_rect; + pixman_box32_t *box; + struct weston_coord corners[2]; + float sxf1, syf1, sxf2, syf2, swidth, sheight; + + box = pixman_region32_extents(&view->transform.boundingbox); + + /* First calculate the destination co-ordinates by taking the + * area of the view which is visible on this output, performing any + * transforms to account for output rotation and scale as necessary. */ + pixman_region32_init(&dest_rect); + pixman_region32_intersect(&dest_rect, &view->transform.boundingbox, + &output->region); + weston_region_global_to_output(&dest_rect, output, &dest_rect); + + box = pixman_region32_extents(&dest_rect); + pnode->output_dest.x = box->x1; + pnode->output_dest.y = box->y1; + pnode->output_dest.width = box->x2 - box->x1; + pnode->output_dest.height = box->y2 - box->y1; + + /* Now calculate the source rectangle, by transforming the destination + * rectangle by the output to buffer matrix. */ + corners[0] = weston_matrix_transform_coord(&pnode->output_to_buffer_matrix, + weston_coord(box->x1, box->y1)); + corners[1] = weston_matrix_transform_coord(&pnode->output_to_buffer_matrix, + weston_coord(box->x2, box->y2)); + sxf1 = corners[0].x; + syf1 = corners[0].y; + sxf2 = corners[1].x; + syf2 = corners[1].y; + pixman_region32_fini(&dest_rect); + + /* Make sure that our post-transform coordinates are in the + * right order. + */ + if (sxf1 > sxf2) { + float temp = sxf1; + + sxf1 = sxf2; + sxf2 = temp; + } + if (syf1 > syf2) { + float temp = syf1; + + syf1 = syf2; + syf2 = temp; + } + + /* Clamp our source co-ordinates to surface bounds; it's possible + * for intermediate translations to give us slightly incorrect + * co-ordinates if we have, for example, multiple zooming + * transformations. View bounding boxes are also explicitly rounded + * greedily. */ + if (sxf1 < 0.0) + sxf1 = 0.0; + if (syf1 < 0.0) + syf1 = 0.0; + + swidth = sxf2 - sxf1; + sheight = syf2 - syf1; + if (swidth > buffer->width - sxf1) + swidth = buffer->width - sxf1; + if (sheight > buffer->height - syf1) + sheight = buffer->height - syf1; + + pnode->buffer_source_x = sxf1; + pnode->buffer_source_y = syf1; + pnode->buffer_source_width = swidth; + pnode->buffer_source_height = sheight; +} + /* Paint nodes contain filter and transform information that needs to be * up to date before assign_planes() is called. But there are also * damage related bits that must be updated after assign_planes() @@ -224,6 +307,8 @@ paint_node_update_early(struct weston_paint_node *pnode) pnode->simple_transform = weston_matrix_to_transform(mat, &pnode->transform); + if (pnode->simple_transform) + paint_node_update_rectangles(pnode); } buffer = pnode->surface->buffer_ref.buffer; diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index 22b3d4ef3..99b15e300 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -712,6 +712,15 @@ struct weston_paint_node { bool simple_transform; /* Only valid if the transform is considered simple. */ enum wl_output_transform transform; + /* The paint node's output destination rectangle, only valid if simple_transform + * is true */ + struct weston_geometry output_dest; + /* The paint node's buffer source rectangle, only valid if simple_transform + * is true */ + float buffer_source_x; + float buffer_source_y; + float buffer_source_width; + float buffer_source_height; /* struct weston_output::paint_node_z_order_list */ struct wl_list z_order_link;