Bumps the supported DRI2 protocol version.

Signed-off-by: Francisco Jerez <curroje...@riseup.net>
---
 configure.ac                |    2 +-
 hw/xfree86/dri2/dri2.c      |  109 +++++++++++++++++++++++++++++++++++++++++++
 hw/xfree86/dri2/dri2.h      |    5 ++
 hw/xfree86/dri2/dri2ext.c   |   35 ++++++++++++--
 include/protocol-versions.h |    2 +-
 5 files changed, 147 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 8c1085b..85225ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -754,7 +754,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 02a93ff..90a5879 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)
@@ -734,6 +818,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
     DRI2DrawablePtr pPriv;
     WindowPtr              pWin;
     PixmapPtr      pPixmap;
+    DRI2ClientRefPtr ref;
 
     pPriv = DRI2GetDrawable(pDraw);
     if (pPriv == NULL)
@@ -752,6 +837,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. */
@@ -800,6 +888,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)
 {
@@ -834,6 +940,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 dd59297..736cfb6 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -256,4 +256,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 3e6b03e..713c82e 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,8 @@ ProcDRI2SwapBuffers(ClientPtr client)
     if (status != Success)
        return BadDrawable;
 
+    DRI2InvalidateDrawable(pDrawable);
+
     rep.type = X_Reply;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
@@ -618,11 +639,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

Reply via email to