[PATCH 2/2] DRI2: Track clients' outstanding swap requests.
Christopher James Halse Rogers
christopher.halse.rogers at canonical.com
Tue Dec 7 22:56:34 PST 2010
Clients can terminate with pending SwapBuffers requests waiting
for the trigger, potentially a long way in the future.
Track these requests so we don't end up delivering
SwapBuffersComplete to an entirely unrelated client.
Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
---
hw/xfree86/dri2/dri2.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 6da2e17..37648bd 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -60,6 +60,9 @@ static DevPrivateKeyRec dri2WindowPrivateKeyRec;
static DevPrivateKeyRec dri2PixmapPrivateKeyRec;
#define dri2PixmapPrivateKey (&dri2PixmapPrivateKeyRec)
+static DevPrivateKeyRec dri2ClientPrivateKeyRec;
+#define dri2ClientPrivateKey (&dri2ClientPrivateKeyRec)
+
static RESTYPE dri2DrawableRes;
typedef struct _DRI2Screen *DRI2ScreenPtr;
@@ -111,8 +114,16 @@ typedef struct _DRI2SwapCompleteDataRec {
DRI2BufferPtr src;
DRI2BufferPtr dest;
void * data;
+ Bool clientGone;
+ struct list link;
} DRI2SwapCompleteDataRec, *DRI2SwapCompleteDataPtr;
+static struct list *
+DRI2GetClientEventList(ClientPtr client)
+{
+ return dixLookupPrivate(&client->devPrivates, dri2ClientPrivateKey);
+}
+
static DRI2ScreenPtr
DRI2GetScreen(ScreenPtr pScreen)
{
@@ -739,6 +750,7 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
static void
free_swap_complete_data (DrawablePtr pDraw, DRI2SwapCompleteDataPtr pSwapData)
{
+ list_del(&pSwapData->link);
buffer_unref(pDraw, pSwapData->src);
buffer_unref(pDraw, pSwapData->dest);
free(pSwapData);
@@ -776,15 +788,16 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
DRI2BufferFrontLeft);
ust = ((CARD64)tv_sec * 1000000) + tv_usec;
- if (swap_complete)
+ if (swap_complete && !pSwapData->clientGone)
swap_complete(client, pSwapData->data, type, ust, frame,
pPriv->swap_count);
pPriv->last_swap_msc = frame;
pPriv->last_swap_ust = ust;
- DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
-
+ if (!pSwapData->clientGone)
+ DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
+
free_swap_complete_data(pDraw, pSwapData);
}
@@ -817,6 +830,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
DRI2DrawablePtr pPriv;
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
DRI2SwapCompleteDataPtr pSwapData;
+ struct list * clientEvents = DRI2GetClientEventList(client);
int ret, i;
CARD64 ust, current_msc;
@@ -855,6 +869,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
pSwapData->src = pSrcBuffer;
pSwapData->dest = pDestBuffer;
pSwapData->data = data;
+ pSwapData->clientGone = FALSE;
+ list_add (&pSwapData->link, clientEvents);
/* Old DDX or no swap interval, just blit */
if (!ds->ScheduleSwap || !pPriv->swap_interval) {
@@ -1137,6 +1153,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
if (!dixRegisterPrivateKey(&dri2PixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
return FALSE;
+ if (!dixRegisterPrivateKey(&dri2ClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (struct list)))
+ return FALSE;
+
ds = calloc(1, sizeof *ds);
if (!ds)
return FALSE;
@@ -1226,6 +1245,34 @@ DRI2CloseScreen(ScreenPtr pScreen)
dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
}
+static void
+DRI2ClientCallback(CallbackListPtr *ClientStateCallback, pointer closure, pointer calldata)
+{
+ NewClientInfoRec *clientinfo = calldata;
+ ClientPtr pClient = clientinfo->client;
+ struct list *clientEvents = DRI2GetClientEventList(pClient);
+ DRI2SwapCompleteDataPtr ref, next;
+
+ switch (pClient->clientState) {
+ case ClientStateInitial:
+ list_init(clientEvents);
+ break;
+ case ClientStateRunning:
+ break;
+ case ClientStateRetained:
+ case ClientStateGone:
+ if (clientEvents) {
+ list_for_each_entry_safe(ref, next, clientEvents, link) {
+ ref->clientGone = TRUE;
+ list_del(&ref->link);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
extern ExtensionModule dri2ExtensionModule;
static pointer
@@ -1238,6 +1285,7 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
if (!setupDone)
{
setupDone = TRUE;
+ AddCallback(&ClientStateCallback, DRI2ClientCallback, NULL);
LoadExtension(&dri2ExtensionModule, FALSE);
}
else
--
1.7.2.3
More information about the xorg-devel
mailing list