[PULL] DRI2 Invalidate series

Kristian Høgsberg krh at bitplanet.net
Wed Feb 17 19:01:57 PST 2010


2010/2/17 Francisco Jerez <currojerez at riseup.net>:
> Bumps the supported DRI2 protocol version.
> ---
> v5: Restructuring as proposed by Kristian: Don't duplicate the
> invalidation policy in the GLX code, keep it in dri2.c and hide the
> actual invalidation mechanism behind an opaque callback.

That's exactly what I had in mind, thanks.  I've applied the series
with S-o-b's and posted a DRI2 tree here for Keith to pull:

  ssh://git.freedesktop.org/git/~krh/xserver dri2-invalidate

I added a patch on top to make DRI2SwapBuffer only send out invalidate
events when it manages to actually swap the buffers (as opposed to
falling back to blitting).  I just committed the mesa patch that will
let the intel dri drivers take advantage of the DRI2 invalidate event,
and I've tested the setup with compiz, openarena and glxgears.

thanks,
Kristian

>  configure.ac                |    2 +-
>  hw/xfree86/dri2/dri2.c      |  104 +++++++++++++++++++++++++++++++++++++++++++
>  hw/xfree86/dri2/dri2.h      |    4 ++
>  hw/xfree86/dri2/dri2ext.c   |   56 ++++++++++++++++++++++-
>  include/protocol-versions.h |    2 +-
>  5 files changed, 163 insertions(+), 5 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index de252f3..e9ca45a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -759,7 +759,7 @@ RECORDPROTO="recordproto >= 1.13.99.1"
>  SCRNSAVERPROTO="scrnsaverproto >= 1.1"
>  RESOURCEPROTO="resourceproto"
>  DRIPROTO="xf86driproto >= 2.1.0"
> -DRI2PROTO="dri2proto >= 2.2"
> +DRI2PROTO="dri2proto >= 2.3"
>  XINERAMAPROTO="xineramaproto"
>  BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
>  XCALIBRATEPROTO="xcalibrateproto"
> diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
> index 48618e1..daeeea5 100644
> --- a/hw/xfree86/dri2/dri2.c
> +++ b/hw/xfree86/dri2/dri2.c
> @@ -52,6 +52,14 @@ static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
>  static int dri2PixmapPrivateKeyIndex;
>  static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
>
> +typedef struct _DRI2ClientRef *DRI2ClientRefPtr;
> +
> +struct _DRI2ClientRef {
> +    DRI2ClientRefPtr    next;
> +    XID                         resource;
> +    void              (*invalidate)(DrawablePtr, XID);
> +};
> +
>  typedef struct _DRI2Drawable {
>     unsigned int        refCount;
>     int                         width;
> @@ -65,6 +73,8 @@ typedef struct _DRI2Drawable {
>     CARD64              target_sbc; /* -1 means no SBC wait outstanding */
>     CARD64              last_swap_target; /* most recently queued swap target */
>     int                         swap_limit; /* for N-buffering */
> +    DRI2ClientRefPtr    track_clients; /* Clients to notify on drawable changes. */
> +
>  } DRI2DrawableRec, *DRI2DrawablePtr;
>
>  typedef struct _DRI2Screen *DRI2ScreenPtr;
> @@ -84,6 +94,8 @@ typedef struct _DRI2Screen {
>     DRI2ScheduleWaitMSCProcPtr  ScheduleWaitMSC;
>
>     HandleExposuresProcPtr       HandleExposures;
> +
> +    PreConfigureWindowProcPtr    PreConfigureWindow;
>  } DRI2ScreenRec;
>
>  static DRI2ScreenPtr
> @@ -143,6 +155,7 @@ DRI2CreateDrawable(DrawablePtr pDraw)
>     pPriv->swap_interval = 1;
>     pPriv->last_swap_target = -1;
>     pPriv->swap_limit = 1; /* default to double buffering */
> +    pPriv->track_clients = NULL;
>
>     if (pDraw->type == DRAWABLE_WINDOW)
>     {
> @@ -406,6 +419,72 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
>  }
>
>  int
> +DRI2TrackClient(DrawablePtr pDraw, XID id,
> +               void (*invalidate)(DrawablePtr, XID))
> +{
> +    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
> +    DRI2ClientRefPtr ref;
> +
> +    if (pPriv == NULL)
> +       return BadDrawable;
> +
> +    /* Check if the client is already in. */
> +    for (ref = pPriv->track_clients; ref; ref = ref->next) {
> +       if (CLIENT_ID(ref->resource) == CLIENT_ID(id))
> +           return BadIDChoice;
> +    }
> +
> +    /* Allocate a client ref. */
> +    ref = xalloc(sizeof(*ref));
> +    if (ref == NULL)
> +       return BadAlloc;
> +
> +    ref->resource = id;
> +    ref->invalidate = invalidate;
> +    ref->next = pPriv->track_clients;
> +    pPriv->track_clients = ref;
> +
> +    return Success;
> +}
> +
> +void
> +DRI2UntrackClient(DrawablePtr pDraw, XID id)
> +{
> +    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
> +    DRI2ClientRefPtr ref, *prev;
> +
> +    if (pPriv == NULL)
> +       return;
> +
> +    prev = &pPriv->track_clients;
> +
> +    for (ref = *prev; ref; prev = &ref->next, ref = ref->next) {
> +       if (CLIENT_ID(ref->resource) == CLIENT_ID(id)) {
> +           *prev = ref->next;
> +           xfree(ref);
> +           break;
> +       }
> +    }
> +}
> +
> +static void
> +DRI2InvalidateDrawable(DrawablePtr pDraw)
> +{
> +    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
> +    DRI2ClientRefPtr ref;
> +
> +    if (pPriv == NULL)
> +       return;
> +
> +    while ((ref = pPriv->track_clients)) {
> +       ref->invalidate(pDraw, ref->resource);
> +
> +       pPriv->track_clients = ref->next;
> +       xfree(ref);
> +    }
> +}
> +
> +int
>  DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
>               unsigned int dest, unsigned int src)
>  {
> @@ -659,6 +738,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
>     pPriv->swapsPending++;
>     pPriv->last_swap_target = *swap_target;
>
> +    DRI2InvalidateDrawable(pDraw);
> +
>     return Success;
>  }
>
> @@ -776,6 +857,8 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
>        xfree(pPriv->buffers);
>     }
>
> +    DRI2InvalidateDrawable(pDraw);
> +
>     /* If the window is destroyed while we have a swap pending, don't
>      * actually free the priv yet.  We'll need it in the DRI2SwapComplete()
>      * callback and we'll free it there once we're done. */
> @@ -811,6 +894,24 @@ DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
>     return TRUE;
>  }
>
> +static void
> +DRI2PreConfigureWindow(WindowPtr pWin, int x, int y, int w, int h, int bw,
> +                      WindowPtr pSib)
> +{
> +    DrawablePtr pDraw = (DrawablePtr)pWin;
> +    ScreenPtr pScreen = pDraw->pScreen;
> +    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
> +    DRI2DrawablePtr dd = DRI2GetDrawable(pDraw);
> +
> +    if (ds->PreConfigureWindow)
> +       (*ds->PreConfigureWindow)(pWin, x, y, w, h, bw, pSib);
> +
> +    if (!dd || (dd->width == w && dd->height == h))
> +       return;
> +
> +    DRI2InvalidateDrawable(pDraw);
> +}
> +
>  Bool
>  DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
>  {
> @@ -869,6 +970,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
>
>     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
>
> +    ds->PreConfigureWindow = pScreen->PreConfigureWindow;
> +    pScreen->PreConfigureWindow = DRI2PreConfigureWindow;
> +
>     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
>     for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) {
>        if (i < ds->numDrivers && ds->driverNames[i]) {
> diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
> index 1c8626b..4bb2aa0 100644
> --- a/hw/xfree86/dri2/dri2.h
> +++ b/hw/xfree86/dri2/dri2.h
> @@ -265,4 +265,8 @@ extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
>                                          int frame, unsigned int tv_sec,
>                                          unsigned int tv_usec);
>
> +extern _X_EXPORT int DRI2TrackClient(DrawablePtr pDraw, XID id,
> +                                    void (*invalidate)(DrawablePtr, XID));
> +extern _X_EXPORT void DRI2UntrackClient(DrawablePtr pDraw, XID id);
> +
>  #endif
> diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
> index 3e6b03e..98236ae 100644
> --- a/hw/xfree86/dri2/dri2ext.c
> +++ b/hw/xfree86/dri2/dri2ext.c
> @@ -197,6 +197,43 @@ ProcDRI2DestroyDrawable(ClientPtr client)
>     return client->noClientException;
>  }
>
> +static void
> +DRI2InvalidateBuffersEvent(DrawablePtr pDraw, XID id)
> +{
> +    xDRI2InvalidateBuffers event;
> +    ClientPtr client = clients[CLIENT_ID(id)];
> +
> +    FreeResource(id, dri2DrawableRes);
> +
> +    if (!client || client->clientGone)
> +       return;
> +
> +    event.type = DRI2EventBase + DRI2_InvalidateBuffers;
> +    event.sequenceNumber = client->sequence;
> +    event.drawable = pDraw->id;
> +
> +    WriteEventsToClient(client, 1, (xEvent *)&event);
> +}
> +
> +static int
> +track_client(ClientPtr client, DrawablePtr pDraw)
> +{
> +    XID id;
> +    int ret;
> +
> +    id = FakeClientID(client->index);
> +    if (!AddResource(id, dri2DrawableRes, pDraw))
> +       return BadAlloc;
> +
> +    ret = DRI2TrackClient(pDraw, id, DRI2InvalidateBuffersEvent);
> +    if (ret) {
> +       FreeResource(id, dri2DrawableRes);
> +       if (ret != BadIDChoice)
> +           return ret;
> +    }
> +
> +    return Success;
> +}
>
>  static void
>  send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
> @@ -266,6 +303,9 @@ ProcDRI2GetBuffers(ClientPtr client)
>     buffers = DRI2GetBuffers(pDrawable, &width, &height,
>                             attachments, stuff->count, &count);
>
> +    status = track_client(client, pDrawable);
> +    if (status)
> +       return status;
>
>     send_buffers_reply(client, pDrawable, buffers, count, width, height);
>
> @@ -293,6 +333,10 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
>     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
>                                       attachments, stuff->count, &count);
>
> +    status = track_client(client, pDrawable);
> +    if (status)
> +       return status;
> +
>     send_buffers_reply(client, pDrawable, buffers, count, width, height);
>
>     return client->noClientException;
> @@ -618,11 +662,17 @@ SProcDRI2Dispatch (ClientPtr client)
>     }
>  }
>
> -static int DRI2DrawableGone(pointer p, XID id)
> +static int
> +DRI2DrawableGone(pointer p, XID id)
>  {
> -    DrawablePtr pDrawable = p;
> +    DrawablePtr pDraw = p;
>
> -    DRI2DestroyDrawable(pDrawable);
> +    if (pDraw->id != id) {
> +       /* Secondary reference. */
> +       DRI2UntrackClient(pDraw, id);
> +    } else {
> +       DRI2DestroyDrawable(pDraw);
> +    }
>
>     return Success;
>  }
> diff --git a/include/protocol-versions.h b/include/protocol-versions.h
> index c74b7fa..c425eef 100644
> --- a/include/protocol-versions.h
> +++ b/include/protocol-versions.h
> @@ -53,7 +53,7 @@
>
>  /* DRI2 */
>  #define SERVER_DRI2_MAJOR_VERSION              1
> -#define SERVER_DRI2_MINOR_VERSION              2
> +#define SERVER_DRI2_MINOR_VERSION              3
>
>  /* Generic event extension */
>  #define SERVER_GE_MAJOR_VERSION                 1
> --
> 1.6.4.4
>
>


More information about the xorg-devel mailing list