[Mesa-dev] [PATCH] glx/dri3: Use a separate xcb connection for Present events

Axel Davy axel.davy at ens.fr
Sat Apr 18 01:10:48 PDT 2015


Previously glx was using the xcb connection from Xlib.
It is a problem for several reasons:
. There are issues if Xlib is used in another thread (Present event lost)
. Mixing Present events if you receive some for different windows (ie
the client is having more than one window it renders to)

This patch creates a per-context xcb connection to solve these issues.

Solves: https://bugs.freedesktop.org/show_bug.cgi?id=84252

Tested-by: Tobias Jakobi <tjakobi at math.uni-bielefeld.de>
Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
 src/glx/dri3_glx.c  | 56 ++++++++++++++++++++++++++++++++++++-----------------
 src/glx/dri3_priv.h |  1 +
 2 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 1ddc723..245d32f 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -122,6 +122,7 @@ dri3_destroy_context(struct glx_context *context)
    free((char *) context->extensions);
 
    (*psc->core->destroyContext) (pcp->driContext);
+   xcb_disconnect(pcp->xcb_connection);
 
    free(pcp);
 }
@@ -171,6 +172,9 @@ dri3_create_context_attribs(struct glx_screen *base,
    struct dri3_screen *psc = (struct dri3_screen *) base;
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
    __DRIcontext *shared = NULL;
+   Display *dpy = base->dpy;
+   int screen_num = DefaultScreen(dpy);
+   xcb_connection_t *c = NULL;
 
    uint32_t minor_ver = 1;
    uint32_t major_ver = 2;
@@ -198,6 +202,12 @@ dri3_create_context_attribs(struct glx_screen *base,
       shared = pcp_shared->driContext;
    }
 
+   /* Create XCB connection for present calls. Do not use the Xlib one,
+    * to prevent issues if application uses Xlib in another thread */
+   c = xcb_connect(DisplayString(dpy), &screen_num);
+   if (!c)
+      goto error_exit;
+
    pcp = calloc(1, sizeof *pcp);
    if (pcp == NULL) {
       *error = __DRI_CTX_ERROR_NO_MEMORY;
@@ -244,11 +254,14 @@ dri3_create_context_attribs(struct glx_screen *base,
       goto error_exit;
 
    pcp->base.vtable = &dri3_context_vtable;
+   pcp->xcb_connection = c;
 
    return &pcp->base;
 
 error_exit:
    free(pcp);
+   if (c)
+       xcb_disconnect(c);
 
    return NULL;
 }
@@ -284,8 +297,9 @@ static void
 dri3_destroy_drawable(__GLXDRIdrawable *base)
 {
    struct dri3_screen *psc = (struct dri3_screen *) base->psc;
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
-   xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
+   xcb_connection_t *c = pcp->xcb_connection;
    int i;
 
    (*psc->core->destroyDrawable) (pdraw->driDrawable);
@@ -455,8 +469,9 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_
 static bool
 dri3_wait_for_event(__GLXDRIdrawable *pdraw)
 {
-   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   xcb_connection_t *c = pcp->xcb_connection;
    xcb_generic_event_t *ev;
    xcb_present_generic_event_t *ge;
 
@@ -478,8 +493,9 @@ static int
 dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
                   int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
 {
-   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   xcb_connection_t *c = pcp->xcb_connection;
    uint32_t msc_serial;
 
    /* Ask for the an event for the target MSC */
@@ -578,7 +594,8 @@ dri3_drawable_gc(struct dri3_drawable *priv)
 {
    if (!priv->gc) {
       uint32_t v;
-      xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
+      struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
+      xcb_connection_t *c = pcp->xcb_connection;
 
       v = 0;
       xcb_create_gc(c,
@@ -637,7 +654,7 @@ dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    struct dri3_screen *psc = (struct dri3_screen *) pdraw->psc;
    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
-   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   xcb_connection_t *c = pcp->xcb_connection;
    struct dri3_buffer *back;
 
    unsigned flags = __DRI2_FLUSH_DRAWABLE;
@@ -701,7 +718,8 @@ static void
 dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
 {
    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
-   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
+   xcb_connection_t *c = pcp->xcb_connection;
 
    dri3_flush(psc, priv, __DRI2_FLUSH_DRAWABLE, 0);
 
@@ -838,10 +856,10 @@ dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw,
                          unsigned int format, int width, int height, int depth)
 {
    struct dri3_screen *psc = (struct dri3_screen *) glx_screen;
-   Display *dpy = glx_screen->dpy;
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_buffer *buffer;
    __DRIimage *pixmap_buffer;
-   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_connection_t *c = pcp->xcb_connection;
    xcb_pixmap_t pixmap;
    xcb_sync_fence_t sync_fence;
    struct xshmfence *shm_fence;
@@ -979,7 +997,8 @@ static void
 dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
 {
    struct dri3_screen   *psc = (struct dri3_screen *) pdraw->base.psc;
-   xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
+   xcb_connection_t *c = pcp->xcb_connection;
 
    if (buffer->own_pixmap)
       xcb_free_pixmap(c, buffer->pixmap);
@@ -999,7 +1018,8 @@ dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
 static void
 dri3_flush_present_events(struct dri3_drawable *priv)
 {
-   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
+   xcb_connection_t *c = pcp->xcb_connection;
 
    /* Check to see if any configuration changes have occurred
     * since we were last invoked
@@ -1024,7 +1044,8 @@ static int
 dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
 {
    struct dri3_drawable *priv = loaderPrivate;
-   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
+   xcb_connection_t *c = pcp->xcb_connection;
 
    /* First time through, go get the current drawable geometry
     */
@@ -1142,13 +1163,13 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
                        void *loaderPrivate)
 {
    struct dri3_drawable                 *pdraw = loaderPrivate;
+   struct dri3_context                  *pcp = (struct dri3_context *) __glXGetCurrentContext();
    int                                  buf_id = dri3_pixmap_buf_id(buffer_type);
    struct dri3_buffer                   *buffer = pdraw->buffers[buf_id];
    Pixmap                               pixmap;
    xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
    xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
    int                                  *fds;
-   Display                              *dpy;
    struct dri3_screen                   *psc;
    xcb_connection_t                     *c;
    xcb_sync_fence_t                     sync_fence;
@@ -1162,8 +1183,7 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
 
    pixmap = pdraw->base.xDrawable;
    psc = (struct dri3_screen *) pdraw->base.psc;
-   dpy = psc->base.dpy;
-   c = XGetXCBConnection(dpy);
+   c = pcp->xcb_connection;
 
    buffer = calloc(1, sizeof (struct dri3_buffer));
    if (!buffer)
@@ -1281,7 +1301,7 @@ dri3_get_buffer(__DRIdrawable *driDrawable,
    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *priv = loaderPrivate;
    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
-   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   xcb_connection_t *c = pcp->xcb_connection;
    struct dri3_buffer      *buffer;
    int                  buf_id;
 
@@ -1522,8 +1542,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
-   Display *dpy = priv->base.psc->dpy;
-   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_connection_t *c = pcp->xcb_connection;
    struct dri3_buffer *back;
    int64_t ret = 0;
    uint32_t options = XCB_PRESENT_OPTION_NONE;
@@ -1636,8 +1655,9 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
 static int
 dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
 {
-   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+   struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   xcb_connection_t *c = pcp->xcb_connection;
    int back_id = DRI3_BACK_ID(dri3_find_back(c, priv));
 
    if (back_id < 0 || !priv->buffers[back_id])
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index 1604449..99ccb82 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -145,6 +145,7 @@ struct dri3_context
 {
    struct glx_context base;
    __DRIcontext *driContext;
+   xcb_connection_t *xcb_connection;
 };
 
 #define DRI3_MAX_BACK   4
-- 
2.1.0



More information about the mesa-dev mailing list