xf86-video-intel: 3 commits - src/intel_display.c src/intel_dri.c src/intel.h

Keith Packard keithp at kemper.freedesktop.org
Wed Mar 23 17:24:57 PDT 2011


 src/intel.h         |   26 ++++++-
 src/intel_display.c |   14 +--
 src/intel_dri.c     |  189 ++++++++++++++++++++++++++++++++++++----------------
 3 files changed, 162 insertions(+), 67 deletions(-)

New commits:
commit 86f23f21ab57fcbc031bcd2b8f432a08ff4cc320
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 23 17:07:49 2011 -0700

    Skip client and drawable resource delete calls when deleting frame event
    
    As the frame_event is about to be freed, there's no point in cleaning
    up references to the drawable and client.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/src/intel_dri.c b/src/intel_dri.c
index f039e9d..3b80823 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -635,9 +635,9 @@ static void
 i830_dri2_del_frame_event(DRI2FrameEventPtr frame_event)
 {
 	if (frame_event->client_id)
-		FreeResourceByType(frame_event->client_id, frame_event_client_type, FALSE);
+		FreeResourceByType(frame_event->client_id, frame_event_client_type, TRUE);
 	if (frame_event->drawable_id)
-		FreeResourceByType(frame_event->drawable_id, frame_event_drawable_type, FALSE);
+		FreeResourceByType(frame_event->drawable_id, frame_event_drawable_type, TRUE);
 }
 
 static void
commit e1ff5182304e00c0d392092069422cae7626cf8d
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 9 17:00:41 2011 -0800

    Handle drawable/client destruction in pending swaps/flips
    
    A pending swap or flip holds references to drawables and clients which
    become invalid when destroyed. Add suitable resources to the database
    to track those lifetimes and clean up the pending data structure then.
    
    Later, when the pending swap or flip occurs, handle a missing drawable
    by just discarding the flip or swap. Handle a missing client by not
    sending an event or reply.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/src/intel.h b/src/intel.h
index 711449a..4179989 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -472,6 +472,7 @@ enum DRI2FrameEventType {
 
 typedef struct _DRI2FrameEvent {
 	XID drawable_id;
+	XID client_id;	/* fake client ID to track client destruction */
 	ClientPtr client;
 	enum DRI2FrameEventType type;
 	int frame;
diff --git a/src/intel_display.c b/src/intel_display.c
index eb07cf5..4734844 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -1512,7 +1512,7 @@ static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
 
 static void
 intel_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
-		       unsigned int tv_usec, DRI2FrameEventPtr event)
+		       unsigned int tv_usec, void *event)
 {
 	I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event);
 }
diff --git a/src/intel_dri.c b/src/intel_dri.c
index 9e8c370..f039e9d 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -577,6 +577,69 @@ I830DRI2DrawablePipe(DrawablePtr pDraw)
 	return pipe;
 }
 
+static RESTYPE	frame_event_client_type, frame_event_drawable_type;
+
+static int
+i830_dri2_frame_event_client_gone(void *data, XID id)
+{
+	DRI2FrameEventPtr	frame_event = data;
+
+	frame_event->client = NULL;
+	frame_event->client_id = None;
+	return Success;
+}
+
+static int
+i830_dri2_frame_event_drawable_gone(void *data, XID id)
+{
+	DRI2FrameEventPtr	frame_event = data;
+
+	frame_event->drawable_id = None;
+	return Success;
+}
+
+static Bool
+i830_dri2_register_frame_event_resource_types(void)
+{
+	frame_event_client_type = CreateNewResourceType(i830_dri2_frame_event_client_gone, "Frame Event Client");
+	if (!frame_event_client_type)
+		return FALSE;
+
+	frame_event_drawable_type = CreateNewResourceType(i830_dri2_frame_event_drawable_gone, "Frame Event Drawable");
+	if (!frame_event_drawable_type)
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * Hook this frame event into the server resource
+ * database so we can clean it up if the drawable or
+ * client exits while the swap is pending
+ */
+static Bool
+i830_dri2_add_frame_event(DRI2FrameEventPtr frame_event)
+{
+	frame_event->client_id = FakeClientID(frame_event->client->index);
+
+	if (!AddResource(frame_event->client_id, frame_event_client_type, frame_event))
+		return FALSE;
+
+	if (!AddResource(frame_event->drawable_id, frame_event_drawable_type, frame_event))
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+i830_dri2_del_frame_event(DRI2FrameEventPtr frame_event)
+{
+	if (frame_event->client_id)
+		FreeResourceByType(frame_event->client_id, frame_event_client_type, FALSE);
+	if (frame_event->drawable_id)
+		FreeResourceByType(frame_event->drawable_id, frame_event_drawable_type, FALSE);
+}
+
 static void
 I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front,
 			DRI2BufferPtr back)
@@ -642,11 +705,18 @@ I830DRI2ScheduleFlip(struct intel_screen_private *intel,
 	flip_info->event_data = data;
 	flip_info->frame = target_msc;
 
+	i830_dri2_add_frame_event(flip_info);
+
 	/* Page flip the full screen buffer */
 	back_priv = back->driverPrivate;
-	return intel_do_pageflip(intel,
-				 intel_get_pixmap_bo(back_priv->pixmap),
-				 flip_info, ref_crtc_hw_id);
+	if (intel_do_pageflip(intel,
+			      intel_get_pixmap_bo(back_priv->pixmap),
+			      flip_info, ref_crtc_hw_id))
+		return TRUE;
+
+	i830_dri2_del_frame_event(flip_info);
+	free(flip_info);
+	return FALSE;
 }
 
 static Bool
@@ -682,7 +752,7 @@ can_exchange(DRI2BufferPtr front, DRI2BufferPtr back)
 }
 
 void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, DRI2FrameEventPtr event)
