[PATCH v2 03/10] dri2: Change driver interface to support DRI2Drawable
Pauli
ext-pauli.nieminen at nokia.com
Tue Feb 8 13:42:49 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 91ae1a0..7e3e0fd 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(®ion, &box, 0);
- DRI2CopyRegion(pPriv, ®ion, DRI2BufferFakeFrontLeft,
- DRI2BufferFrontLeft);
+
+ if (pDraw) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDraw->width;
+ box.y2 = pDraw->height;
+ RegionInit(®ion, &box, 0);
+ DRI2CopyRegion(pPriv, ®ion, 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, ®ion, 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