From 6748d85297580474ff0d440915841e9fa9e1fe8e Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Fri, 17 Apr 2015 19:24:52 +0200 Subject: [PATCH] glx/dri3: Use a separate xcb connection for Present events 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. Signed-off-by: Axel Davy --- 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