Bumps the supported DRI2 protocol version to 1.3. Signed-off-by: Francisco Jerez <curroje...@riseup.net> --- v1 was evil because the multiple clients rendering to the same drawable case wasn't handled correctly (sometimes it crashed). Seems to work now.
hw/xfree86/dri2/dri2.c | 109 +++++++++++++++++++++++++++++++++++++++++++ hw/xfree86/dri2/dri2.h | 5 ++ hw/xfree86/dri2/dri2ext.c | 36 +++++++++++++-- include/protocol-versions.h | 2 +- 4 files changed, 147 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 65433e9..82ecf28 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -52,6 +52,13 @@ static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; static int dri2PixmapPrivateKeyIndex; static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; +typedef struct _DRI2ClientRef *DRI2ClientRefPtr; + +struct _DRI2ClientRef { + DRI2ClientRefPtr next; + XID resource; +}; + typedef struct _DRI2Drawable { unsigned int refCount; int width; @@ -65,6 +72,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; @@ -83,6 +92,8 @@ typedef struct _DRI2Screen { DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; HandleExposuresProcPtr HandleExposures; + + PreConfigureWindowProcPtr PreConfigureWindow; } DRI2ScreenRec; static DRI2ScreenPtr @@ -142,6 +153,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) { @@ -379,6 +391,78 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) } } +extern RESTYPE dri2DrawableRes; + +int +DRI2TrackClient(DrawablePtr pDraw, int id) +{ + 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) == id) + return Success; + } + + /* Allocate a client ref. */ + ref = xalloc(sizeof(*ref)); + if (ref == NULL) + return BadAlloc; + + ref->next = pPriv->track_clients; + pPriv->track_clients = ref; + + /* Allocate a resource for it. */ + ref->resource = FakeClientID(id); + if (!AddResource(ref->resource, dri2DrawableRes, pDraw)) + return BadAlloc; + + return Success; +} + +void +DRI2UntrackClient(DrawablePtr pDraw, int 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) == id) { + *prev = ref->next; + xfree(ref); + break; + } + } +} + +void +DRI2InvalidateDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2ClientRefPtr ref; + + if (pPriv == NULL) + return; + + while ((ref = pPriv->track_clients)) { + ClientPtr client = clients[CLIENT_ID(ref->resource)]; + + FreeResource(ref->resource, RT_NONE); + + if (client && !client->clientGone) + DRI2InvalidateBuffersEvent(pDraw, client); + } +} + int DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, unsigned int dest, unsigned int src) @@ -736,6 +820,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw) DRI2DrawablePtr pPriv; WindowPtr pWin; PixmapPtr pPixmap; + DRI2ClientRefPtr ref; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) @@ -754,6 +839,9 @@ DRI2DestroyDrawable(DrawablePtr pDraw) xfree(pPriv->buffers); } + while ((ref = pPriv->track_clients)) + FreeResource(ref->resource, RT_NONE); + /* 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. */ @@ -802,6 +890,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) { @@ -836,6 +942,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"); return TRUE; diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index c0f82ee..4973819 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -259,4 +259,9 @@ 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, int id); +extern _X_EXPORT void DRI2UntrackClient(DrawablePtr pDraw, int id); +extern _X_EXPORT void DRI2InvalidateBuffersEvent(DrawablePtr pDraw, ClientPtr client); +extern _X_EXPORT void DRI2InvalidateDrawable(DrawablePtr pDraw); + #endif diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index a4ed2ad..fadda3b 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -51,7 +51,7 @@ #include "xf86Module.h" static ExtensionEntry *dri2Extension; -static RESTYPE dri2DrawableRes; +RESTYPE dri2DrawableRes; static Bool validDrawable(ClientPtr client, XID drawable, Mask access_mode, @@ -266,6 +266,9 @@ ProcDRI2GetBuffers(ClientPtr client) buffers = DRI2GetBuffers(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(pDrawable, client->index); + if (status) + return status; send_buffers_reply(client, pDrawable, buffers, count, width, height); @@ -293,6 +296,10 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(pDrawable, client->index); + if (status) + return status; + send_buffers_reply(client, pDrawable, buffers, count, width, height); return client->noClientException; @@ -367,6 +374,18 @@ DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, WriteEventsToClient(client, 1, (xEvent *)&event); } +void +DRI2InvalidateBuffersEvent(DrawablePtr pDraw, ClientPtr client) +{ + xDRI2InvalidateBuffers event; + + event.type = DRI2EventBase + DRI2_InvalidateBuffers; + event.sequenceNumber = client->sequence; + event.drawable = pDraw->id; + + WriteEventsToClient(client, 1, (xEvent *)&event); +} + static int ProcDRI2SwapBuffers(ClientPtr client) { @@ -391,6 +410,9 @@ ProcDRI2SwapBuffers(ClientPtr client) if (status != Success) return BadDrawable; + if (type != DRI2_SWAP_BLIT) + DRI2InvalidateDrawable(pDrawable); + rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; @@ -618,11 +640,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, CLIENT_ID(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 ------------------------------------------------------------------------------ Throughout its 18-year history, RSA Conference consistently attracts the world's best and brightest in the field, creating opportunities for Conference attendees to learn about information security's most important issues through interactions with peers, luminaries and emerging and established companies. http://p.sf.net/sfu/rsaconf-dev2dev _______________________________________________ Mesa3d-dev mailing list Mesa3d-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mesa3d-dev