GLX/DRI2: handle swap event swap count wrapping
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 6 May 2011 17:31:24 +0000 (10:31 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 8 Jul 2011 19:38:20 +0000 (12:38 -0700)
Create a new GLX drawable struct to track client related info, and add a
wrap counter to it drawable and track it as we receive events.  This
allows us to support the full 64 bits of the event structure we pass to
the client even though the server only gives us a 32 bit count.

Reviewed-by: Michel Dänzer <michel@daenzer.net>
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
src/glx/dri2.c
src/glx/glx_pbuffer.c
src/glx/glxclient.h
src/glx/glxcmds.c
src/glx/glxext.c

index 8654a37688f588c19c6f976dd808934f96f3089a..229840d69195fcff74f674ddefb666d5bad93b3e 100644 (file)
@@ -88,6 +88,7 @@ static Bool
 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   struct glx_drawable *glxDraw;
 
    XextCheckExtension(dpy, info, dri2ExtensionName, False);
 
@@ -98,6 +99,9 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
    {
       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
       xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire;
+      __GLXDRIdrawable *pdraw;
+
+      pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable);
 
       /* Ignore swap events if we're not looking for them */
       aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
@@ -124,7 +128,13 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
       }
       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
-      aevent->sbc = awire->sbc;
+
+      glxDraw = GetGLXDrawable(dpy, pdraw->drawable);
+      if (awire->sbc < glxDraw->lastEventSbc)
+        glxDraw->eventSbcWrap += 0x100000000;
+      glxDraw->lastEventSbc = awire->sbc;
+      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
+
       return True;
    }
 #endif
index 0e74e7ccd0e92fe4c773f26259c89eb2b8cd0756..6738252a31d724a072ca019c8d276ec509670be8 100644 (file)
@@ -396,6 +396,7 @@ CreateDrawable(Display *dpy, struct glx_config *config,
                Drawable drawable, const int *attrib_list, CARD8 glxCode)
 {
    xGLXCreateWindowReq *req;
+   struct glx_drawable *glxDraw;
    CARD32 *data;
    unsigned int i;
    CARD8 opcode;
@@ -411,6 +412,10 @@ CreateDrawable(Display *dpy, struct glx_config *config,
    if (!opcode)
       return None;
 
+   glxDraw = Xmalloc(sizeof(*glxDraw));
+   if (!glxDraw)
+      return None;
+
    LockDisplay(dpy);
    GetReqExtra(GLXCreateWindow, 8 * i, req);
    data = (CARD32 *) (req + 1);
@@ -429,6 +434,11 @@ CreateDrawable(Display *dpy, struct glx_config *config,
    UnlockDisplay(dpy);
    SyncHandle();
 
+   if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) {
+      free(glxDraw);
+      return None;
+   }
+
    if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
       if (glxCode == X_GLXCreatePixmap)
          glxCode = X_GLXDestroyPixmap;
@@ -454,6 +464,7 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
 
    protocolDestroyDrawable(dpy, drawable, glxCode);
 
+   DestroyGLXDrawable(dpy, drawable);
    DestroyDRIDrawable(dpy, drawable, GL_FALSE);
 
    return;
index 06415288165c24a4776bd25d2fed08bdb8ca9ece..f91542661016eb9ff9f8ba0f7a90007a55a44e64 100644 (file)
@@ -567,6 +567,8 @@ struct glx_display
      */
    struct glx_screen **screens;
 
+   __glxHashTable *glXDrawHash;
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    __glxHashTable *drawHash;
 
@@ -579,6 +581,14 @@ struct glx_display
 #endif
 };
 
+struct glx_drawable {
+   XID xDrawable;
+   XID drawable;
+
+   uint32_t lastEventSbc;
+   int64_t eventSbcWrap;
+};
+
 extern int
 glx_screen_init(struct glx_screen *psc,
                int screen, struct glx_display * priv);
@@ -784,6 +794,12 @@ extern int
 applegl_create_display(struct glx_display *display);
 #endif
 
+
+extern struct glx_drawable *GetGLXDrawable(Display *dpy, GLXDrawable drawable);
+extern int InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw,
+                          XID xDrawable, GLXDrawable drawable);
+extern void DestroyGLXDrawable(Display *dpy, GLXDrawable drawable);
+
 extern struct glx_context dummyContext;
 
 extern struct glx_screen *
