[PATCH 2/2] compositor.c: restore surface->plane from destroyed plane to primary plane

Xiong Zhang xiong.y.zhang at intel.com
Fri Oct 11 08:43:08 CEST 2013


In drm backend, the plane pointer of cursor surface point to drm_output->cursor_plane.
when this output is removed, drm_output->cursor_plane is destroyed, but
cursor_surface->plane doesn't restored to primary plane. So once mouse move to this
cursor_surface and system will repaint this cursor_surface, segment fault will occure in
weston_surface_damage_below() function.

plane should track all the surfaces belonged to it, when plane is destroyed,
restroe surface on destroyed plane to primary plane.

bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69777

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 src/compositor-drm.c |  6 +++---
 src/compositor.c     | 22 ++++++++++++++++++++--
 src/compositor.h     |  5 ++++-
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index ffdec89..fc78360 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1105,8 +1105,8 @@ drm_output_destroy(struct weston_output *output_base)
 		gbm_surface_destroy(output->surface);
 	}
 
-	weston_plane_release(&output->fb_plane);
-	weston_plane_release(&output->cursor_plane);
+	weston_plane_release(&c->base, &output->fb_plane);
+	weston_plane_release(&c->base, &output->cursor_plane);
 
 	weston_output_destroy(&output->base);
 	wl_list_remove(&output->base.link);
@@ -2076,7 +2076,7 @@ destroy_sprites(struct drm_compositor *compositor)
 				0, 0, 0, 0, 0, 0, 0, 0);
 		drm_output_release_fb(output, sprite->current);
 		drm_output_release_fb(output, sprite->next);
-		weston_plane_release(&sprite->plane);
+		weston_plane_release(&compositor->base, &sprite->plane);
 		free(sprite);
 	}
 }
diff --git a/src/compositor.c b/src/compositor.c
index 376ddfd..f9f1957 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -362,6 +362,7 @@ weston_surface_create(struct weston_compositor *compositor)
 
 	wl_list_init(&surface->link);
 	wl_list_init(&surface->layer_link);
+	wl_list_init(&surface->plane_link);
 
 	surface->compositor = compositor;
 	surface->alpha = 1.0;
@@ -378,6 +379,7 @@ weston_surface_create(struct weston_compositor *compositor)
 	surface->pending.buffer_scale = surface->buffer_scale;
 	surface->output = NULL;
 	surface->plane = &compositor->primary_plane;
+	wl_list_insert(compositor->primary_plane.surface_list.prev, &surface->plane_link);
 	surface->pending.newly_attached = 0;
 
 	pixman_region32_init(&surface->damage);
@@ -566,7 +568,9 @@ weston_surface_move_to_plane(struct weston_surface *surface,
 		return;
 
 	weston_surface_damage_below(surface);
+	wl_list_remove(&surface->plane_link);
 	surface->plane = plane;
+	wl_list_insert(plane->surface_list.prev, &surface->plane_link);
 	weston_surface_damage(surface);
 }
 
@@ -1125,6 +1129,8 @@ weston_surface_destroy(struct weston_surface *surface)
 
 	weston_surface_set_transform_parent(surface, NULL);
 
+	wl_list_remove(&surface->plane_link);
+
 	free(surface);
 }
 
@@ -2614,14 +2620,26 @@ weston_plane_init(struct weston_plane *plane, int32_t x, int32_t y)
 	/* Init the link so that the call to wl_list_remove() when releasing
 	 * the plane without ever stacking doesn't lead to a crash */
 	wl_list_init(&plane->link);
+	wl_list_init(&plane->surface_list);
 }
 
 WL_EXPORT void
-weston_plane_release(struct weston_plane *plane)
+weston_plane_release(struct weston_compositor *ec,
+				struct weston_plane *plane)
 {
+	struct weston_surface *surface, *next;
+
 	pixman_region32_fini(&plane->damage);
 	pixman_region32_fini(&plane->clip);
 
+	if (plane != &ec->primary_plane) {
+		wl_list_for_each_safe(surface, next, &plane->surface_list, plane_link) {
+			wl_list_remove(&surface->plane_link);
+			surface->plane = &ec->primary_plane;
+			wl_list_insert(ec->primary_plane.surface_list.prev, &surface->plane_link);
+		}
+	}
+
 	wl_list_remove(&plane->link);
 }
 
@@ -3075,7 +3093,7 @@ weston_compositor_shutdown(struct weston_compositor *ec)
 	weston_binding_list_destroy_all(&ec->axis_binding_list);
 	weston_binding_list_destroy_all(&ec->debug_binding_list);
 
-	weston_plane_release(&ec->primary_plane);
+	weston_plane_release(ec, &ec->primary_plane);
 
 	wl_event_loop_destroy(ec->input_loop);
 
diff --git a/src/compositor.h b/src/compositor.h
index a19d966..a4cd4ca 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -508,6 +508,7 @@ struct weston_plane {
 	pixman_region32_t damage;
 	pixman_region32_t clip;
 	int32_t x, y;
+	struct wl_list surface_list;
 	struct wl_list link;
 };
 
@@ -724,6 +725,7 @@ struct weston_surface {
 	pixman_region32_t input;
 	struct wl_list link;
 	struct wl_list layer_link;
+	struct wl_list plane_link;
 	float alpha;                     /* part of geometry, see below */
 	struct weston_plane *plane;
 	int32_t ref_count;
@@ -929,7 +931,8 @@ weston_layer_init(struct weston_layer *layer, struct wl_list *below);
 void
 weston_plane_init(struct weston_plane *plane, int32_t x, int32_t y);
 void
-weston_plane_release(struct weston_plane *plane);
+weston_plane_release(struct weston_compositor *ec,
+			struct weston_plane *plane);
 
 void
 weston_compositor_stack_plane(struct weston_compositor *ec,
-- 
1.8.3.2



More information about the wayland-devel mailing list