xf86-video-ati: Branch 'master' - 3 commits

Alex Deucher agd5f at kemper.freedesktop.org
Mon Aug 1 08:40:24 PDT 2011


 src/drmmode_display.c |   52 ++++++++++++++++++++++++++++++--------------------
 src/drmmode_display.h |   10 ++++++---
 src/radeon_dri2.c     |   45 ++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 79 insertions(+), 28 deletions(-)

New commits:
commit 104b2d7c071f29266b1bc4184a74e9714d14febc
Author: Alex Deucher <alexander.deucher at amd.com>
Date:   Mon Aug 1 10:05:30 2011 -0400

    kms: fix possible leak in pageflip code
    
    Signed-off-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 7f6ce18..f49aa3d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1654,7 +1654,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	unsigned int pitch;
 	int i, old_fb_id;
 	uint32_t tiling_flags = 0;
-	int height;
+	int height, emitted = 0;
 	drmmode_flipdata_ptr flipdata;
 	drmmode_flipevtcarrier_ptr flipcarrier;
 
@@ -1708,6 +1708,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 		if (!flipcarrier) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue: carrier alloc failed.\n");
+			if (emitted == 0)
+				free(flipdata);
 			goto error_undo;
 		}
 
@@ -1722,8 +1724,11 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
 			free(flipcarrier);
+			if (emitted == 0)
+				free(flipdata);
 			goto error_undo;
 		}
+		emitted++;
 	}
 
 	flipdata->old_fb_id = old_fb_id;
commit d29bab632e9ecccba518d4107d52620bf75eb1cf
Author: Ville Syrjala <syrjala at sci.fi>
Date:   Wed May 4 23:51:27 2011 +0300

    kms: Move flip_count and co. to a per swap structure
    
    If multiple drawables are doing page flipping, the global drmmode
    structure can't be used to keep per swap information. For example
    flip_count can increase prematurely due to another swap request,
    and then the previous swap request never gets completed, leading to a
    stuck client. Move the relevant pieces of data to a strucuture that
    gets allocated once per swap request and shared by all involved CRTCs.
    
    Signed-off-by: Ville Syrjala <syrjala at sci.fi>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index afa4c26..7f6ce18 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1331,31 +1331,34 @@ drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
 		     unsigned int tv_usec, void *event_data)
 {
 	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
-	drmmode_ptr drmmode = flipcarrier->drmmode;
+	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+	drmmode_ptr drmmode = flipdata->drmmode;
 
 	/* Is this the event whose info shall be delivered to higher level? */
 	if (flipcarrier->dispatch_me) {
 		/* Yes: Cache msc, ust for later delivery. */
-		drmmode->fe_frame = frame;
-		drmmode->fe_tv_sec = tv_sec;
-		drmmode->fe_tv_usec = tv_usec;
+		flipdata->fe_frame = frame;
+		flipdata->fe_tv_sec = tv_sec;
+		flipdata->fe_tv_usec = tv_usec;
 	}
 	free(flipcarrier);
 
 	/* Last crtc completed flip? */
-	drmmode->flip_count--;
-	if (drmmode->flip_count > 0)
+	flipdata->flip_count--;
+	if (flipdata->flip_count > 0)
 		return;
 
 	/* Release framebuffer */
-	drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
+	drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
 
-	if (drmmode->event_data == NULL)
+	if (flipdata->event_data == NULL)
 		return;
 
 	/* Deliver cached msc, ust from reference crtc to flip event handler */
-	radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec,
-				       drmmode->fe_tv_usec, drmmode->event_data);
+	radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
+				       flipdata->fe_tv_usec, flipdata->event_data);
+
+	free(flipdata);
 }
 
 
@@ -1399,12 +1402,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 
 	xf86InitialConfiguration(pScrn, TRUE);
 
-	drmmode->flip_count = 0;
 	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
 	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
 	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
 	if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) {
-		drmmode->flip_count = 0;
 		AddGeneralSocket(drmmode->fd);
 		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
 				drm_wakeup_handler, drmmode);
@@ -1654,6 +1655,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	int i, old_fb_id;
 	uint32_t tiling_flags = 0;
 	int height;
+	drmmode_flipdata_ptr flipdata;
 	drmmode_flipevtcarrier_ptr flipcarrier;
 
 	if (info->allowColorTiling) {
@@ -1676,6 +1678,12 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 			 new_front->handle, &drmmode->fb_id))
 		goto error_out;
 
+        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
+        if (!flipdata) {
+             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                        "flip queue: data alloc failed.\n");
+             goto error_undo;
+        }
 	/*
 	 * Queue flips on all enabled CRTCs
 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -1685,16 +1693,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 	 * Also, flips queued on disabled or incorrectly configured displays
 	 * may never complete; this is a configuration error.
 	 */
