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;