xf86-video-intel: src/i830_dri.c

Chris Wilson ickle at kemper.freedesktop.org
Fri May 14 02:38:32 PDT 2010


 src/i830_dri.c |   32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

New commits:
commit 0d2392d44aae95d6b571d98f7ec323cf672a687f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 14 10:32:12 2010 +0100

    dri: Hold reference to buffers across swap
    
    As we schedule swaps for some time in the future and may process a
    detachment prior to receiving the vblank notification from the kernel,
    we need to hold a reference to the buffers for our swap event handler.
    
    Fixes:
      Bug 28080 - "glresize" causes X server segfault with indirect rendering.
      https://bugs.freedesktop.org/show_bug.cgi?id=28080
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 9500dad..21871c5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -75,6 +75,7 @@ extern XF86ModuleData dri2ModuleData;
 #endif
 
 typedef struct {
+	int refcnt;
 	PixmapPtr pixmap;
 	unsigned int attachment;
 } I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
@@ -147,6 +148,7 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
 		buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
 		buffers[i].driverPrivate = &privates[i];
 		buffers[i].flags = 0;	/* not tiled */
+		privates[i].refcnt = 1;
 		privates[i].pixmap = pixmap;
 		privates[i].attachment = attachments[i];
 
@@ -223,6 +225,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
 	buffer->driverPrivate = privates;
 	buffer->format = format;
 	buffer->flags = 0;	/* not tiled */
+	privates->refcnt = 1;
 	privates->pixmap = pixmap;
 	privates->attachment = attachment;
 
@@ -262,17 +265,27 @@ static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
 {
 	if (buffer) {
 		I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
-		ScreenPtr screen = drawable->pScreen;
+		if (--private->refcnt == 0) {
+			ScreenPtr screen = private->pixmap->drawable.pScreen;
 
-		screen->DestroyPixmap(private->pixmap);
+			screen->DestroyPixmap(private->pixmap);
 
-		xfree(private);
-		xfree(buffer);
+			xfree(private);
+			xfree(buffer);
+		}
 	}
 }
 
 #endif
 
+static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer)
+{
+	if (buffer) {
+		I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
+		private->refcnt++;
+	}
+}
+
 static void
 I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
 		   DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer)
@@ -510,6 +523,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 	status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
 				   M_ANY, DixWriteAccess);
 	if (status != Success) {
+		I830DRI2DestroyBuffer(NULL, event->front);
+		I830DRI2DestroyBuffer(NULL, event->back);
 		xfree(event);
 		return;
 	}
@@ -568,6 +583,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
 		break;
 	}
 
+	I830DRI2DestroyBuffer(drawable, event->front);
+	I830DRI2DestroyBuffer(drawable, event->back);
 	xfree(event);
 }
 
@@ -661,6 +678,8 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	swap_info->event_data = data;
 	swap_info->front = front;
 	swap_info->back = back;
+	I830DRI2ReferenceBuffer(front);
+	I830DRI2ReferenceBuffer(back);
 
 	/* Get current count */
 	vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -791,8 +810,11 @@ blit_fallback:
 	I830DRI2CopyRegion(draw, &region, front, back);
 
 	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
-	if (swap_info)
+	if (swap_info) {
+	    I830DRI2DestroyBuffer(draw, swap_info->front);
+	    I830DRI2DestroyBuffer(draw, swap_info->back);
 	    xfree(swap_info);
+	}
 	*target_msc = 0; /* offscreen, so zero out target vblank count */
 	return TRUE;
 }


More information about the xorg-commit mailing list