+			       unsigned int tv_usec, DRI2FrameEventPtr swap_info)
 {
 	DrawablePtr drawable;
 	ScreenPtr screen;
@@ -690,12 +760,16 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 	intel_screen_private *intel;
 	int status;
 
-	status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
-				   M_ANY, DixWriteAccess);
+	if (!swap_info->drawable_id)
+		status = BadDrawable;
+	else
+		status = dixLookupDrawable(&drawable, swap_info->drawable_id, serverClient,
+					   M_ANY, DixWriteAccess);
 	if (status != Success) {
-		I830DRI2DestroyBuffer(NULL, event->front);
-		I830DRI2DestroyBuffer(NULL, event->back);
-		free(event);
+		i830_dri2_del_frame_event(swap_info);
+		I830DRI2DestroyBuffer(NULL, swap_info->front);
+		I830DRI2DestroyBuffer(NULL, swap_info->back);
+		free(swap_info);
 		return;
 	}
 
@@ -703,28 +777,28 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 	scrn = xf86Screens[screen->myNum];
 	intel = intel_get_screen_private(scrn);
 
-	switch (event->type) {
+	switch (swap_info->type) {
 	case DRI2_FLIP:
 		/* If we can still flip... */
 		if (DRI2CanFlip(drawable) && !intel->shadow_present &&
 		    intel->use_pageflipping &&
-		    can_exchange(event->front, event->back) &&
+		    can_exchange(swap_info->front, swap_info->back) &&
 		    I830DRI2ScheduleFlip(intel,
-					 event->client, drawable, event->front,
-					 event->back, event->event_complete,
-					 event->event_data, event->frame)) {
+					 swap_info->client, drawable, swap_info->front,
+					 swap_info->back, swap_info->event_complete,
+					 swap_info->event_data, swap_info->frame)) {
 			I830DRI2ExchangeBuffers(drawable,
-						event->front, event->back);
+						swap_info->front, swap_info->back);
 			break;
 		}
 		/* else fall through to exchange/blit */
 	case DRI2_SWAP: {
 		int swap_type;
 
-		if (DRI2CanExchange(drawable) && can_exchange(event->front,
-							      event->back)) {
+		if (DRI2CanExchange(drawable) && can_exchange(swap_info->front,
+							      swap_info->back)) {
 			I830DRI2ExchangeBuffers(drawable,
-						event->front, event->back);
+						swap_info->front, swap_info->back);
 			swap_type = DRI2_EXCHANGE_COMPLETE;
 		} else {
 			BoxRec	    box;
@@ -737,17 +811,19 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 			REGION_INIT(pScreen, &region, &box, 0);
 
 			I830DRI2CopyRegion(drawable,
-					   &region, event->front, event->back);
+					   &region, swap_info->front, swap_info->back);
 			swap_type = DRI2_BLIT_COMPLETE;
 		}
-		DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
+		DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
 				 swap_type,
-				 event->event_complete, event->event_data);
+				 swap_info->client ? swap_info->event_complete : NULL,
+				 swap_info->event_data);
 		break;
 	}
 	case DRI2_WAITMSC:
-		DRI2WaitMSCComplete(event->client, drawable,
-				    frame, tv_sec, tv_usec);
+		if (swap_info->client)
+			DRI2WaitMSCComplete(swap_info->client, drawable,
+					    frame, tv_sec, tv_usec);
 		break;
 	default:
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -756,23 +832,28 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
-	I830DRI2DestroyBuffer(drawable, event->front);
-	I830DRI2DestroyBuffer(drawable, event->back);
-	free(event);
+	i830_dri2_del_frame_event(swap_info);
+	I830DRI2DestroyBuffer(drawable, swap_info->front);
+	I830DRI2DestroyBuffer(drawable, swap_info->back);
+	free(swap_info);
 }
 
 void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
