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 
> <[email protected]>
> ---
>  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
> 
> _______________________________________________
> [email protected]: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to