xf86-video-intel: 2 commits - src/sna/sna_dri2.c src/sna/sna_driver.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 26 01:32:28 PDT 2014


 src/sna/sna.h        |    2 
 src/sna/sna_dri2.c   |  140 ++++++++++++++++++++++++++++++++++++---------------
 src/sna/sna_driver.c |   83 ++++++++++++++----------------
 3 files changed, 140 insertions(+), 85 deletions(-)

New commits:
commit c5c7dd24a55f04322d5eec10dc4352d8a8e92b1e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 26 09:25:06 2014 +0100

    sna: Remove scare quotes from hotplug detection "enabled"
    
    Tidy up the log message by improving its formatting, and making it more
    accurate.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index e0995ce..c57832b 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -752,8 +752,7 @@ sna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
 static void
 sna_handle_uevents(int fd, void *closure)
 {
-	ScrnInfoPtr scrn = closure;
-	struct sna *sna = to_sna(scrn);
+	struct sna *sna = closure;
 	struct udev_device *dev;
 	const char *str;
 	struct stat s;
@@ -773,9 +772,11 @@ sna_handle_uevents(int fd, void *closure)
 
 	str = udev_device_get_property_value(dev, "HOTPLUG");
 	if (str && atoi(str) == 1) {
-		DBG(("%s: hotplug event (vtSema?=%d)\n",
-		     __FUNCTION__, sna->scrn->vtSema));
-		if (sna->scrn->vtSema) {
+		ScrnInfoPtr scrn = sna->scrn;
+
+		DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema));
+
+		if (scrn->vtSema) {
 			sna_mode_discover(sna);
 			sna_mode_check(sna);
 			RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
@@ -787,12 +788,10 @@ sna_handle_uevents(int fd, void *closure)
 }
 
 static void
-sna_uevent_init(ScrnInfoPtr scrn)
+sna_uevent_init(struct sna *sna)
 {
-	struct sna *sna = to_sna(scrn);
 	struct udev *u;
 	struct udev_monitor *mon;
-	Bool hotplug;
 	MessageType from = X_CONFIG;
 
 	if (sna->flags & SNA_IS_HOSTED)
@@ -804,51 +803,47 @@ sna_uevent_init(ScrnInfoPtr scrn)
 	 * RR hotplug events is then verboten.
 	 */
 	if (!dixPrivateKeyRegistered(rrPrivKey))
-		return;
+		goto out;
 
-	if (!xf86GetOptValBool(sna->Options, OPTION_HOTPLUG, &hotplug))
-		from = X_DEFAULT, hotplug = TRUE;
-	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
-			hotplug ? "enabled" : "disabled");
-	if (!hotplug)
-		return;
-
-	u = udev_new();
+	u = NULL;
+	if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE))
+		u = udev_new();
 	if (!u)
-		return;
+		goto out;
+
+	from = X_DEFAULT;
 
 	mon = udev_monitor_new_from_netlink(u, "udev");
-	if (!mon) {
-		udev_unref(u);
-		return;
-	}
+	if (!mon)
+		goto err_dev;
 
-	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
-				"drm", "drm_minor") < 0 ||
-	    udev_monitor_enable_receiving(mon) < 0)
-	{
-		udev_monitor_unref(mon);
-		udev_unref(u);
-		return;
-	}
+	if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0)
+		goto err_monitor;
+
+	if (udev_monitor_enable_receiving(mon) < 0)
+		goto err_monitor;
 
 	sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
-						    sna_handle_uevents, scrn);
-	if (!sna->uevent_handler) {
-		udev_monitor_unref(mon);
-		udev_unref(u);
-		return;
-	}
+						    sna_handle_uevents, sna);
+	if (!sna->uevent_handler)
+		goto err_monitor;
 
 	sna->uevent_monitor = mon;
-
-	DBG(("%s: installed uvent handler\n", __FUNCTION__));
+out:
+	xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n",
+		   sna->uevent_monitor ? "enabled" : "disabled");
+	return;
+
+err_monitor:
+	udev_monitor_unref(mon);
+err_dev:
+	udev_unref(u);
+	goto out;
 }
 
 static void
