diff --git a/libweston/backend-drm/state-helpers.c b/libweston/backend-drm/state-helpers.c index dbcef7696..a9ae24337 100644 --- a/libweston/backend-drm/state-helpers.c +++ b/libweston/backend-drm/state-helpers.c @@ -224,13 +224,8 @@ 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; + struct weston_surface *surface = pnode->surface; + struct weston_buffer *buffer = surface->buffer_ref.buffer; uint16_t min_alpha = state->plane->alpha_min; uint16_t max_alpha = state->plane->alpha_max; @@ -243,58 +238,16 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state, assert(pnode->valid_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; - } + 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; /* Shift from S23.8 wl_fixed 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(sxf2 - sxf1) << 8; - state->src_h = wl_fixed_from_double(syf2 - syf1) << 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; /* Clamp our source co-ordinates to surface bounds; it's possible * for intermediate translations to give us slightly incorrect diff --git a/libweston/compositor.c b/libweston/compositor.c index 5c9462e77..ab244deca 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -195,6 +195,69 @@ get_placeholder_color(struct weston_paint_node *pnode, color->a = 1.0; } +/* If we have a valid 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; + pixman_region32_t dest_rect; + pixman_box32_t *box; + struct weston_coord corners[2]; + float sxf1, syf1, sxf2, syf2; + + 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; + } + pnode->buffer_source_x = sxf1; + pnode->buffer_source_y = syf1; + pnode->buffer_source_width = sxf2 - sxf1; + pnode->buffer_source_height = syf2 - syf1; +} + /* 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 +287,8 @@ paint_node_update_early(struct weston_paint_node *pnode) pnode->valid_transform = weston_matrix_to_transform(mat, &pnode->transform); + if (pnode->valid_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 65f754c25..91f40ef96 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -703,6 +703,15 @@ struct weston_paint_node { bool valid_transform; enum wl_output_transform transform; + /* The paint node's output destination rectangle, only valid if valid_transform + * is true */ + struct weston_geometry output_dest; + /* The paint node's buffer source rectangle, only valid if valid_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;