diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2018-04-06 17:50:31 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2018-04-10 15:22:06 +0200 |
commit | ebe128ba8d79130d7107c79e9af2edc0195fc82c (patch) | |
tree | 5d497ce40260023042eee70c2de229c4c1a03e9d | |
parent | 98dfd5b8871596612db2a1dc8b5e886d01c86c50 (diff) | |
download | mutter-wip/carlosg/pending-state-leak-fix.tar.gz |
wayland: Plug surface pending state contents leakwip/carlosg/pending-state-leak-fix
When moving the pending state of an effectively synchronized subsurface
so it is applied together with the parent, perform a merge of the source
MetaWaylandPendingState into the destination one, instead of simply
overwriting the struct.
The other approach had 2 kind of leaks, one that would happen everytime
a wl_surface.commit happens on a sync subsurface (both surface/buffer
damage regions are leaked). The other more unlikely one would apply on
the rest of pending state data, happening whenever the compositor gets
>1 wl_surface.commit calls on the subsurface before the parent surface
gets its own.
The function has also been renamed to use the more descriptive "merge"
term.
Related: gnome-shell#64
-rw-r--r-- | src/wayland/meta-wayland-surface.c | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 05b99f8bb..87384cac0 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -439,36 +439,77 @@ pending_state_reset (MetaWaylandPendingState *state) } static void -move_pending_state (MetaWaylandPendingState *from, - MetaWaylandPendingState *to) -{ - if (from->buffer) - g_signal_handler_disconnect (from->buffer, from->buffer_destroy_handler_id); - - to->newly_attached = from->newly_attached; - to->buffer = from->buffer; - to->dx = from->dx; - to->dy = from->dy; - to->scale = from->scale; - to->surface_damage = from->surface_damage; - to->buffer_damage = from->buffer_damage; - to->input_region = from->input_region; - to->input_region_set = from->input_region_set; - to->opaque_region = from->opaque_region; - to->opaque_region_set = from->opaque_region_set; - to->new_geometry = from->new_geometry; - to->has_new_geometry = from->has_new_geometry; - to->has_new_min_size = from->has_new_min_size; - to->new_min_width = from->new_min_width; - to->new_min_height = from->new_min_height; - to->has_new_max_size = from->has_new_max_size; - to->new_max_width = from->new_max_width; - to->new_max_height = from->new_max_height; +merge_pending_state (MetaWaylandPendingState *from, + MetaWaylandPendingState *to) +{ + if (from->newly_attached) + { + if (to->buffer) + { + g_signal_handler_disconnect (to->buffer, to->buffer_destroy_handler_id); + to->buffer_destroy_handler_id = 0; + } + + if (from->buffer) + { + g_signal_handler_disconnect (from->buffer, from->buffer_destroy_handler_id); + from->buffer_destroy_handler_id = 0; + } + + to->newly_attached = TRUE; + to->buffer = from->buffer; + to->dx = from->dx; + to->dy = from->dy; + } wl_list_init (&to->frame_callback_list); wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list); - if (to->buffer) + cairo_region_union (to->surface_damage, from->surface_damage); + cairo_region_union (to->buffer_damage, from->buffer_damage); + + if (from->input_region_set) + { + if (to->input_region) + cairo_region_union (to->input_region, from->input_region); + else + to->input_region = cairo_region_reference (from->input_region); + to->input_region_set = TRUE; + } + + if (from->opaque_region_set) + { + if (to->opaque_region) + cairo_region_union (to->opaque_region, from->opaque_region); + else + to->opaque_region = cairo_region_reference (from->opaque_region); + to->opaque_region_set = TRUE; + } + + if (from->has_new_geometry) + { + to->new_geometry = from->new_geometry; + to->has_new_geometry = TRUE; + } + + if (from->has_new_min_size) + { + to->new_min_width = from->new_min_width; + to->new_min_height = from->new_min_height; + to->has_new_min_size = TRUE; + } + + if (from->has_new_max_size) + { + to->new_max_width = from->new_max_width; + to->new_max_height = from->new_max_height; + to->has_new_max_size = TRUE; + } + + if (from->scale > 0) + to->scale = from->scale; + + if (to->buffer && to->buffer_destroy_handler_id == 0) { to->buffer_destroy_handler_id = g_signal_connect (to->buffer, "resource-destroyed", @@ -716,7 +757,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) * surface is in effective desynchronized mode. */ if (meta_wayland_surface_is_effectively_synchronized (surface)) - move_pending_state (surface->pending, surface->sub.pending); + merge_pending_state (surface->pending, surface->sub.pending); else meta_wayland_surface_apply_pending_state (surface, surface->pending); } |