[Mesa-dev] [RFC 1/1] glx: port dri2GetBuffers/dri2GetBuffersWithFormat to XCB

Gregory Hainaut gregory.hainaut at gmail.com
Wed Apr 26 08:07:47 UTC 2017


By default Xlib isn't thread safe so we better avoid it when gl thread
is enabled.

It will help applications that use XCB. But it will still crash if
applications are still relying on Xlib (without XInitThread).

Note: those dri2* functions are typically called by gallium/mesa state
tracker to handle new backbuffer allocation. When the old backbuffer was
previously invalidated due to vsync.

Signed-off-by: Gregory Hainaut <gregory.hainaut at gmail.com>
---
 src/glx/dri2.c     | 118 -----------------------------------------------------
 src/glx/dri2.h     |  25 ------------
 src/glx/dri2_glx.c |  64 +++++++++++++++++++++--------
 3 files changed, 47 insertions(+), 160 deletions(-)

diff --git a/src/glx/dri2.c b/src/glx/dri2.c
index f00b96525a..eed899e237 100644
--- a/src/glx/dri2.c
+++ b/src/glx/dri2.c
@@ -391,138 +391,20 @@ DRI2DestroyDrawable(Display * dpy, XID drawable)
 
    LockDisplay(dpy);
    GetReq(DRI2DestroyDrawable, req);
    req->reqType = info->codes->major_opcode;
    req->dri2ReqType = X_DRI2DestroyDrawable;
    req->drawable = drawable;
    UnlockDisplay(dpy);
    SyncHandle();
 }
 
-DRI2Buffer *
-DRI2GetBuffers(Display * dpy, XID drawable,
-               int *width, int *height,
-               unsigned int *attachments, int count, int *outCount)
-{
-   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
-   xDRI2GetBuffersReply rep;
-   xDRI2GetBuffersReq *req;
-   DRI2Buffer *buffers;
-   xDRI2Buffer repBuffer;
-   CARD32 *p;
-   int i;
-
-   XextCheckExtension(dpy, info, dri2ExtensionName, False);
-
-   LockDisplay(dpy);
-   GetReqExtra(DRI2GetBuffers, count * 4, req);
-   req->reqType = info->codes->major_opcode;
-   req->dri2ReqType = X_DRI2GetBuffers;
-   req->drawable = drawable;
-   req->count = count;
-   p = (CARD32 *) & req[1];
-   for (i = 0; i < count; i++)
-      p[i] = attachments[i];
-
-   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
-
-   *width = rep.width;
-   *height = rep.height;
-   *outCount = rep.count;
-
-   buffers = malloc(rep.count * sizeof buffers[0]);
-   if (buffers == NULL) {
-      _XEatData(dpy, rep.count * sizeof repBuffer);
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
-
-   for (i = 0; i < rep.count; i++) {
-      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
-      buffers[i].attachment = repBuffer.attachment;
-      buffers[i].name = repBuffer.name;
-      buffers[i].pitch = repBuffer.pitch;
-      buffers[i].cpp = repBuffer.cpp;
-      buffers[i].flags = repBuffer.flags;
-   }
-
-   UnlockDisplay(dpy);
-   SyncHandle();
-
-   return buffers;
-}
-
-
-DRI2Buffer *
-DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
-                         int *width, int *height,
-                         unsigned int *attachments, int count, int *outCount)
-{
-   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
-   xDRI2GetBuffersReply rep;
-   xDRI2GetBuffersReq *req;
-   DRI2Buffer *buffers;
-   xDRI2Buffer repBuffer;
-   CARD32 *p;
-   int i;
-
-   XextCheckExtension(dpy, info, dri2ExtensionName, False);
-
-   LockDisplay(dpy);
-   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
-   req->reqType = info->codes->major_opcode;
-   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
-   req->drawable = drawable;
-   req->count = count;
-   p = (CARD32 *) & req[1];
-   for (i = 0; i < (count * 2); i++)
-      p[i] = attachments[i];
-
-   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
-
-   *width = rep.width;
-   *height = rep.height;
-   *outCount = rep.count;
-
-   buffers = malloc(rep.count * sizeof buffers[0]);
-   if (buffers == NULL) {
-      _XEatData(dpy, rep.count * sizeof repBuffer);
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
-
-   for (i = 0; i < rep.count; i++) {
-      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
-      buffers[i].attachment = repBuffer.attachment;
-      buffers[i].name = repBuffer.name;
-      buffers[i].pitch = repBuffer.pitch;
-      buffers[i].cpp = repBuffer.cpp;
-      buffers[i].flags = repBuffer.flags;
-   }
-
-   UnlockDisplay(dpy);
-   SyncHandle();
-
-   return buffers;
-}
-
-
 void
 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
                CARD32 dest, CARD32 src)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    xDRI2CopyRegionReq *req;
    xDRI2CopyRegionReply rep;
 
    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
 
diff --git a/src/glx/dri2.h b/src/glx/dri2.h
index 4be5bf8eb8..c383e27123 100644
--- a/src/glx/dri2.h
+++ b/src/glx/dri2.h
@@ -30,29 +30,20 @@
  *   Kristian Høgsberg (krh at redhat.com)
  */
 
 #ifndef _DRI2_H_
 #define _DRI2_H_
 
 #include <xf86drm.h>
 #include <X11/extensions/Xfixes.h>
 #include <X11/extensions/dri2tokens.h>
 
