[PATCH 9/9] improve hotplug remove a output in clone mode

Xiong Zhang xiong.y.zhang at intel.com
Tue Sep 17 20:51:04 PDT 2013


primary output is A, clone output is B
 first situation: if the event sequence is A's flip event, A's remove event,
 B's flip event. Then in the B's flip event handler, because A is destroied,
 B can't get a correct primary output A to release fb. So A's remove event
 must wait B's flip event.
second situation: A's repaint requeste, A and B will do page flip. Before
 B's page flip finish event, B's destroy event arrived and free(b), then B's
 page flip event arrived, Segment fault occur in B's page flip handler.

Add a drm_output->destroy_pending to handle above situation.

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 src/compositor-drm.c | 51 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 3594a1d..2c97a8a 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -147,6 +147,7 @@ struct drm_output {
 
 	int vblank_pending;
 	int page_flip_pending;
+	int destroy_pending;
 
 	struct gbm_surface *surface;
 	struct gbm_bo *cursor_bo[2];
@@ -643,6 +644,7 @@ drm_output_repaint(struct weston_output *output_base,
 					weston_log("queueing pageflip failed: %m\n");
 					return;
 				}
+				clone_output->page_flip_pending = 1;
 				compositor->flip_counter++;
 			}
 		}
@@ -773,20 +775,13 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
 }
 
 static void
-page_flip_handler(int fd, unsigned int frame,
-		  unsigned int sec, unsigned int usec, void *data)
+drm_output_destroy(struct weston_output *output_base);
+
+static void
+primary_output_page_flip_handler(struct drm_output *output,
+		unsigned int sec, unsigned int usec)
 {
-	struct drm_output *output = (struct drm_output *) data;
 	uint32_t msecs;
-	struct drm_compositor *c = (struct drm_compositor *)output->base.compositor;
-
-	if ((--c->flip_counter != 0) &&
-		(c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE))
-		return;
-
-	if ((c->base.multiscreen_mode == WESTON_MULTISCREEN_CLONE) &&
-		(&output->base != c->base.primary_output))
-		output = (struct drm_output *)c->base.primary_output;
 
 	/* We don't set page_flip_pending on start_repaint_loop, in that case
 	 * we just want to page flip to the current buffer to get an accurate
@@ -799,12 +794,37 @@ page_flip_handler(int fd, unsigned int frame,
 
 	output->page_flip_pending = 0;
 
-	if (!output->vblank_pending) {
+	if (output->destroy_pending)
+		drm_output_destroy(&output->base);
+	else if (!output->vblank_pending) {
 		msecs = sec * 1000 + usec / 1000;
 		weston_output_finish_frame(&output->base, msecs);
 	}
 }
 
+static void
+page_flip_handler(int fd, unsigned int frame,
+		  unsigned int sec, unsigned int usec, void *data)
+{
+	struct drm_output *output = (struct drm_output *) data;
+	struct drm_compositor *c = (struct drm_compositor *)output->base.compositor;
+
+	--c->flip_counter;
+	if (c->base.multiscreen_mode == WESTON_MULTISCREEN_EXTEND)
+		primary_output_page_flip_handler(output, sec, usec);
+	else {
+		if (&output->base != c->base.primary_output) {
+			output->page_flip_pending = 0;
+			if (output->destroy_pending) {
+				drm_output_destroy(&output->base);
+			}
+			output = (struct drm_output *)c->base.primary_output;
+		}
+		if (c->flip_counter == 0)
+			primary_output_page_flip_handler(output, sec, usec);
+	}
+}
+
 static uint32_t
 drm_output_check_sprite_format(struct drm_sprite *s,
 			       struct weston_surface *es, struct gbm_bo *bo)
@@ -1357,6 +1377,11 @@ drm_output_destroy(struct weston_output *output_base)
 		(struct drm_compositor *) output->base.compositor;
 	drmModeCrtcPtr origcrtc = output->original_crtc;
 
+	if (output->page_flip_pending) {
+		output->destroy_pending = 1;
+		return;
+	}
+
 	if (output->backlight)
 		backlight_destroy(output->backlight);
 
-- 
1.8.3.2



More information about the wayland-devel mailing list