-sna_uevent_fini(ScrnInfoPtr scrn)
+sna_uevent_fini(struct sna *sna)
 {
-	struct sna *sna = to_sna(scrn);
 	struct udev *u;
 
 	if (sna->uevent_handler == NULL)
@@ -866,8 +861,8 @@ sna_uevent_fini(ScrnInfoPtr scrn)
 	DBG(("%s: removed uvent handler\n", __FUNCTION__));
 }
 #else
-static void sna_uevent_init(ScrnInfoPtr scrn) { }
-static void sna_uevent_fini(ScrnInfoPtr scrn) { }
+static void sna_uevent_init(struct sna *sna) { }
+static void sna_uevent_fini(struct sna *sna) { }
 #endif /* HAVE_UDEV */
 
 static void sna_leave_vt(VT_FUNC_ARGS_DECL)
@@ -892,7 +887,7 @@ static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
 
 	/* XXX Note that we will leak kernel resources if !vtSema */
 
-	sna_uevent_fini(scrn);
+	sna_uevent_fini(sna);
 	sna_mode_close(sna);
 
 	if (sna->present.open) {
@@ -1142,7 +1137,7 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
 
 	sna->suspended = FALSE;
 
-	sna_uevent_init(scrn);
+	sna_uevent_init(sna);
 
 	return TRUE;
 }
commit 2e8c09f3fe468abba9c307ba3d7b2d22908e1172
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 25 22:19:23 2014 +0100

    sna/dri2: Hook into ClientGone callback to clear dangling references
    
    As the Window may exist for multiple Clients, we cannot rely on the
    destruction of the Window decoupling all outstanding events and
    preventing chasing a stale Client pointer.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80157
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 8640f2f..7b89f8c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -114,6 +114,7 @@ struct sna_cursor;
 struct sna_crtc;
 
 struct sna_client {
+	struct list events;
 	int is_compositor; /* only 4 bits used */
 };
 
@@ -334,6 +335,7 @@ struct sna {
 
 #if HAVE_DRI2
 		void *flip_pending;
+		unsigned client_count;
 #endif
 	} dri2;
 
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 9f8b8ee..f24086a 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -123,6 +123,7 @@ struct sna_dri2_event {
 	struct sna_dri2_event *chain;
 
 	struct list cache;
+	struct list link;
 
 	int mode;
 };
@@ -1218,8 +1219,93 @@ sna_dri2_remove_event(WindowPtr win, struct sna_dri2_event *info)
 	chain->chain = info->chain;
 }
 
+static void
+sna_dri2_event_free(struct sna *sna,
+		    DrawablePtr draw,
+		    struct sna_dri2_event *info)
+{
+	DBG(("%s(draw?=%d)\n", __FUNCTION__, draw != NULL));
+
+	if (draw && draw->type == DRAWABLE_WINDOW)
+		sna_dri2_remove_event((WindowPtr)draw, info);
+	_sna_dri2_destroy_buffer(sna, info->front);
+	_sna_dri2_destroy_buffer(sna, info->back);
+
+	while (!list_is_empty(&info->cache)) {
+		struct dri_bo *c;
+
+		c = list_first_entry(&info->cache, struct dri_bo, link);
+		list_del(&c->link);
+
+		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
+		if (c->bo)
+			kgem_bo_destroy(&sna->kgem, c->bo);
+
+		free(c);
+	}
+
+	if (info->bo) {
+		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
+		kgem_bo_destroy(&sna->kgem, info->bo);
+	}
+
+	_list_del(&info->link);
+	free(info);
+}
+
+static void
+sna_dri2_client_gone(CallbackListPtr *list, void *closure, void *data)
+{
+	NewClientInfoRec *clientinfo = data;
+	ClientPtr client = clientinfo->client;
+	struct sna_client *priv = sna_client(client);
+	struct sna *sna = closure;
+
+	if (priv->events.next == NULL)
+		return;
+
+	if (client->clientState != ClientStateGone)
+		return;
+
+	DBG(("%s()\n", __FUNCTION__));
+
+	while (!list_is_empty(&priv->events)) {
+		struct sna_dri2_event *event;
+
+		event = list_first_entry(&priv->events, struct sna_dri2_event, link);
+		assert(event->client == client);
+
+		if (event->queued) {
+			event->client = NULL;
+			event->draw = NULL;
+			list_del(&event->link);
+		} else
+			sna_dri2_event_free(sna, event->draw, event);
+	}
+
+	if (--sna->dri2.client_count == 0)
+		DeleteCallback(&ClientStateCallback, sna_dri2_client_gone, sna);
+}
+
+static bool add_event_to_client(struct sna_dri2_event *info, struct sna *sna, ClientPtr client)
+{
+	struct sna_client *priv = sna_client(client);
+
+	if (priv->events.next == NULL) {
+		if (sna->dri2.client_count++ == 0 &&
+		    !AddCallback(&ClientStateCallback, sna_dri2_client_gone, sna))
+			return false;
+
+		list_init(&priv->events);
+	}
+
+	list_add(&info->link, &priv->events);
+	info->client = client;
+	return true;
+}
+
 static struct sna_dri2_event *
