diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 79f8444b..1be05f02 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1,6 +1,6 @@ /* * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2012, 2017, 2018 Collabora, Ltd. + * Copyright © 2012, 2017, 2018, 2021 Collabora, Ltd. * Copyright © 2017, 2018 General Electric Company * * Permission is hereby granted, free of charge, to any person obtaining @@ -280,6 +280,9 @@ struct weston_output { struct wl_list link; struct weston_compositor *compositor; + /* struct weston_paint_node::output_link */ + struct wl_list paint_node_list; + /** From global to output buffer coordinates. */ struct weston_matrix matrix; /** From output buffer to global coordinates. */ @@ -1268,6 +1271,9 @@ struct weston_view { struct wl_list surface_link; struct wl_signal destroy_signal; + /* struct weston_paint_node::view_link */ + struct wl_list paint_node_list; + struct wl_list link; /* weston_compositor::view_list */ struct weston_layer_entry layer_link; /* part of geometry */ struct weston_plane *plane; @@ -1427,6 +1433,9 @@ struct weston_surface { struct weston_compositor *compositor; struct wl_signal commit_signal; + /* struct weston_paint_node::surface_link */ + struct wl_list paint_node_list; + /** Damage in local coordinates from the client, for tex upload. */ pixman_region32_t damage; diff --git a/libweston/compositor.c b/libweston/compositor.c index 3a96dea3..cacded7a 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2012-2018 Collabora, Ltd. + * Copyright © 2012-2018, 2021 Collabora, Ltd. * Copyright © 2017, 2018 General Electric Company * * Permission is hereby granted, free of charge, to any person obtaining @@ -93,11 +93,47 @@ weston_output_transform_scale_init(struct weston_output *output, uint32_t transform, uint32_t scale); static void -weston_compositor_build_view_list(struct weston_compositor *compositor); +weston_compositor_build_view_list(struct weston_compositor *compositor, + struct weston_output *output); static char * weston_output_create_heads_string(struct weston_output *output); +static struct weston_paint_node * +weston_paint_node_create(struct weston_surface *surface, + struct weston_view *view, + struct weston_output *output) +{ + struct weston_paint_node *pnode; + + assert(view->surface == surface); + + pnode = zalloc(sizeof *pnode); + if (!pnode) + return NULL; + + pnode->surface = surface; + wl_list_insert(&surface->paint_node_list, &pnode->surface_link); + + pnode->view = view; + wl_list_insert(&view->paint_node_list, &pnode->view_link); + + pnode->output = output; + wl_list_insert(&output->paint_node_list, &pnode->output_link); + + return pnode; +} + +static void +weston_paint_node_destroy(struct weston_paint_node *pnode) +{ + assert(pnode->view->surface == pnode->surface); + wl_list_remove(&pnode->surface_link); + wl_list_remove(&pnode->view_link); + wl_list_remove(&pnode->output_link); + free(pnode); +} + /** Send wl_output events for mode and scale changes * * \param head Send on all resources bound to this head. @@ -336,6 +372,7 @@ weston_view_create(struct weston_surface *surface) wl_signal_init(&view->destroy_signal); wl_list_init(&view->link); wl_list_init(&view->layer_link.link); + wl_list_init(&view->paint_node_list); pixman_region32_init(&view->clip); @@ -553,6 +590,7 @@ weston_surface_create(struct weston_compositor *compositor) region_init_infinite(&surface->input); wl_list_init(&surface->views); + wl_list_init(&surface->paint_node_list); wl_list_init(&surface->frame_callback_list); wl_list_init(&surface->feedback_list); @@ -1951,6 +1989,23 @@ weston_view_matches_output_entirely(struct weston_view *ev, return true; } +/** Find paint node for the given view and output + */ +WL_EXPORT struct weston_paint_node * +weston_view_find_paint_node(struct weston_view *view, + struct weston_output *output) +{ + struct weston_paint_node *pnode; + + wl_list_for_each(pnode, &view->paint_node_list, view_link) { + assert(pnode->surface == view->surface); + if (pnode->output == output) + return pnode; + } + + return NULL; +} + /* Check if a surface has a view assigned to it * * The indicator is set manually when mapping @@ -2192,15 +2247,21 @@ weston_surface_reset_pending_buffer(struct weston_surface *surface) WL_EXPORT void weston_view_destroy(struct weston_view *view) { + struct weston_paint_node *pnode, *pntmp; + wl_signal_emit(&view->destroy_signal, view); assert(wl_list_empty(&view->geometry.child_list)); if (weston_view_is_mapped(view)) { weston_view_unmap(view); - weston_compositor_build_view_list(view->surface->compositor); + weston_compositor_build_view_list(view->surface->compositor, + NULL); } + wl_list_for_each_safe(pnode, pntmp, &view->paint_node_list, view_link) + weston_paint_node_destroy(pnode); + wl_list_remove(&view->link); weston_layer_entry_remove(&view->layer_link); @@ -2223,6 +2284,7 @@ weston_surface_destroy(struct weston_surface *surface) struct weston_frame_callback *cb, *next; struct weston_view *ev, *nv; struct weston_pointer_constraint *constraint, *next_constraint; + struct weston_paint_node *pnode, *pntmp; if (--surface->ref_count > 0) return; @@ -2237,6 +2299,11 @@ weston_surface_destroy(struct weston_surface *surface) wl_list_for_each_safe(ev, nv, &surface->views, surface_link) weston_view_destroy(ev); + wl_list_for_each_safe(pnode, pntmp, + &surface->paint_node_list, surface_link) { + weston_paint_node_destroy(pnode); + } + weston_surface_state_fini(&surface->pending); weston_buffer_reference(&surface->buffer_ref, NULL); @@ -2594,10 +2661,26 @@ surface_free_unused_subsurface_views(struct weston_surface *surface) } } +static struct weston_paint_node * +view_ensure_paint_node(struct weston_view *view, struct weston_output *output) +{ + struct weston_paint_node *pnode; + + if (!output) + return NULL; + + pnode = weston_view_find_paint_node(view, output); + if (pnode) + return pnode; + + return weston_paint_node_create(view->surface, view, output); +} + static void view_list_add_subsurface_view(struct weston_compositor *compositor, struct weston_subsurface *sub, - struct weston_view *parent) + struct weston_view *parent, + struct weston_output *output) { struct weston_subsurface *child; struct weston_view *view = NULL, *iv; @@ -2627,6 +2710,7 @@ view_list_add_subsurface_view(struct weston_compositor *compositor, view->parent_view = parent; weston_view_update_transform(view); view->is_mapped = true; + view_ensure_paint_node(view, output); if (wl_list_empty(&sub->surface->subsurface_list)) { wl_list_insert(compositor->view_list.prev, &view->link); @@ -2637,7 +2721,7 @@ view_list_add_subsurface_view(struct weston_compositor *compositor, if (child->surface == sub->surface) wl_list_insert(compositor->view_list.prev, &view->link); else - view_list_add_subsurface_view(compositor, child, view); + view_list_add_subsurface_view(compositor, child, view, output); } } @@ -2649,11 +2733,13 @@ view_list_add_subsurface_view(struct weston_compositor *compositor, */ static void view_list_add(struct weston_compositor *compositor, - struct weston_view *view) + struct weston_view *view, + struct weston_output *output) { struct weston_subsurface *sub; weston_view_update_transform(view); + view_ensure_paint_node(view, output); if (wl_list_empty(&view->surface->subsurface_list)) { wl_list_insert(compositor->view_list.prev, &view->link); @@ -2664,12 +2750,13 @@ view_list_add(struct weston_compositor *compositor, if (sub->surface == view->surface) wl_list_insert(compositor->view_list.prev, &view->link); else - view_list_add_subsurface_view(compositor, sub, view); + view_list_add_subsurface_view(compositor, sub, view, output); } } static void -weston_compositor_build_view_list(struct weston_compositor *compositor) +weston_compositor_build_view_list(struct weston_compositor *compositor, + struct weston_output *output) { struct weston_view *view, *tmp; struct weston_layer *layer; @@ -2684,7 +2771,7 @@ weston_compositor_build_view_list(struct weston_compositor *compositor) wl_list_for_each(layer, &compositor->layer_list, link) { wl_list_for_each(view, &layer->view_list.link, layer_link.link) { - view_list_add(compositor, view); + view_list_add(compositor, view, output); } } @@ -2737,7 +2824,7 @@ weston_output_repaint(struct weston_output *output, void *repaint_data) TL_POINT(ec, "core_repaint_begin", TLP_OUTPUT(output), TLP_END); /* Rebuild the surface list and update surface transforms up front. */ - weston_compositor_build_view_list(ec); + weston_compositor_build_view_list(ec, output); /* Find the highest protection desired for an output */ wl_list_for_each(ev, &ec->view_list, link) { @@ -6102,6 +6189,8 @@ weston_output_transform_coordinate(struct weston_output *output, * * The following happens: * + * - Destroys all paint nodes related to the output. + * * - The output assignments of all views in the current scenegraph are * recomputed. * @@ -6127,12 +6216,18 @@ static void weston_compositor_remove_output(struct weston_output *output) { struct weston_compositor *compositor = output->compositor; + struct weston_paint_node *pnode, *pntmp; struct weston_view *view; struct weston_head *head; assert(output->destroying); assert(output->enabled); + wl_list_for_each_safe(pnode, pntmp, + &output->paint_node_list, output_link) { + weston_paint_node_destroy(pnode); + } + wl_list_for_each(view, &compositor->view_list, link) { if (view->output_mask & (1u << output->id)) weston_view_assign_output(view); @@ -6483,6 +6578,7 @@ weston_output_enable(struct weston_output *output) wl_list_init(&output->animation_list); wl_list_init(&output->feedback_list); + wl_list_init(&output->paint_node_list); /* Enable the output (set up the crtc or create a * window representing the output, set up the @@ -6645,6 +6741,8 @@ weston_output_release(struct weston_output *output) if (output->enabled) weston_compositor_remove_output(output); + assert(wl_list_empty(&output->paint_node_list)); + pixman_region32_fini(&output->region); wl_list_remove(&output->link); diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index 6921d7d6..3a895c77 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -1,7 +1,7 @@ /* * Copyright © 2008-2011 Kristian Høgsberg * Copyright © 2017, 2018 General Electric Company - * Copyright © 2012, 2017-2019 Collabora, Ltd. + * Copyright © 2012, 2017-2019, 2021 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -40,6 +40,7 @@ * features should either provide their own (internal) header or use this one. */ +#include /* weston_buffer */ @@ -391,6 +392,29 @@ const uint64_t * weston_drm_format_get_modifiers(const struct weston_drm_format *format, unsigned int *count_out); +/** + * paint node + * + * A generic data structure unique for surface-view-output combination. + */ +struct weston_paint_node { + /* struct weston_surface::paint_node_list */ + struct wl_list surface_link; + struct weston_surface *surface; + + /* struct weston_view::paint_node_list */ + struct wl_list view_link; + struct weston_view *view; + + /* struct weston_output::paint_node_list */ + struct wl_list output_link; + struct weston_output *output; +}; + +struct weston_paint_node * +weston_view_find_paint_node(struct weston_view *view, + struct weston_output *output); + /* others */ int wl_data_device_manager_init(struct wl_display *display);