Merge branch 'view_to_node_round_two' into 'main'

More weston_view removal from backends and renderers

See merge request wayland/weston!2034
This commit is contained in:
Derek Foreman 2026-05-01 08:18:43 -05:00
commit 63b63e3e12
6 changed files with 188 additions and 171 deletions

View file

@ -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

View file

@ -195,6 +195,107 @@ 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;
}
static void
paint_node_rebuild_regions(struct weston_paint_node *pnode)
{
struct weston_surface *surface = pnode->surface;
struct weston_view *view = pnode->view;
pixman_region32_t *surface_opaque = &pnode->surface_opaque;
pixman_region32_t *surface_blend = &pnode->surface_blend;
pixman_region32_fini(surface_opaque);
pixman_region32_fini(surface_blend);
if (pnode->is_fully_opaque) {
pixman_region32_init_rect(surface_opaque, 0, 0,
surface->width,
surface->height);
} else {
pixman_region32_init(surface_opaque);
pixman_region32_copy(surface_opaque, &pnode->surface->opaque);
}
if (view->geometry.scissor_enabled)
pixman_region32_intersect(surface_opaque,
surface_opaque,
&pnode->view->geometry.scissor);
/* blended region is whole surface minus opaque region: */
pixman_region32_init_rect(surface_blend, 0, 0,
surface->width, surface->height);
if (view->geometry.scissor_enabled)
pixman_region32_intersect(surface_opaque,
surface_opaque,
&view->geometry.scissor);
pixman_region32_subtract(surface_blend, surface_blend,
surface_opaque);
}
/* 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,8 +325,13 @@ 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);
}
if (view_dirty)
paint_node_rebuild_regions(pnode);
buffer = pnode->surface->buffer_ref.buffer;
pnode->draw_solid = false;
pnode->is_fully_transparent = false;
@ -441,9 +547,14 @@ weston_paint_node_create(struct weston_surface *surface,
pixman_region32_init(&pnode->clipped_view);
pixman_region32_copy(&pnode->visible, &view->transform.boundingbox);
pixman_region32_init(&pnode->surface_opaque);
pixman_region32_init(&pnode->surface_blend);
pnode->plane = &pnode->output->primary_plane;
pnode->plane_next = NULL;
pnode->view_transform_matrix = &view->transform.matrix;
pnode->need_hole = false;
pnode->status =
WESTON_PAINT_NODE_ALL_DIRTY & ~WESTON_PAINT_NODE_PLANE_DIRTY;
@ -499,6 +610,8 @@ weston_paint_node_destroy(struct weston_paint_node *pnode)
pixman_region32_fini(&pnode->visible);
pixman_region32_fini(&pnode->visible_previous);
pixman_region32_fini(&pnode->clipped_view);
pixman_region32_fini(&pnode->surface_opaque);
pixman_region32_fini(&pnode->surface_blend);
free(pnode->internal_name);
free(pnode);
}

View file

@ -689,6 +689,7 @@ struct weston_paint_node {
/* struct weston_view::paint_node_list */
struct wl_list view_link;
struct weston_view *view;
struct weston_matrix *view_transform_matrix;
/* struct weston_output::paint_node_list */
struct wl_list output_link;
@ -705,6 +706,20 @@ 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;
/* Opaqure region in surface co-ordinates */
pixman_region32_t surface_opaque;
/* Blended region in surface co-ordinates */
pixman_region32_t surface_blend;
/* struct weston_output::paint_node_z_order_list */
struct wl_list z_order_link;

View file