-sna_dri2_add_event(DrawablePtr draw, ClientPtr client)
+sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
 {
 	struct dri2_window *priv;
 	struct sna_dri2_event *info, *chain;
@@ -1238,10 +1324,14 @@ sna_dri2_add_event(DrawablePtr draw, ClientPtr client)
 
 	list_init(&info->cache);
 	info->draw = draw;
-	info->client = client;
 	info->crtc = priv->crtc;
 	info->pipe = sna_crtc_to_pipe(priv->crtc);
 
+	if (!add_event_to_client(info, sna, client)) {
+		free(info);
+		return NULL;
+	}
+
 	assert(priv->chain != info);
 
 	if (priv->chain == NULL) {
@@ -1258,39 +1348,6 @@ sna_dri2_add_event(DrawablePtr draw, ClientPtr client)
 	return info;
 }
 
-static void
-sna_dri2_event_free(struct sna *sna,
-		    DrawablePtr draw,
-		    struct sna_dri2_event *info)
-{
-	DBG(("%s\n", __FUNCTION__));
-
-	if (draw && draw->type == DRAWABLE_WINDOW)
-		sna_dri2_remove_event((WindowPtr)draw, info);
-	_sna_dri2_destroy_buffer(sna, info->front);
-	_sna_dri2_destroy_buffer(sna, info->back);
-
-	while (!list_is_empty(&info->cache)) {
-		struct dri_bo *c;
-
-		c = list_first_entry(&info->cache, struct dri_bo, link);
-		list_del(&c->link);
-
-		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
-		if (c->bo)
-			kgem_bo_destroy(&sna->kgem, c->bo);
-
-		free(c);
-	}
-
-	if (info->bo) {
-		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
-		kgem_bo_destroy(&sna->kgem, info->bo);
-	}
-
-	free(info);
-}
-
 void sna_dri2_destroy_window(WindowPtr win)
 {
 	struct sna *sna;
@@ -2022,6 +2079,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 		break;
 
 	case WAITMSC:
+		assert(info->client);
 		DRI2WaitMSCComplete(info->client, draw, msc,
 				    event->tv_sec, event->tv_usec);
 		break;
@@ -2377,7 +2435,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 			}
 		}
 
-		info = sna_dri2_add_event(draw, client);
+		info = sna_dri2_add_event(sna, draw, client);
 		if (info == NULL)
 			return false;
 
@@ -2423,7 +2481,7 @@ out:
 		return true;
 	}
 
-	info = sna_dri2_add_event(draw, client);
+	info = sna_dri2_add_event(sna, draw, client);
 	if (info == NULL)
 		return false;
 
@@ -2507,7 +2565,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 	if (sync) {
 		struct sna_dri2_event *info;
 
-		info = sna_dri2_add_event(draw, client);
+		info = sna_dri2_add_event(sna, draw, client);
 		if (!info)
 			goto complete;
 
@@ -2568,7 +2626,7 @@ sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc
 	if (sync) {
 		struct sna_dri2_event *info;
 
-		info = sna_dri2_add_event(draw, client);
+		info = sna_dri2_add_event(sna, draw, client);
 		if (!info)
 			goto complete;
 
@@ -2725,7 +2783,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	VG_CLEAR(vbl);
 
-	info = sna_dri2_add_event(draw, client);
+	info = sna_dri2_add_event(sna, draw, client);
 	if (!info)
 		goto blit;
 
@@ -2893,7 +2951,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
 	if (divisor == 0 && current_msc >= target_msc)
 		goto out_complete;
 
-	info = sna_dri2_add_event(draw, client);
+	info = sna_dri2_add_event(sna, draw, client);
 	if (!info)
 		goto out_complete;
 


More information about the xorg-commit mailing list