[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