[PATCH v3 03/11] dri2: Change driver interface to support DRI2Drawable

Pauli ext-pauli.nieminen at nokia.com
Wed Feb 16 02:21:37 PST 2011


From: Pauli Nieminen <ext-pauli.nieminen at nokia.com>

To let DRI2Drawable exists longer than Drawable driver has to use
DRI2DrawablePtr to complete swaps and MSC waits. This allows DRI2 to
clean up after all operations complete without accessing the freed
DrawablePtr.

v2:
* Refactor interface to allow tracking when client is gone

Signed-off-by: Pauli Nieminen <ext-pauli.nieminen at nokia.com>
---
 hw/xfree86/dri2/dri2.c |  118 +++++++++++++++++++++++++++++------------------
 hw/xfree86/dri2/dri2.h |   41 +++++++++++++++-
 2 files changed, 111 insertions(+), 48 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 8efaa9a..8b166d5 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -95,11 +95,11 @@ typedef struct _DRI2Screen {
     unsigned int		 lastSequence;
 
     DRI2CreateBufferProcPtr	 CreateBuffer;
-    DRI2DestroyBufferProcPtr	 DestroyBuffer;
+    DRI2DestroyBuffer2ProcPtr	 DestroyBuffer;
     DRI2CopyRegionProcPtr	 CopyRegion;
     DRI2ScheduleSwapProcPtr	 ScheduleSwap;
     DRI2GetMSCProcPtr		 GetMSC;
-    DRI2ScheduleWaitMSCProcPtr	 ScheduleWaitMSC;
+    DRI2ScheduleWaitMSC2ProcPtr	 ScheduleWaitMSC;
     DRI2AuthMagicProcPtr	 AuthMagic;
 
     HandleExposuresProcPtr       HandleExposures;
@@ -107,6 +107,11 @@ typedef struct _DRI2Screen {
     ConfigNotifyProcPtr		 ConfigNotify;
 } DRI2ScreenRec;
 
+typedef struct _DRI2SwapCompleteDataRec {
+    ClientPtr client;
+    void *data;
+} DRI2SwapCompleteDataRec, *DRI2SwapCompleteDataPtr;
+
 static DRI2ScreenPtr
 DRI2GetScreen(ScreenPtr pScreen)
 {
@@ -137,6 +142,12 @@ DRI2DrawableGetDrawable(DRI2DrawablePtr pPriv)
     return pPriv->drawable;
 }
 
+ScreenPtr
+DRI2DrawableGetScreen(DRI2DrawablePtr pPriv)
+{
+    return pPriv->dri2_screen->screen;
+}
+
 static unsigned long
 DRI2DrawableSerial(DrawablePtr pDraw)
 {
@@ -323,6 +334,7 @@ static int DRI2DrawableGone(pointer p, XID id)
 	return Success;
 
     pDraw = pPriv->drawable;
+
     if (pDraw->type == DRAWABLE_WINDOW) {
 	pWin = (WindowPtr) pDraw;
 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
@@ -333,7 +345,7 @@ static int DRI2DrawableGone(pointer p, XID id)
 
     if (pPriv->buffers != NULL) {
 	for (i = 0; i < pPriv->bufferCount; i++)
-	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+	    (*ds->DestroyBuffer)(pPriv, pPriv->buffers[i]);
 
 	free(pPriv->buffers);
     }
@@ -394,7 +406,7 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
     if (pPriv->buffers != NULL) {
 	for (i = 0; i < pPriv->bufferCount; i++) {
 	    if (pPriv->buffers[i] != NULL) {
-		(*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+		(*ds->DestroyBuffer)(pPriv, pPriv->buffers[i]);
 	    }
 	}
 
@@ -531,7 +543,7 @@ err_out:
 
     for (i = 0; i < count; i++) {
 	    if (buffers[i] != NULL)
-		    (*ds->DestroyBuffer)(pDraw, buffers[i]);
+		    (*ds->DestroyBuffer)(pPriv, buffers[i]);
     }
 
     free(buffers);
@@ -684,14 +696,11 @@ DRI2CanExchange(DrawablePtr pDraw)
 }
 
 void
-DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
-		    unsigned int tv_sec, unsigned int tv_usec)
+DRI2WaitMSCComplete2(DRI2DrawablePtr pPriv, int frame,
+		     unsigned int tv_sec, unsigned int tv_usec,
+		     void *data)
 {
-    DRI2DrawablePtr pPriv;
-
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL)
-	return;
+    ClientPtr client = data;
 
     ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
 			 frame, pPriv->swap_count);
@@ -740,42 +749,43 @@ DRI2WakeClient(ClientPtr client, DRI2DrawablePtr pPriv, int frame,
 }
 
 void
-DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+DRI2SwapComplete2(DRI2DrawablePtr pPriv, int frame,
 		   unsigned int tv_sec, unsigned int tv_usec, int type,
 		   DRI2SwapEventPtr swap_complete, void *swap_data)
 {
-    ScreenPtr	    pScreen = pDraw->pScreen;
-    DRI2DrawablePtr pPriv;
-    CARD64          ust = 0;
-    BoxRec          box;
-    RegionRec       region;
-
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL) {
-        xf86DrvMsg(pScreen->myNum, X_ERROR,
-		   "[DRI2] %s: bad drawable\n", __func__);
-	return;
-    }
+    DRI2SwapCompleteDataPtr pSwapData = swap_data;
+    ClientPtr               client = pSwapData->client;
+    DrawablePtr             pDraw = pPriv->drawable;
+    CARD64                  ust = 0;
 
     pPriv->swapsPending--;
     pPriv->swap_count++;
 
-    box.x1 = 0;
-    box.y1 = 0;
-    box.x2 = pDraw->width;
-    box.y2 = pDraw->height;
-    RegionInit(&region, &box, 0);
-    DRI2CopyRegion(pPriv, &region, DRI2BufferFakeFrontLeft,
-		   DRI2BufferFrontLeft);
+
+    if (pDraw) {
+	BoxRec          box;
+	RegionRec       region;
+
+	box.x1 = 0;
+	box.y1 = 0;
+	box.x2 = pDraw->width;
+	box.y2 = pDraw->height;
+	RegionInit(&region, &box, 0);
+	DRI2CopyRegion(pPriv, &region, DRI2BufferFakeFrontLeft,
+		       DRI2BufferFrontLeft);
+    }
 
     ust = ((CARD64)tv_sec * 1000000) + tv_usec;
     if (swap_complete)
-	swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
+	swap_complete(client, pSwapData->data, type, ust, frame,
+		pPriv->swap_count);
 
     pPriv->last_swap_msc = frame;
     pPriv->last_swap_ust = ust;
 
     DRI2WakeClient(client, pPriv, frame, tv_sec, tv_usec);
+
+    free(pSwapData);
 }
 
 Bool
@@ -800,12 +810,13 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
 		CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
 		DRI2SwapEventPtr func, void *data)
 {
-    DrawablePtr     pDraw = pPriv->drawable;
-    ScreenPtr       pScreen = pPriv->dri2_screen->screen;
-    DRI2ScreenPtr   ds = pPriv->dri2_screen;
-    DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
-    int             ret, i;
-    CARD64          ust, current_msc;
+    DrawablePtr             pDraw = pPriv->drawable;
+    ScreenPtr               pScreen = pPriv->dri2_screen->screen;
+    DRI2ScreenPtr           ds = pPriv->dri2_screen;
+    DRI2BufferPtr           pDestBuffer = NULL, pSrcBuffer = NULL;
+    DRI2SwapCompleteDataPtr pSwapData;
+    int                     ret, i;
+    CARD64                  ust, current_msc;
 
     if (pDraw == NULL) {
         xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -825,6 +836,13 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
 	return BadDrawable;
     }
 
+    pSwapData = malloc(sizeof *pSwapData);
+    if (pSwapData == NULL)
+	return BadAlloc;
+
+    pSwapData->client = client;
+    pSwapData->data = data;
+
     /* Old DDX or no swap interval, just blit */
     if (!ds->ScheduleSwap || !pPriv->swap_interval) {
 	BoxRec box;
@@ -839,8 +857,8 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
 	pPriv->swapsPending++;
 
 	(*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
-	DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
-			 func, data);
+	DRI2SwapComplete2(pPriv, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
+			  func, pSwapData);
 	return Success;
     }
 
@@ -882,6 +900,7 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
 			      swap_target, divisor, remainder, func, data);
     if (!ret) {
 	pPriv->swapsPending--; /* didn't schedule */
+	free(pSwapData);
         xf86DrvMsg(pScreen->myNum, X_ERROR,
 		   "[DRI2] %s: driver failed to schedule swap\n", __func__);
 	return BadDrawable;
@@ -954,12 +973,12 @@ DRI2WaitMSC(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
 
     /* Old DDX just completes immediately */
     if (!ds->ScheduleWaitMSC) {
-	DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
+	DRI2WaitMSCComplete2(pPriv, target_msc, 0, 0, client);
 
 	return Success;
     }
 
-    ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
+    ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder, client);
     if (!ret)
 	return BadDrawable;
 
@@ -1098,12 +1117,10 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     dri2_major         = 1;
 
     ds->CreateBuffer   = info->CreateBuffer;
-    ds->DestroyBuffer  = info->DestroyBuffer;
     ds->CopyRegion     = info->CopyRegion;
 
     if (info->version >= 4) {
 	ds->ScheduleSwap = info->ScheduleSwap;
-	ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
 	ds->GetMSC = info->GetMSC;
 	cur_minor = 3;
     } else {
@@ -1114,6 +1131,11 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         ds->AuthMagic = info->AuthMagic;
     }
 
+    if (info->version >= 6) {
+	ds->DestroyBuffer = info->DestroyBuffer2;
+	ds->ScheduleWaitMSC = info->ScheduleWaitMSC2;
+    }
+
     /*
      * if the driver doesn't provide an AuthMagic function or the info struct
      * version is too low, it relies on the old method (using libdrm) or fail
@@ -1125,6 +1147,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
         goto err_out;
 #endif
 
+    if (!ds->DestroyBuffer) {
+	xf86DrvMsg(pScreen->myNum, X_WARNING,
+		"[DRI2] DestroyBuffer2 hook is required by this server.\n");
+	goto err_out;
+    }
+
     /* Initialize minor if needed and set to minimum provied by DDX */
     if (!dri2_minor || dri2_minor > cur_minor)
 	dri2_minor = cur_minor;
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 509d4f6..3dec65e 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -113,6 +113,8 @@ typedef DRI2BufferPtr	(*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
 						   unsigned int format);
 typedef void		(*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
 						    DRI2BufferPtr buffer);
+typedef void		(*DRI2DestroyBuffer2ProcPtr)(DRI2DrawablePtr pPriv,
+						    DRI2BufferPtr buffer);
 /**
  * Get current media stamp counter values
  *
@@ -159,6 +161,14 @@ typedef int		(*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
 						      CARD64 divisor,
 						      CARD64 remainder);
 
+typedef int		(*DRI2ScheduleWaitMSC2ProcPtr)(ClientPtr client,
+						       DrawablePtr pDraw,
+						       CARD64 target_msc,
+						       CARD64 divisor,
+						       CARD64 remainder,
+						       void *data);
+
+
 typedef void		(*DRI2InvalidateProcPtr)(DRI2DrawablePtr pPriv,
 						 void *data,
 						 XID id);
@@ -166,7 +176,7 @@ typedef void		(*DRI2InvalidateProcPtr)(DRI2DrawablePtr pPriv,
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 5
+#define DRI2INFOREC_VERSION 6
 
 typedef struct {
     unsigned int version;	/**< Version of this struct */
@@ -175,7 +185,7 @@ typedef struct {
     const char *deviceName;
 
     DRI2CreateBufferProcPtr	CreateBuffer;
-    DRI2DestroyBufferProcPtr	DestroyBuffer;
+    DRI2DestroyBufferProcPtr	DestroyBuffer; /* Ignored in version 6 and after */
     DRI2CopyRegionProcPtr	CopyRegion;
     DRI2WaitProcPtr		Wait;
 
@@ -183,7 +193,7 @@ typedef struct {
 
     DRI2ScheduleSwapProcPtr	ScheduleSwap;
     DRI2GetMSCProcPtr		GetMSC;
-    DRI2ScheduleWaitMSCProcPtr	ScheduleWaitMSC;
+    DRI2ScheduleWaitMSCProcPtr	ScheduleWaitMSC; /* Ignored in version 6 and after */
 
     /* number of drivers in the driverNames array */
     unsigned int numDrivers;
@@ -194,6 +204,11 @@ typedef struct {
     /* added in version 5 */
 
     DRI2AuthMagicProcPtr	AuthMagic;
+
+    /* added in version 6 */
+
+    DRI2DestroyBuffer2ProcPtr	DestroyBuffer2;
+    DRI2ScheduleWaitMSC2ProcPtr	ScheduleWaitMSC2;
 }  DRI2InfoRec, *DRI2InfoPtr;
 
 extern _X_EXPORT int DRI2EventBase;
@@ -282,6 +297,7 @@ extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
 /* Note: use *only* for MSC related waits */
 extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
 
+/* Only for source compatibility with older servers */
 extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
 				       int frame, unsigned int tv_sec,
 				       unsigned int tv_usec, int type,
@@ -290,6 +306,17 @@ extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
 extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
 					  int frame, unsigned int tv_sec,
 					  unsigned int tv_usec);
+
+extern _X_EXPORT void DRI2SwapComplete2(DRI2DrawablePtr pPriv,
+				        int frame, unsigned int tv_sec,
+				        unsigned int tv_usec, int type,
+				        DRI2SwapEventPtr swap_complete,
+				        void *swap_data);
+extern _X_EXPORT void DRI2WaitMSCComplete2(DRI2DrawablePtr pPriv,
+					   int frame, unsigned int tv_sec,
+					   unsigned int tv_usec,
+					   void *data);
+
 /**
  * Provides access to DrawablePtr trough DRI2DrawablePtr
  *
@@ -301,6 +328,14 @@ extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
 extern _X_EXPORT DrawablePtr DRI2DrawableGetDrawable(DRI2DrawablePtr pPriv);
 
 /**
+ * Provides access to ScreenPtr trough DRI2DrawablePtr
+ *
+ * \param pPriv DRI2 private drawable
+ * \return valid pointer to Screen
+ */
+extern _X_EXPORT ScreenPtr DRI2DrawableGetScreen(DRI2DrawablePtr pPriv);
+
+/**
  * Provides access to DRI2DrawablePtr trough DrawablePtr
  *
  * \param pDraw drawable pointer
-- 
1.7.0.4



More information about the xorg-devel mailing list