[PATCH 4/5] DRI2: support generic swap event handling

Jesse Barnes jbarnes at virtuousgeek.org
Tue May 3 10:59:17 PDT 2011


The existing swap event structure is too large to fit in an XEvent, so new
servers will send a generic event if the client supports it.  This
allows a valid swap count value to be sent along with the event type,
timestamp, and media stamp.  Check for server support based on the
advertised DRI2 version and look for generic events in the event stream
with DRI2 in the extension field.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
---
 configure.ac        |    2 +-
 src/glx/dri2.c      |  105 ++++++++++++++++++++++++++++++++++++--------------
 src/glx/dri2.h      |    3 +-
 src/glx/dri2_glx.c  |   31 +++++++++++++-
 src/glx/glxclient.h |    2 +
 5 files changed, 108 insertions(+), 35 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3b05ca3..92d11af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@ dnl Versions for external dependencies
 LIBDRM_REQUIRED=2.4.24
 LIBDRM_RADEON_REQUIRED=2.4.24
 LIBDRM_INTEL_REQUIRED=2.4.24
-DRI2PROTO_REQUIRED=2.1
+DRI2PROTO_REQUIRED=2.4
 GLPROTO_REQUIRED=1.4.11
 LIBDRM_XORG_REQUIRED=2.4.24
 LIBKMS_XORG_REQUIRED=1.0.0
diff --git a/src/glx/dri2.c b/src/glx/dri2.c
index adfd3d1..9cab639 100644
--- a/src/glx/dri2.c
+++ b/src/glx/dri2.c
@@ -48,7 +48,7 @@
  */
 #if DRI2_MINOR < 1
 #undef DRI2_MINOR
-#define DRI2_MINOR 1
+#define DRI2_MINOR 4
 #define X_DRI2GetBuffersWithFormat 7
 #endif
 
@@ -88,43 +88,85 @@ static Bool
 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   int type;
 
    XextCheckExtension(dpy, info, dri2ExtensionName, False);
 
-   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
+   if (wire->u.u.type == GenericEvent &&
+       dri2ServerSupportsSBC(dpy)) {
+      xGenericEvent *wire2 = (xGenericEvent *)wire;
+      if (!dri2Event(dpy, wire2->extension))
+	  return False;
+      type = wire2->evtype;
+   } else {
+      type = (wire->u.u.type & 0x7f) - info->codes->first_event;
+   }
+
+   switch (type) {
 
 #ifdef X_DRI2SwapBuffers
    case DRI2_BufferSwapComplete:
    {
       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
-      xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
-
-      /* Ignore swap events if we're not looking for them */
-      aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
-      if(!aevent->type)
-         return False;
-
-      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
-      aevent->send_event = (awire->type & 0x80) != 0;
-      aevent->display = dpy;
-      aevent->drawable = awire->drawable;
-      switch (awire->event_type) {
-      case DRI2_EXCHANGE_COMPLETE:
-	 aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
-	 break;
-      case DRI2_BLIT_COMPLETE:
-	 aevent->event_type = GLX_COPY_COMPLETE_INTEL;
-	 break;
-      case DRI2_FLIP_COMPLETE:
-	 aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
-	 break;
-      default:
-	 /* unknown swap completion type */
-	 return False;
+
+      if (dri2ServerSupportsSBC(dpy)) {
+	 xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire;
+
+	 /* Ignore swap events if we're not looking for them */
+	 aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
+	 if(!aevent->type)
+	    return False;
+
+	 aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
+	 aevent->send_event = (awire->type & 0x80) != 0;
+	 aevent->display = dpy;
+	 aevent->drawable = awire->drawable;
+	 switch (awire->swap_event_type) {
+	 case DRI2_EXCHANGE_COMPLETE:
+	    aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+	    break;
+	 case DRI2_BLIT_COMPLETE:
+	    aevent->event_type = GLX_COPY_COMPLETE_INTEL;
+	    break;
+	 case DRI2_FLIP_COMPLETE:
+	    aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
+	    break;
+	 default:
+	    /* unknown swap completion type */
+	    return False;
+	 }
+	 aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
+	 aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
+	 aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
+      } else {
+	 xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
+	 /* Ignore swap events if we're not looking for them */
+	 aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
+	 if(!aevent->type)
+	    return False;
+
+	 aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
+	 aevent->send_event = (awire->type & 0x80) != 0;
+	 aevent->display = dpy;
+	 aevent->drawable = awire->drawable;
+	 switch (awire->event_type) {
+	 case DRI2_EXCHANGE_COMPLETE:
+	    aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+	    break;
+	 case DRI2_BLIT_COMPLETE:
+	    aevent->event_type = GLX_COPY_COMPLETE_INTEL;
+	    break;
+	 case DRI2_FLIP_COMPLETE:
+	    aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
+	    break;
+	 default:
+	    /* unknown swap completion type */
+	    return False;
+	 }
+	 aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
+	 aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
+	 aevent->sbc = 0;
       }
-      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
-      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
-      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
       return True;
    }
 #endif
@@ -184,11 +226,12 @@ DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
 }
 
 Bool
-DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
+DRI2QueryExtension(Display * dpy, int *extBase, int *eventBase, int *errorBase)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 
    if (XextHasExtension(info)) {
+      *extBase = info->codes->major_opcode;
       *eventBase = info->codes->first_event;
       *errorBase = info->codes->first_error;
       return True;
@@ -241,6 +284,8 @@ DRI2QueryVersion(Display * dpy, int *major, int *minor)
        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
    }
 
+   XESetWireToEvent(dpy, GenericEvent, DRI2WireToEvent);
+
    return True;
 }
 