-			      unsigned int tv_usec, DRI2FrameEventPtr flip)
+			      unsigned int tv_usec, DRI2FrameEventPtr flip_info)
 {
 	DrawablePtr drawable;
 	ScreenPtr screen;
 	ScrnInfoPtr scrn;
 	int status;
 
-	status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
-				     M_ANY, DixWriteAccess);
+	if (!flip_info->drawable_id)
+		status = BadDrawable;
+	else
+		status = dixLookupDrawable(&drawable, flip_info->drawable_id, serverClient,
+					   M_ANY, DixWriteAccess);
 	if (status != Success) {
-		free(flip);
+		i830_dri2_del_frame_event(flip_info);
+		free(flip_info);
 		return;
 	}
 
@@ -780,13 +861,13 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 	scrn = xf86Screens[screen->myNum];
 
 	/* We assume our flips arrive in order, so we don't check the frame */
-	switch (flip->type) {
+	switch (flip_info->type) {
 	case DRI2_SWAP:
 		/* Check for too small vblank count of pageflip completion, taking wraparound
 		 * into account. This usually means some defective kms pageflip completion,
 		 * causing wrong (msc, ust) return values and possible visual corruption.
 		 */
-		if ((frame < flip->frame) && (flip->frame - frame < 5)) {
+		if ((frame < flip_info->frame) && (flip_info->frame - frame < 5)) {
 			static int limit = 5;
 
 			/* XXX we are currently hitting this path with older
@@ -795,7 +876,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 			if (limit) {
 				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 					   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
-					   __func__, frame, flip->frame);
+					   __func__, frame, flip_info->frame);
 				limit--;
 			}
 
@@ -803,9 +884,9 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 			frame = tv_sec = tv_usec = 0;
 		}
 
-		DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
-				 DRI2_FLIP_COMPLETE, flip->event_complete,
-				 flip->event_data);
+		DRI2SwapComplete(flip_info->client, drawable, frame, tv_sec, tv_usec,
+				 DRI2_FLIP_COMPLETE, flip_info->client ? flip_info->event_complete : NULL,
+				 flip_info->event_data);
 	break;
 	default:
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -814,7 +895,8 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
-	free(flip);
+	i830_dri2_del_frame_event(flip_info);
+	free(flip_info);
 }
 
 /*
@@ -876,6 +958,8 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	I830DRI2ReferenceBuffer(front);
 	I830DRI2ReferenceBuffer(back);
 
+	i830_dri2_add_frame_event(swap_info);
+
 	/* Get current count */
 	vbl.request.type = DRM_VBLANK_RELATIVE;
 	if (pipe > 0)
@@ -1008,6 +1092,7 @@ blit_fallback:
 
 	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
 	if (swap_info) {
+	    i830_dri2_del_frame_event(swap_info);
 	    I830DRI2DestroyBuffer(draw, swap_info->front);
 	    I830DRI2DestroyBuffer(draw, swap_info->back);
 	    free(swap_info);
@@ -1198,6 +1283,8 @@ out_complete:
 }
 #endif
 
+static int dri2_server_generation;
+
 Bool I830DRI2ScreenInit(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
@@ -1224,6 +1311,14 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
 		return FALSE;
 	}
 
+	if (serverGeneration != dri2_server_generation) {
+	    dri2_server_generation = serverGeneration;
+	    if (!i830_dri2_register_frame_event_resource_types()) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "Cannot register DRI2 frame event resources\n");
+		return FALSE;
+	    }
+	}
 	intel->deviceName = drmGetDeviceNameFromFd(intel->drmSubFD);
 	memset(&info, '\0', sizeof(info));
 	info.fd = intel->drmSubFD;
commit aa0328f342177e33f9c863531712eaa4577b5f2b
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 9 16:23:22 2011 -0800

    dri2: Make DRI2FrameEvent public and use instead of void *
    
    Instead of using void * for all of the flip_info and swap_info
    pointers, just make the underlying structure a public data type and
    use that.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/src/intel.h b/src/intel.h
index d2a553f..711449a 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -464,9 +464,28 @@ extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crt
 extern int intel_crtc_id(xf86CrtcPtr crtc);
 extern int intel_output_dpms_status(xf86OutputPtr output);
 
+enum DRI2FrameEventType {
+	DRI2_SWAP,
+	DRI2_FLIP,
+	DRI2_WAITMSC,
+};
+
+typedef struct _DRI2FrameEvent {
+	XID drawable_id;
+	ClientPtr client;
+	enum DRI2FrameEventType type;
+	int frame;
+
+	/* for swaps & flips only */
+	DRI2SwapEventPtr event_complete;
+	void *event_data;
+	DRI2BufferPtr front;
+	DRI2BufferPtr back;
+} DRI2FrameEventRec, *DRI2FrameEventPtr;
+
 extern Bool intel_do_pageflip(intel_screen_private *intel,
 			      dri_bo *new_front,
-			      void *data, int ref_crtc_hw_id);
+			      DRI2FrameEventPtr flip_info, int ref_crtc_hw_id);
 
 static inline intel_screen_private *
 intel_get_screen_private(ScrnInfoPtr scrn)
@@ -500,9 +519,9 @@ extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
 Bool I830DRI2ScreenInit(ScreenPtr pScreen);
 void I830DRI2CloseScreen(ScreenPtr pScreen);
 void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, void *user_data);
