[PATCH v2 07/10] DRI2: Track clients' outstanding swap requests.
Pauli
ext-pauli.nieminen at nokia.com
Tue Feb 8 13:42:53 PST 2011
From: Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
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>
Signed-off-by: Pauli Nieminen <ext-pauli.nieminen at nokia.com>
---
hw/xfree86/dri2/dri2.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 5868fb4..9133bb3 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)
+
RESTYPE dri2DrawableRes;
typedef struct _DRI2Screen *DRI2ScreenPtr;
@@ -113,8 +116,15 @@ typedef struct _DRI2SwapCompleteDataRec {
DRI2BufferPtr dest;
ClientPtr client;
void * data;
+ struct list link;
} DRI2SwapCompleteDataRec, *DRI2SwapCompleteDataPtr;
+static struct list *
+DRI2GetClientEventList(ClientPtr client)
+{
+ return dixLookupPrivate(&client->devPrivates, dri2ClientPrivateKey);
+}
+
static DRI2ScreenPtr
DRI2GetScreen(ScreenPtr pScreen)
{
@@ -806,6 +816,7 @@ DRI2WakeClient(ClientPtr client, DRI2DrawablePtr pPriv, int frame,
static void
free_swap_complete_data (DRI2DrawablePtr pPriv, DRI2SwapCompleteDataPtr pSwapData)
{
+ list_del(&pSwapData->link);
buffer_unref(pPriv, pSwapData->src);
buffer_unref(pPriv, pSwapData->dest);
free(pSwapData);
@@ -825,6 +836,11 @@ DRI2SwapComplete2(DRI2DrawablePtr pPriv, int frame,
pPriv->swap_count++;
pPriv->refcnt--;
+ ust = ((CARD64)tv_sec * 1000000) + tv_usec;
+
+ if (client == NULL)
+ goto out;
+
if (pDraw) {
BoxRec box;
RegionRec region;
@@ -838,16 +854,16 @@ DRI2SwapComplete2(DRI2DrawablePtr pPriv, int frame,
DRI2BufferFrontLeft);
}
- ust = ((CARD64)tv_sec * 1000000) + tv_usec;
if (swap_complete)
swap_complete(client, pSwapData->data, type, ust, frame,
pPriv->swap_count);
+ DRI2WakeClient(client, pPriv, frame, tv_sec, tv_usec);
+
+out:
pPriv->last_swap_msc = frame;
pPriv->last_swap_ust = ust;
- DRI2WakeClient(client, pPriv, frame, tv_sec, tv_usec);
-
free_swap_complete_data(pPriv, pSwapData);
if (pPriv->refcnt <= 0)
@@ -881,6 +897,7 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
DRI2ScreenPtr ds = pPriv->dri2_screen;
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
DRI2SwapCompleteDataPtr pSwapData;
+ struct list * clientEvents = DRI2GetClientEventList(client);
int ret, i;
CARD64 ust, current_msc;
@@ -919,6 +936,7 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
pSwapData->dest = pDestBuffer;
pSwapData->client = client;
pSwapData->data = data;
+ list_add (&pSwapData->link, clientEvents);
/* Old DDX or no swap interval, just blit */
if (!ds->ScheduleSwap || !pPriv->swap_interval) {
@@ -1191,6 +1209,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;
@@ -1289,6 +1310,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->client = NULL;
+ list_del(&ref->link);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
extern ExtensionModule dri2ExtensionModule;
static pointer
@@ -1301,6 +1350,7 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
if (!setupDone)
{
setupDone = TRUE;
+ AddCallback(&ClientStateCallback, DRI2ClientCallback, NULL);
LoadExtension(&dri2ExtensionModule, FALSE);
}
else
--
1.7.0.4
More information about the xorg-devel
mailing list