[PATCH 2/2] DRI2: Track clients' outstanding swap requests.
Pauli Nieminen
ext-pauli.nieminen at nokia.com
Thu Dec 9 07:10:55 PST 2010
On 08/12/10 07:56 +0100, ext Christopher James Halse Rogers wrote:
> 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.
>
Client going should trigger resource freeing that should free the
DRI2DrawableReference. That is enough to remove client from listening for
invalidate events.
Could this be tied to the reference that already handles client disconnecting?
> 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
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
More information about the xorg-devel
mailing list