diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 97faa2125..f27b9a668 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1649,7 +1649,6 @@ struct weston_view { struct wl_list link; /* weston_compositor::view_list */ struct weston_layer_entry layer_link; /* part of geometry */ - struct weston_plane *plane; /* For weston_layer inheritance from another view */ struct weston_view *parent_view; diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c index 273f26a4f..7b45fc546 100644 --- a/libweston/backend-drm/state-propose.c +++ b/libweston/backend-drm/state-propose.c @@ -1055,11 +1055,11 @@ drm_assign_planes(struct weston_output *output_base) drm_debug(b, "\t[repaint] view %p on %s plane %lu\n", ev, plane_type_enums[target_plane->type].name, (unsigned long) target_plane->plane_id); - weston_view_move_to_plane(ev, &target_plane->base); + weston_paint_node_move_to_plane(pnode, &target_plane->base); } else { drm_debug(b, "\t[repaint] view %p using renderer " "composition\n", ev); - weston_view_move_to_plane(ev, primary); + weston_paint_node_move_to_plane(pnode, primary); } if (!target_plane || diff --git a/libweston/backend-vnc/vnc.c b/libweston/backend-vnc/vnc.c index 975838779..0dae686c0 100644 --- a/libweston/backend-vnc/vnc.c +++ b/libweston/backend-vnc/vnc.c @@ -449,7 +449,8 @@ vnc_client_cleanup(struct nvnc_client *client) } static struct weston_pointer * -vnc_output_get_pointer(struct vnc_output *output) +vnc_output_get_pointer(struct vnc_output *output, + struct weston_paint_node **pointer_pnode) { struct weston_pointer *pointer = NULL; struct weston_paint_node *pnode; @@ -464,8 +465,10 @@ vnc_output_get_pointer(struct vnc_output *output) return NULL; wl_list_for_each(pnode, &output->base.paint_node_z_order_list, z_order_link) { - if (pnode->view == pointer->sprite) + if (pnode->view == pointer->sprite) { + *pointer_pnode = pnode; return pointer; + } } return NULL; @@ -476,6 +479,7 @@ vnc_output_update_cursor(struct vnc_output *output) { struct vnc_backend *backend = output->backend; struct weston_pointer *pointer; + struct weston_paint_node *pointer_pnode = NULL; struct weston_view *view; struct weston_buffer *buffer; struct nvnc_fb *fb; @@ -484,7 +488,7 @@ vnc_output_update_cursor(struct vnc_output *output) uint8_t *src, *dst; int i; - pointer = vnc_output_get_pointer(output); + pointer = vnc_output_get_pointer(output, &pointer_pnode); if (!pointer) return; @@ -500,7 +504,9 @@ vnc_output_update_cursor(struct vnc_output *output) if (format != WL_SHM_FORMAT_ARGB8888) return; - weston_view_move_to_plane(view, &output->cursor_plane); + assert(pointer_pnode); + + weston_paint_node_move_to_plane(pointer_pnode, &output->cursor_plane); if (view->surface == output->cursor_surface && !pixman_region32_not_empty(&view->surface->damage)) @@ -1050,7 +1056,7 @@ vnc_output_assign_planes(struct weston_output *base) assert(view->output_mask & (1u << output->base.id)); /* Skip cursor view */ - if (view->plane == &output->cursor_plane) + if (pnode->plane == &output->cursor_plane) continue; if (topmost && @@ -1061,7 +1067,7 @@ vnc_output_assign_planes(struct weston_output *base) pixman_region32_t local_damage; pixman_region16_t nvnc_damage; - weston_view_move_to_plane(view, &output->scanout_plane); + weston_paint_node_move_to_plane(pnode, &output->scanout_plane); /* Convert to local coordinates */ pixman_region32_init(&local_damage); @@ -1083,7 +1089,7 @@ vnc_output_assign_planes(struct weston_output *base) nvnc_fb_unref(fb); } else { - weston_view_move_to_plane(view, primary); + weston_paint_node_move_to_plane(pnode, primary); } topmost = false; diff --git a/libweston/compositor.c b/libweston/compositor.c index 72f6b933a..a6f3fddb0 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -181,6 +181,8 @@ paint_node_update_early(struct weston_paint_node *pnode) static void paint_node_update_late(struct weston_paint_node *pnode) { + bool plane_dirty = pnode->status & PAINT_NODE_PLANE_DIRTY; + /* Even if our geometry didn't change, our visible region may * have been updated by some other node changing. Keep the * visible region up to date. @@ -189,7 +191,15 @@ paint_node_update_late(struct weston_paint_node *pnode) &pnode->view->visible, &pnode->output->region); - pnode->status &= ~(PAINT_NODE_VISIBILITY_DIRTY); + if (plane_dirty) { + assert(pnode->plane_next); + + pnode->plane = pnode->plane_next; + pnode->plane_next = NULL; + } + + pnode->status &= ~(PAINT_NODE_VISIBILITY_DIRTY | + PAINT_NODE_PLANE_DIRTY); /* Nothing should be able to flip "early" bits between * the early and late updates. @@ -240,7 +250,10 @@ weston_paint_node_create(struct weston_surface *surface, pixman_region32_init(&pnode->visible); pixman_region32_copy(&pnode->visible, &view->visible); - pnode->status = PAINT_NODE_ALL_DIRTY; + pnode->plane = &pnode->surface->compositor->primary_plane; + pnode->plane_next = NULL; + + pnode->status = PAINT_NODE_ALL_DIRTY & ~PAINT_NODE_PLANE_DIRTY; return pnode; } @@ -503,7 +516,6 @@ weston_view_create_internal(struct weston_surface *surface) return NULL; view->surface = surface; - view->plane = &surface->compositor->primary_plane; /* Assign to surface */ wl_list_insert(&surface->views, &view->surface_link); @@ -984,15 +996,20 @@ weston_view_buffer_to_output_matrix(const struct weston_view *view, } WL_EXPORT void -weston_view_move_to_plane(struct weston_view *view, - struct weston_plane *plane) +weston_paint_node_move_to_plane(struct weston_paint_node *pnode, + struct weston_plane *plane) { - if (view->plane == plane) + assert(plane); + + if (pnode->plane == plane) return; - weston_view_damage_below(view); - view->plane = plane; - weston_surface_damage(view->surface); + weston_view_damage_below(pnode->view); + pnode->plane_next = plane; + weston_surface_damage(pnode->view->surface); + + pnode->status |= PAINT_NODE_PLANE_DIRTY | + PAINT_NODE_VISIBILITY_DIRTY; } /** Inflict damage on the plane where the view is visible. @@ -1014,14 +1031,18 @@ weston_view_move_to_plane(struct weston_view *view, WL_EXPORT void weston_view_damage_below(struct weston_view *view) { + struct weston_paint_node *pnode; pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_subtract(&damage, &view->transform.boundingbox, &view->clip); - if (view->plane) - pixman_region32_union(&view->plane->damage, - &view->plane->damage, &damage); + wl_list_for_each(pnode, &view->paint_node_list, view_link) { + assert(pnode->plane); + + pixman_region32_union(&pnode->plane->damage, + &pnode->plane->damage, &damage); + } pixman_region32_fini(&damage); weston_view_schedule_repaint(view); } @@ -2242,7 +2263,6 @@ weston_view_unmap(struct weston_view *view) weston_view_damage_below(view); weston_view_set_output(view, NULL); - view->plane = NULL; view->is_mapped = false; weston_layer_entry_remove(&view->layer_link); wl_list_remove(&view->link); @@ -2942,6 +2962,7 @@ surface_flush_damage(struct weston_surface *surface, struct weston_output *outpu static void view_accumulate_damage(struct weston_view *view) { + struct weston_paint_node *pnode; pixman_region32_t damage; assert(!view->transform.dirty); @@ -2960,8 +2981,11 @@ view_accumulate_damage(struct weston_view *view) } pixman_region32_intersect(&damage, &damage, &view->visible); - pixman_region32_union(&view->plane->damage, - &view->plane->damage, &damage); + + wl_list_for_each(pnode, &view->paint_node_list, view_link) { + pixman_region32_union(&pnode->plane->damage, + &pnode->plane->damage, &damage); + } pixman_region32_fini(&damage); } @@ -2995,7 +3019,7 @@ output_update_visibility(struct weston_output *output) wl_list_for_each(pnode, &output->paint_node_z_order_list, z_order_link) { - if (pnode->view->plane != plane) + if (pnode->plane != plane) continue; view_update_clip_and_visible(pnode->view, &opaque); @@ -3018,7 +3042,7 @@ output_accumulate_damage(struct weston_output *output) wl_list_for_each(plane, &ec->plane_list, link) { wl_list_for_each(pnode, &output->paint_node_z_order_list, z_order_link) { - if (pnode->view->plane != plane) + if (pnode->plane != plane) continue; view_accumulate_damage(pnode->view); @@ -3300,7 +3324,7 @@ weston_output_repaint(struct weston_output *output) } else { wl_list_for_each(pnode, &output->paint_node_z_order_list, z_order_link) { - weston_view_move_to_plane(pnode->view, &ec->primary_plane); + weston_paint_node_move_to_plane(pnode, &ec->primary_plane); pnode->view->psf_flags = 0; } } @@ -5658,18 +5682,24 @@ weston_plane_init(struct weston_plane *plane, struct weston_compositor *ec) WL_EXPORT void weston_plane_release(struct weston_plane *plane) { - struct weston_view *view; + struct weston_output *output; pixman_region32_fini(&plane->damage); pixman_region32_fini(&plane->clip); - /* - * Can't use paint node list here, weston_plane is not specific to an - * output. - */ - wl_list_for_each(view, &plane->compositor->view_list, link) { - if (view->plane == plane) - view->plane = NULL; + wl_list_for_each(output, &plane->compositor->output_list, link) { + struct weston_paint_node *node; + + wl_list_for_each(node, &output->paint_node_z_order_list, + z_order_link) { + if (node->plane != plane) + continue; + + node->plane = NULL; + node->plane_next = &output->compositor->primary_plane; + node->status |= PAINT_NODE_PLANE_DIRTY | + PAINT_NODE_VISIBILITY_DIRTY; + } } wl_list_remove(&plane->link); diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index 5b303c8bc..79610b9be 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -418,8 +418,8 @@ weston_view_takes_input_at_point(struct weston_view *view, struct weston_coord_surface surf_pos); void -weston_view_move_to_plane(struct weston_view *view, - struct weston_plane *plane); +weston_paint_node_move_to_plane(struct weston_paint_node *pnode, + struct weston_plane *plane); void weston_view_buffer_to_output_matrix(const struct weston_view *view, const struct weston_output *output, @@ -509,7 +509,8 @@ enum paint_node_status { PAINT_NODE_OUTPUT_DIRTY = 1 << 0, PAINT_NODE_VIEW_DIRTY = 1 << 1, PAINT_NODE_VISIBILITY_DIRTY = 1 << 2, - PAINT_NODE_ALL_DIRTY = (1 << 3) - 1, + PAINT_NODE_PLANE_DIRTY = 1 << 3, + PAINT_NODE_ALL_DIRTY = (1 << 4) - 1, }; /** @@ -546,6 +547,8 @@ struct weston_paint_node { struct wl_list z_order_link; pixman_region32_t visible; + struct weston_plane *plane; + struct weston_plane *plane_next; struct weston_surface_color_transform surf_xform; bool surf_xform_valid; diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index fec1e9637..46e37d2f9 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -550,7 +550,7 @@ repaint_surfaces(struct weston_output *output, pixman_region32_t *damage) wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list, z_order_link) { - if (pnode->view->plane == &compositor->primary_plane) + if (pnode->plane == &compositor->primary_plane) draw_paint_node(pnode, damage); } } diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 6caf36cbf..ef0a5edc9 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -1338,7 +1338,7 @@ repaint_views(struct weston_output *output, pixman_region32_t *damage) wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list, z_order_link) { - if (pnode->view->plane == &compositor->primary_plane) + if (pnode->plane == &compositor->primary_plane) draw_paint_node(pnode, damage); } @@ -1365,7 +1365,7 @@ update_buffer_release_fences(struct weston_compositor *compositor, struct weston_buffer_release *buffer_release; int fence_fd; - if (view->plane != &compositor->primary_plane) + if (pnode->plane != &compositor->primary_plane) continue; gs = get_surface_state(view->surface); @@ -1861,7 +1861,7 @@ gl_renderer_repaint_output(struct weston_output *output, * which surfaces were used in this output repaint. */ wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list, z_order_link) { - if (pnode->view->plane == &compositor->primary_plane) { + if (pnode->plane == &compositor->primary_plane) { struct gl_surface_state *gs = get_surface_state(pnode->view->surface); gs->used_in_output_repaint = false; @@ -2075,7 +2075,7 @@ gl_renderer_flush_damage(struct weston_surface *surface, &surface->compositor->test_data.test_quirks; struct gl_surface_state *gs = get_surface_state(surface); struct gl_buffer_state *gb = gs->buffer; - struct weston_view *view; + struct weston_paint_node *pnode; bool texture_used; pixman_box32_t *rectangles; uint8_t *data; @@ -2098,8 +2098,8 @@ gl_renderer_flush_damage(struct weston_surface *surface, * migrates back to the primary plane. */ texture_used = false; - wl_list_for_each(view, &surface->views, surface_link) { - if (view->plane == &surface->compositor->primary_plane) { + wl_list_for_each(pnode, &surface->paint_node_list, surface_link) { + if (pnode->plane == &surface->compositor->primary_plane) { texture_used = true; break; }