index 191b321ce327c2914d02fe4b05bbbb4f6ed6cb2c..fc0a07901a71a3281a2b3ba78bfed62df2c8e107 100644 (file)
@@ -90,6 +90,51 @@ GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable)
 
 #endif
 
+_X_HIDDEN struct glx_drawable *
+GetGLXDrawable(Display *dpy, GLXDrawable drawable)
+{
+   struct glx_display *priv = __glXInitialize(dpy);
+   struct glx_drawable *glxDraw;
+
+   if (priv == NULL)
+      return NULL;
+
+   if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0)
+      return glxDraw;
+
+   return NULL;
+}
+
+_X_HIDDEN int
+InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable,
+               GLXDrawable drawable)
+{
+   struct glx_display *priv = __glXInitialize(dpy);
+
+   if (!priv)
+      return -1;
+
+   glxDraw->xDrawable = xDrawable;
+   glxDraw->drawable = drawable;
+   glxDraw->lastEventSbc = 0;
+   glxDraw->eventSbcWrap = 0;
+
+   return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw);
+}
+
+_X_HIDDEN void
+DestroyGLXDrawable(Display *dpy, GLXDrawable drawable)
+{
+   struct glx_display *priv = __glXInitialize(dpy);
+   struct glx_drawable *glxDraw;
+
+   if (!priv)
+      return;
+
+   glxDraw = GetGLXDrawable(dpy, drawable);
+   __glxHashDelete(priv->glXDrawHash, drawable);
+   free(glxDraw);
+}
 
 /**
  * Get the GLX per-screen data structure associated with a GLX context.
@@ -608,6 +653,7 @@ glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
    return pixmap;
 #else
    xGLXCreateGLXPixmapReq *req;
+   struct glx_drawable *glxDraw;
    GLXPixmap xid;
    CARD8 opcode;
 
@@ -616,6 +662,10 @@ glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
       return None;
    }
 
+   glxDraw = Xmalloc(sizeof(*glxDraw));
+   if (!glxDraw)
+      return None;
+
    /* Send the glXCreateGLXPixmap request */
    LockDisplay(dpy);
    GetReq(GLXCreateGLXPixmap, req);
@@ -628,6 +678,11 @@ glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
    UnlockDisplay(dpy);
    SyncHandle();
 
+   if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
+      free(glxDraw);
+      return None;
+   }
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    do {
       /* FIXME: Maybe delay __DRIdrawable creation until the drawable
@@ -700,6 +755,8 @@ glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
    UnlockDisplay(dpy);
    SyncHandle();
 
+   DestroyGLXDrawable(dpy, glxpixmap);
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    {
       struct glx_display *const priv = __glXInitialize(dpy);
index 40a06a8612be2b2f230443bb7c660b1b4116c19c..8704c484f9687bd69b59e7f7683b0ac7b4893f43 100644 (file)
@@ -134,11 +134,19 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
    {
       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
       xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
+      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
       aevent->event_type = awire->event_type;
       aevent->drawable = awire->drawable;
       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
-      aevent->sbc = awire->sbc;
+
+      if (!glxDraw)
+        return False;
+
+      if (awire->sbc < glxDraw->lastEventSbc)
+        glxDraw->eventSbcWrap += 0x100000000;
+      glxDraw->lastEventSbc = awire->sbc;
+      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
       return True;
    }
    default:
@@ -227,6 +235,8 @@ glx_display_free(struct glx_display *priv)
    if (priv->serverGLXversion)
       Xfree((char *) priv->serverGLXversion);
 
+   __glxHashDestroy(priv->glXDrawHash);
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    __glxHashDestroy(priv->drawHash);
 
@@ -847,6 +857,8 @@ __glXInitialize(Display * dpy)
    XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
    XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
 
+   dpyPriv->glXDrawHash = __glxHashCreate();
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
    glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);