+			       unsigned int tv_usec, DRI2FrameEventPtr flip_info);
 void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
-			      unsigned int tv_usec, void *user_data);
+			      unsigned int tv_usec, DRI2FrameEventPtr flip_info);
 
 extern Bool intel_crtc_on(xf86CrtcPtr crtc);
 int intel_crtc_to_pipe(xf86CrtcPtr crtc);
diff --git a/src/intel_display.c b/src/intel_display.c
index f487a6e..eb07cf5 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -50,7 +50,7 @@ struct intel_mode {
 	int cpp;
 
 	drmEventContext event_context;
-	void *event_data;
+	DRI2FrameEventPtr flip_info;
 	int old_fb_id;
 	int flip_count;
 	unsigned int fe_frame;
@@ -1428,7 +1428,7 @@ fail:
 Bool
 intel_do_pageflip(intel_screen_private *intel,
 		  dri_bo *new_front,
-		  void *data, int ref_crtc_hw_id)
+		  DRI2FrameEventPtr flip_info, int ref_crtc_hw_id)
 {
 	ScrnInfoPtr scrn = intel->scrn;
 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1464,7 +1464,7 @@ intel_do_pageflip(intel_screen_private *intel,
 		if (!config->crtc[i]->enabled)
 			continue;
 
-		mode->event_data = data;
+		mode->flip_info = flip_info;
 		mode->flip_count++;
 
 		crtc = config->crtc[i]->driver_private;
@@ -1512,9 +1512,9 @@ static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
 
 static void
 intel_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
-		       unsigned int tv_usec, void *event_data)
+		       unsigned int tv_usec, DRI2FrameEventPtr event)
 {
-	I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event_data);
+	I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event);
 }
 
 static void
@@ -1541,12 +1541,12 @@ intel_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
 	/* Release framebuffer */
 	drmModeRmFB(mode->fd, mode->old_fb_id);
 
-	if (mode->event_data == NULL)
+	if (mode->flip_info == NULL)
 		return;
 
 	/* Deliver cached msc, ust from reference crtc to flip event handler */
 	I830DRI2FlipEventHandler(mode->fe_frame, mode->fe_tv_sec,
-				 mode->fe_tv_usec, mode->event_data);
+				 mode->fe_tv_usec, mode->flip_info);
 }
 
 static void
diff --git a/src/intel_dri.c b/src/intel_dri.c
index 7449232..9e8c370 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -553,24 +553,6 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
 
 #if DRI2INFOREC_VERSION >= 4
 
-enum DRI2FrameEventType {
-	DRI2_SWAP,
-	DRI2_FLIP,
-	DRI2_WAITMSC,
-};
-
-typedef struct _DRI2FrameEvent {
-	XID drawable_id;
-	ClientPtr client;
-	enum DRI2FrameEventType type;
-	int frame;
-
-	/* for swaps & flips only */
-	DRI2SwapEventPtr event_complete;
-	void *event_data;
-	DRI2BufferPtr front;
-	DRI2BufferPtr back;
-} DRI2FrameEventRec, *DRI2FrameEventPtr;
 
 static int
 I830DRI2DrawablePipe(DrawablePtr pDraw)
@@ -700,9 +682,8 @@ can_exchange(DRI2BufferPtr front, DRI2BufferPtr back)
 }
 
 void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
-			       unsigned int tv_usec, void *event_data)
+			       unsigned int tv_usec, DRI2FrameEventPtr event)
 {
-	DRI2FrameEventPtr event = event_data;
 	DrawablePtr drawable;
 	ScreenPtr screen;
 	ScrnInfoPtr scrn;
@@ -781,9 +762,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 }
 
 void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
-			      unsigned int tv_usec, void *event_data)
+			      unsigned int tv_usec, DRI2FrameEventPtr flip)
 {
-	DRI2FrameEventPtr flip = event_data;
 	DrawablePtr drawable;
 	ScreenPtr screen;
 	ScrnInfoPtr scrn;


More information about the xorg-commit mailing list