-typedef struct
-{
-   unsigned int attachment;
-   unsigned int name;
-   unsigned int pitch;
-   unsigned int cpp;
-   unsigned int flags;
-} DRI2Buffer;
-
 struct glx_screen;
 
 extern Bool
 DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
 
 extern Bool
 DRI2QueryVersion(Display * display, int *major, int *minor);
 
 extern Bool
 DRI2Connect(Display * display, XID window,
@@ -60,32 +51,16 @@ DRI2Connect(Display * display, XID window,
 
 extern Bool
 DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
 
 extern void
 DRI2CreateDrawable(Display * display, XID drawable);
 
 extern void
 DRI2DestroyDrawable(Display * display, XID handle);
 
-extern DRI2Buffer*
-DRI2GetBuffers(Display * dpy, XID drawable,
-               int *width, int *height,
-               unsigned int *attachments, int count,
-               int *outCount);
-
-/**
- * \note
- * This function is only supported with DRI2 version 1.1 or later.
- */
-extern DRI2Buffer*
-DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
-                         int *width, int *height,
-                         unsigned int *attachments,
-                         int count, int *outCount);
-
 extern void
 DRI2CopyRegion(Display * dpy, XID drawable,
                XserverRegion region,
                CARD32 dest, CARD32 src);
 
 #endif
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 145f44d6e8..bb61985592 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -707,21 +707,21 @@ dri2DestroyScreen(struct glx_screen *base)
    free(psc);
 }
 
 /**
  * Process list of buffer received from the server
  *
  * Processes the list of buffers received in a reply from the server to either
  * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
  */
 static void
-process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
+process_buffers(struct dri2_drawable * pdraw, xcb_dri2_dri2_buffer_t * buffers,
                 unsigned count)
 {
    int i;
 
    pdraw->bufferCount = count;
    pdraw->have_fake_front = 0;
    pdraw->have_back = 0;
 
    /* This assumes the DRI2 buffer attachment tokens matches the
     * __DRIbuffer tokens. */
@@ -859,57 +859,87 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
     return ret;
 }
 
 static __DRIbuffer *
 dri2GetBuffers(__DRIdrawable * driDrawable,
                int *width, int *height,
                unsigned int *attachments, int count,
                int *out_count, void *loaderPrivate)
 {
    struct dri2_drawable *pdraw = loaderPrivate;
-   DRI2Buffer *buffers;
+   xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy);
+   xcb_dri2_dri2_buffer_t *buffers;
+   xcb_dri2_get_buffers_reply_t *reply;
+   xcb_dri2_get_buffers_cookie_t cookie;
 
-   buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
-                            width, height, attachments, count, out_count);
-   if (buffers == NULL)
+   (void) driDrawable;
+
+   cookie = xcb_dri2_get_buffers_unchecked(c, pdraw->base.xDrawable,
+                                           count, count, attachments);
+
+   reply = xcb_dri2_get_buffers_reply(c, cookie, NULL);
+   if (reply == NULL)
       return NULL;
 
-   pdraw->width = *width;
-   pdraw->height = *height;
+   buffers = xcb_dri2_get_buffers_buffers(reply);
+   if (buffers == NULL) {
+      free(reply);
+      return NULL;
+   }
+
+   *out_count = reply->count;
+   pdraw->width = *width = reply->width;
+   pdraw->height = *height = reply->height;
    process_buffers(pdraw, buffers, *out_count);
 
-   free(buffers);
+   free(reply);
 
    return pdraw->buffers;
 }
 
 static __DRIbuffer *
 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
                          int *width, int *height,
                          unsigned int *attachments, int count,
                          int *out_count, void *loaderPrivate)
 {
    struct dri2_drawable *pdraw = loaderPrivate;
-   DRI2Buffer *buffers;
+   xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy);
+   xcb_dri2_dri2_buffer_t *buffers;
+   xcb_dri2_get_buffers_with_format_reply_t *reply;
+   xcb_dri2_get_buffers_with_format_cookie_t cookie;
+   xcb_dri2_attach_format_t *format_attachments;
+
+   (void) driDrawable;
+
+   format_attachments = (xcb_dri2_attach_format_t *)attachments;
+   cookie = xcb_dri2_get_buffers_with_format_unchecked(c,
+                                                       pdraw->base.xDrawable,
+                                                       count, count,
+                                                       format_attachments);
+
+   reply = xcb_dri2_get_buffers_with_format_reply(c, cookie, NULL);
+   if (reply == NULL)
+      return NULL;
 
-   buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
-                                      pdraw->base.xDrawable,
-                                      width, height, attachments,
-                                      count, out_count);
-   if (buffers == NULL)
+   buffers = xcb_dri2_get_buffers_with_format_buffers(reply);
+   if (buffers == NULL) {
+      free(reply);
       return NULL;
+   }
 
-   pdraw->width = *width;
-   pdraw->height = *height;
+   *out_count = reply->count;
+   pdraw->width = *width = reply->width;
+   pdraw->height = *height = reply->height;
    process_buffers(pdraw, buffers, *out_count);
 
-   free(buffers);
+   free(reply);
 
    return pdraw->buffers;
 }
 
 static int
 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
 {
    xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
    struct dri2_drawable *priv =  (struct dri2_drawable *) pdraw;
    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
-- 
2.11.0



More information about the mesa-dev mailing list