diff --git a/src/glx/dri2.h b/src/glx/dri2.h
index 114e9f8..b3a9918 100644
--- a/src/glx/dri2.h
+++ b/src/glx/dri2.h
@@ -46,7 +46,8 @@ typedef struct
 } DRI2Buffer;
 
 extern Bool
-DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
+DRI2QueryExtension(Display * display, int *extBase, int *eventBase,
+		   int *errorBase);
 
 extern Bool
 DRI2QueryVersion(Display * display, int *major, int *minor);
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index fc0237a..19be513 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -55,12 +55,14 @@
 #define DRI_CONF_VBLANK_ALWAYS_SYNC 3
 
 #undef DRI2_MINOR
-#define DRI2_MINOR 1
+#define DRI2_MINOR 4
 
 struct dri2_display
 {
    __GLXDRIdisplay base;
 
+   int majorOpcode;
+
    /*
     ** XFree86-DRI version information
     */
@@ -791,6 +793,28 @@ static const struct glx_screen_vtable dri2_screen_vtable = {
    dri2_create_context
 };
 
+int
+dri2ServerSupportsSBC(Display *dpy)
+{
+   struct glx_display *dpyPriv = __glXInitialize(dpy);
+   struct dri2_display *pdp =
+      (struct dri2_display *) dpyPriv->dri2Display;
+
+   if (pdp->driMajor > 1 || (pdp->driMajor == 1 && pdp->driMinor > 3))
+      return 1;
+
+   return 0;
+}
+
+int dri2Event(Display *dpy, int extension)
+{
+   struct glx_display *dpyPriv = __glXInitialize(dpy);
+   struct dri2_display *pdp =
+      (struct dri2_display *) dpyPriv->dri2Display;
+
+   return pdp->majorOpcode == extension;
+}
+
 static struct glx_screen *
 dri2CreateScreen(int screen, struct glx_display * priv)
 {
@@ -973,9 +997,9 @@ _X_HIDDEN __GLXDRIdisplay *
 dri2CreateDisplay(Display * dpy)
 {
    struct dri2_display *pdp;
-   int eventBase, errorBase, i;
+   int extBase, eventBase, errorBase, i;
 
-   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
+   if (!DRI2QueryExtension(dpy, &extBase, &eventBase, &errorBase))
       return NULL;
 
    pdp = Xmalloc(sizeof *pdp);
@@ -987,6 +1011,7 @@ dri2CreateDisplay(Display * dpy)
       return NULL;
    }
 
+   pdp->majorOpcode = extBase;
    pdp->driPatch = 0;
    pdp->swapAvailable = (pdp->driMinor >= 2);
    pdp->invalidateAvailable = (pdp->driMinor >= 3);
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 2b6966f..755a66d 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -149,6 +149,8 @@ extern __GLXDRIdisplay *driCreateDisplay(Display * dpy);
 extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
 extern void dri2InvalidateBuffers(Display *dpy, XID drawable);
 extern unsigned dri2GetSwapEventType(Display *dpy, XID drawable);
+extern int dri2ServerSupportsSBC(Display *dpy);
+extern int dri2Event(Display *dpy, int extension);
 
 
 /*
-- 
1.7.4.1



More information about the dri-devel mailing list