@ -350,44 +350,34 @@ draw_node_translated(struct weston_paint_node *pnode,
pixman_region32_t *repaint_global)
{
struct weston_output *output = pnode->output;
struct weston_surface *surface = pnode->surface;
struct weston_view *view = pnode->view;
/* non-opaque region in surface coordinates: */
pixman_region32_t surface_blend;
/* region to be painted in output coordinates: */
pixman_region32_t repaint_output;
pixman_region32_init(&repaint_output);
/* Blended region is whole surface minus opaque region,
* unless surface alpha forces us to blend all.
*/
pixman_region32_init_rect(&surface_blend, 0, 0,
surface->width, surface->height);
if (!(view->alpha < 1.0)) {
pixman_region32_subtract(&surface_blend, &surface_blend,
&surface->opaque);
if (pixman_region32_not_empty(&surface->opaque)) {
region_intersect_only_translation(&repaint_output,
repaint_global,
&surface->opaque,
view);
weston_region_global_to_output(&repaint_output,
output,
&repaint_output);
repaint_region(pnode, &repaint_output, NULL,
PIXMAN_OP_SRC);
}
}
if (pixman_region32_not_empty(&surface_blend)) {
if (pixman_region32_not_empty(&pnode->surface_opaque)) {
region_intersect_only_translation(&repaint_output,
repaint_global,
&surface_blend, view);
&pnode->surface_opaque,
pnode->view);
weston_region_global_to_output(&repaint_output,
output,
&repaint_output);
if (pnode->view_alpha < 1.0)
repaint_region(pnode, &repaint_output, NULL,
PIXMAN_OP_OVER);
else
repaint_region(pnode, &repaint_output, NULL,
PIXMAN_OP_SRC);
}
if (pixman_region32_not_empty(&pnode->surface_blend)) {
region_intersect_only_translation(&repaint_output,
repaint_global,
&pnode->surface_blend,
pnode->view);
weston_region_global_to_output(&repaint_output,
output,
&repaint_output);
@ -395,7 +385,6 @@ draw_node_translated(struct weston_paint_node *pnode,
repaint_region(pnode, &repaint_output, NULL, PIXMAN_OP_OVER);
}
pixman_region32_fini(&surface_blend);
pixman_region32_fini(&repaint_output);
}
@ -405,7 +394,6 @@ draw_node_source_clipped(struct weston_paint_node *pnode,
{
struct weston_surface *surface = pnode->surface;
struct weston_output *output = pnode->output;
struct weston_view *view = pnode->view;
pixman_region32_t surf_region;
pixman_region32_t buffer_region;
pixman_region32_t repaint_output;
@ -415,11 +403,10 @@ draw_node_source_clipped(struct weston_paint_node *pnode,
* opaque separately has no benefit.
*/
pixman_region32_init_rect(&surf_region, 0, 0,
surface->width, surface->height);
if (view->geometry.scissor_enabled)
pixman_region32_intersect(&surf_region, &surf_region,
&view->geometry.scissor);
pixman_region32_init(&surf_region);
pixman_region32_union(&surf_region,
&pnode->surface_opaque,
&pnode->surface_blend);
pixman_region32_init(&buffer_region);
weston_surface_to_buffer_region(surface, &surf_region, &buffer_region);

View file

@ -1728,7 +1728,7 @@ prepare_solid_draw(struct gl_shader_config *sconf,
.variant = SHADER_VARIANT_SOLID,
.input_is_premult = true,
},
.projection = pnode->view->transform.matrix,
.projection = *pnode->view_transform_matrix,
.view_alpha = pnode->view_alpha,
.unicolor = { pnode->solid.r,
pnode->solid.g,
@ -1917,7 +1917,7 @@ prepare_textured_draw(struct gl_shader_config *sconf,
*sconf = (struct gl_shader_config) {
.req.texcoord_input = SHADER_TEXCOORD_INPUT_SURFACE,
.projection = pnode->view->transform.matrix,
.projection = *pnode->view_transform_matrix,
.surface_to_buffer =
pnode->surface->surface_to_buffer_matrix,
.view_alpha = pnode->view_alpha,
@ -2405,7 +2405,6 @@ repaint_region(struct gl_renderer *gr,
struct weston_paint_node *pnode,
struct clipper_quad *quads,
int nquads,
pixman_region32_t *region,
struct gl_shader_config *sconf,
bool opaque)
{
@ -2416,12 +2415,18 @@ repaint_region(struct gl_renderer *gr,
int i, j, n, nrects, positions_size, barycentrics_size, indices_size;
int nvtx = 0, nidx = 0;
bool wireframe = gr->debug_mode == DEBUG_MODE_WIREFRAME;
pixman_region32_t *region;
/* Build-time sub-mesh constants. Clipping emits 8 vertices max.
* store_indices() store at most 10 indices. */
const int nvtx_max = 8;
const int nidx_max = 10;
if (opaque)
region = &pnode->surface_opaque;
else
region = &pnode->surface_blend;
rects = pixman_region32_rectangles(region, &nrects);
assert((nrects > 0) && (nquads > 0));
@ -2595,10 +2600,6 @@ draw_paint_node(struct weston_paint_node *pnode,
struct gl_surface_state *gs = get_surface_state(pnode->surface);
/* repaint bounding region in global coordinates: */
pixman_region32_t repaint;
/* opaque region in surface coordinates: */
pixman_region32_t surface_opaque;
/* non-opaque region in surface coordinates: */
pixman_region32_t surface_blend;
struct gl_shader_config sconf;
struct clipper_quad *quads = NULL;
int nquads;
@ -2638,51 +2639,23 @@ draw_paint_node(struct weston_paint_node *pnode,
goto out;
}
if (pnode->is_fully_opaque) {
pixman_region32_init_rect(&surface_opaque, 0, 0,
pnode->surface->width,
pnode->surface->height);
} else {
pixman_region32_init(&surface_opaque);
pixman_region32_copy(&surface_opaque, &pnode->surface->opaque);
}
if (pnode->view->geometry.scissor_enabled)
pixman_region32_intersect(&surface_opaque,
&surface_opaque,
&pnode->view->geometry.scissor);
/* blended region is whole surface minus opaque region: */
pixman_region32_init_rect(&surface_blend, 0, 0,
pnode->surface->width, pnode->surface->height);
if (pnode->view->geometry.scissor_enabled)
pixman_region32_intersect(&surface_blend, &surface_blend,
&pnode->view->geometry.scissor);
pixman_region32_subtract(&surface_blend, &surface_blend,
&surface_opaque);
gl_log_paint_node_bbox_and_region(gr, "repaint region", &repaint);
transform_damage(pnode, &repaint, &quads, &nquads);
if (pixman_region32_not_empty(&surface_opaque)) {
gl_log_paint_node_bbox_and_region(gr, "opaque region", &surface_opaque);
repaint_region(gr, pnode, quads, nquads, &surface_opaque,
&sconf, true);
if (pixman_region32_not_empty(&pnode->surface_opaque)) {
gl_log_paint_node_bbox_and_region(gr, "opaque region", &pnode->surface_opaque);
repaint_region(gr, pnode, quads, nquads, &sconf, true);
gs->used_in_output_repaint = true;
}
if (pixman_region32_not_empty(&surface_blend)) {
gl_log_paint_node_bbox_and_region(gr, "blended region", &surface_blend);
repaint_region(gr, pnode, quads, nquads, &surface_blend, &sconf,
false);
if (pixman_region32_not_empty(&pnode->surface_blend)) {
gl_log_paint_node_bbox_and_region(gr, "blended region", &pnode->surface_blend);
repaint_region(gr, pnode, quads, nquads, &sconf, false);
gs->used_in_output_repaint = true;
}
free(quads);
pixman_region32_fini(&surface_blend);
pixman_region32_fini(&surface_opaque);
out:
pixman_region32_fini(&repaint);
}

View file

@ -1523,7 +1523,7 @@ vulkan_pipeline_config_init_for_paint_node(struct vulkan_pipeline_config *pconf,
.renderpass = vo->renderpass,
.green_tint = (vr->debug_mode == DEBUG_MODE_FRAGMENT),
},
.projection = pnode->view->transform.matrix,
.projection = *pnode->view_transform_matrix,
.surface_to_buffer =
pnode->surface->surface_to_buffer_matrix,
.view_alpha = pnode->view_alpha,
@ -1633,7 +1633,7 @@ static void
repaint_region(struct vulkan_renderer *vr,
struct weston_paint_node *pnode,
pixman_region32_t *region,
pixman_region32_t *surf_region,
bool opaque,
const struct vulkan_pipeline_config *pconf,
struct vulkan_renderer_frame *fr)
{
@ -1642,12 +1642,18 @@ repaint_region(struct vulkan_renderer *vr,
struct vulkan_pipeline *pipeline;
VkCommandBuffer cmd_buffer = fr->cmd_buffer;
uint32_t nfans;
pixman_region32_t *surf_region;
struct wl_array vertices;
struct wl_array vtxcnt;
wl_array_init(&vertices);
wl_array_init(&vtxcnt);
if (opaque)
surf_region = &pnode->surface_opaque;
else
surf_region = &pnode->surface_blend;
/* The final region to be painted is the intersection of 'region' and
* 'surf_region'. However, 'region' is in the global coordinates, and
* 'surf_region' is in the surface-local coordinates.
@ -1772,10 +1778,6 @@ draw_paint_node(struct weston_paint_node *pnode,
struct weston_buffer *buffer = vs->buffer_ref.buffer;
/* repaint bounding region in global coordinates: */
pixman_region32_t repaint;
/* opaque region in surface coordinates: */
pixman_region32_t surface_opaque;
/* non-opaque region in surface coordinates: */
pixman_region32_t surface_blend;
struct vulkan_pipeline_config pconf;
struct vulkan_pipeline *pipeline;
@ -1813,30 +1815,7 @@ draw_paint_node(struct weston_paint_node *pnode,
image_view, sampler,
&vb->descriptor_set);
if (pnode->is_fully_opaque) {
pixman_region32_init_rect(&surface_opaque, 0, 0,
pnode->surface->width,
pnode->surface->height);
} else {
pixman_region32_init(&surface_opaque);
pixman_region32_copy(&surface_opaque, &pnode->surface->opaque);
}
if (pnode->view->geometry.scissor_enabled)
pixman_region32_intersect(&surface_opaque,
&surface_opaque,
&pnode->view->geometry.scissor);
/* blended region is whole surface minus opaque region: */
pixman_region32_init_rect(&surface_blend, 0, 0,
pnode->surface->width, pnode->surface->height);
if (pnode->view->geometry.scissor_enabled)
pixman_region32_intersect(&surface_blend, &surface_blend,
&pnode->view->geometry.scissor);
pixman_region32_subtract(&surface_blend, &surface_blend,
&surface_opaque);
if (pixman_region32_not_empty(&surface_opaque)) {
if (pixman_region32_not_empty(&pnode->surface_opaque)) {
struct vulkan_pipeline_config alt = pconf;
if (alt.req.variant == PIPELINE_VARIANT_RGBA)
@ -1844,19 +1823,16 @@ draw_paint_node(struct weston_paint_node *pnode,
alt.req.blend = (pnode->view_alpha < 1.0);
repaint_region(vr, pnode, &repaint, &surface_opaque, &alt, fr);
repaint_region(vr, pnode, &repaint, true, &alt, fr);
vs->used_in_output_repaint = true;
}
pconf.req.blend = true;
if (pixman_region32_not_empty(&surface_blend)) {
repaint_region(vr, pnode, &repaint, &surface_blend, &pconf, fr);
if (pixman_region32_not_empty(&pnode->surface_blend)) {
repaint_region(vr, pnode, &repaint, false, &pconf, fr);
vs->used_in_output_repaint = true;
}
pixman_region32_fini(&surface_blend);
pixman_region32_fini(&surface_opaque);
out:
pixman_region32_fini(&repaint);
}