-	drmmode->fe_frame = 0;
-	drmmode->fe_tv_sec = 0;
-	drmmode->fe_tv_usec = 0;
+
+        flipdata->event_data = data;
+        flipdata->drmmode = drmmode;
 
 	for (i = 0; i < config->num_crtc; i++) {
 		if (!config->crtc[i]->enabled)
 			continue;
 
-		drmmode->event_data = data;
-		drmmode->flip_count++;
+		flipdata->flip_count++;
 		drmmode_crtc = config->crtc[i]->driver_private;
 
 		flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
@@ -1708,7 +1715,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 		 * completion event. All other crtc's events will be discarded.
 		 */
 		flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
-		flipcarrier->drmmode = drmmode;
+		flipcarrier->flipdata = flipdata;
 
 		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
@@ -1719,7 +1726,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
 		}
 	}
 
-	drmmode->old_fb_id = old_fb_id;
+	flipdata->old_fb_id = old_fb_id;
 	return TRUE;
 
 error_undo:
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 548907b..eb271f5 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -39,7 +39,6 @@
 typedef struct {
   int fd;
   unsigned fb_id;
-  unsigned old_fb_id;
   drmModeResPtr mode_res;
   drmModeFBPtr mode_fb;
   int cpp;
@@ -50,15 +49,20 @@ typedef struct {
   InputHandlerProc uevent_handler;
 #endif
   drmEventContext event_context;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+  drmmode_ptr drmmode;
+  unsigned old_fb_id;
   int flip_count;
   void *event_data;
   unsigned int fe_frame;
   unsigned int fe_tv_sec;
   unsigned int fe_tv_usec;
-} drmmode_rec, *drmmode_ptr;
+} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
 
 typedef struct {
-  drmmode_ptr drmmode;
+  drmmode_flipdata_ptr flipdata;
   Bool dispatch_me;
 } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
 
commit 9493563c1ef4b51af0ee8a44cb4e7c5bb280347e
Author: Ville Syrjala <syrjala at sci.fi>
Date:   Wed May 4 23:51:26 2011 +0300

    dri2: Update front buffer pixmap and name before exchanging buffers
    
    Buffer exchange assumes that the front buffer pixmap and name
    information is accurate. That may not be the case eg. if the window
    has been (un)redirected since the buffer was created.
    
    Signed-off-by: Ville Syrjala <syrjala at sci.fi>

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 1133319..46573a7 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -662,12 +662,42 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 }
 
 static Bool
-can_exchange(ScrnInfoPtr pScrn,
+update_front(DrawablePtr draw, DRI2BufferPtr front)
+{
+    int r;
+    PixmapPtr pixmap;
+    struct dri2_buffer_priv *priv = front->driverPrivate;
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    if (draw->type == DRAWABLE_PIXMAP)
+	pixmap = (PixmapPtr)draw;
+    else
+	pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw);
+
+    pixmap->refcnt++;
+
+    exaMoveInPixmap(pixmap);
+    driver_priv = exaGetPixmapDriverPrivate(pixmap);
+    r = radeon_gem_get_kernel_name(driver_priv->bo, &front->name);
+    if (r) {
+	(*draw->pScreen->DestroyPixmap)(pixmap);
+	return FALSE;
+    }
+    (*draw->pScreen->DestroyPixmap)(priv->pixmap);
+    front->pitch = pixmap->devKind;
+    front->cpp = pixmap->drawable.bitsPerPixel / 8;
+    priv->pixmap = pixmap;
+
+    return TRUE;
+}
+
+static Bool
+can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw,
 	     DRI2BufferPtr front, DRI2BufferPtr back)
 {
     struct dri2_buffer_priv *front_priv = front->driverPrivate;
     struct dri2_buffer_priv *back_priv = back->driverPrivate;
-    PixmapPtr front_pixmap = front_priv->pixmap;
+    PixmapPtr front_pixmap;
     PixmapPtr back_pixmap = back_priv->pixmap;
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int i;
@@ -678,6 +708,11 @@ can_exchange(ScrnInfoPtr pScrn,
 	    return FALSE;
     }
 
+    if (!update_front(draw, front))
+	return FALSE;
+
+    front_pixmap = front_priv->pixmap;
+
     if (front_pixmap->drawable.width != back_pixmap->drawable.width)
 	return FALSE;
 
@@ -757,7 +792,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
     case DRI2_FLIP:
 	if (info->allowPageFlip &&
 	    DRI2CanFlip(drawable) &&
-	    can_exchange(scrn, event->front, event->back) &&
+	    can_exchange(scrn, drawable, event->front, event->back) &&
 	    radeon_dri2_schedule_flip(scrn,
 				      event->client,
 				      drawable,
@@ -772,7 +807,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
 	/* else fall through to exchange/blit */
     case DRI2_SWAP:
 	if (DRI2CanExchange(drawable) &&
-	    can_exchange(scrn, event->front, event->back)) {
+	    can_exchange(scrn, drawable, event->front, event->back)) {
 	    radeon_dri2_exchange_buffers(drawable, event->front, event->back);
 	    swap_type = DRI2_EXCHANGE_COMPLETE;
 	} else {
@@ -1134,7 +1169,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     /* Flips need to be submitted one frame before */
     if (info->allowPageFlip &&
 	DRI2CanFlip(draw) &&
-	can_exchange(scrn, front, back)) {
+	can_exchange(scrn, draw, front, back)) {
 	swap_type = DRI2_FLIP;
 	flip = 1;
     }


More information about the xorg-commit mailing list