[Mesa-dev] [PATCH v4] glx/dri3: Use a separate xcb connection for Present events
Axel Davy
axel.davy at ens.fr
Sun Apr 19 13:53:55 PDT 2015
Previously glx was using the xcb connection from Xlib.
It is a problem because there are issues if Xlib is used
in another thread (Present event lost)
This patch creates a per-context xcb connection to solve this issue.
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>
v2: use xcb_connection_has_error to check if connection failed, instead
of comparing to NULL (xcb_connect never returns NULL)
v3: put the xcb_connection in dri3_screen, instead of dri3_context
v4: add XSync before the xcb_get_geometry call to prevent drawable errors
---
src/glx/dri3_glx.c | 59 ++++++++++++++++++++++++++++++++---------------------
src/glx/dri3_priv.h | 2 ++
2 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 1ddc723..921fb3d 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -285,7 +285,7 @@ dri3_destroy_drawable(__GLXDRIdrawable *base)
{
struct dri3_screen *psc = (struct dri3_screen *) base->psc;
struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
- xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy);
+ xcb_connection_t *c = psc->xcb_connection;
int i;
(*psc->core->destroyDrawable) (pdraw->driDrawable);
@@ -455,8 +455,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_drawable *priv = (struct dri3_drawable *) pdraw;
+ struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
xcb_generic_event_t *ev;
xcb_present_generic_event_t *ge;
@@ -478,8 +479,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_drawable *priv = (struct dri3_drawable *) pdraw;
+ struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
uint32_t msc_serial;
/* Ask for the an event for the target MSC */
@@ -578,7 +580,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_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
v = 0;
xcb_create_gc(c,
@@ -637,7 +640,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 = psc->xcb_connection;
struct dri3_buffer *back;
unsigned flags = __DRI2_FLUSH_DRAWABLE;
@@ -701,7 +704,7 @@ 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);
+ xcb_connection_t *c = psc->xcb_connection;
dri3_flush(psc, priv, __DRI2_FLUSH_DRAWABLE, 0);
@@ -838,10 +841,9 @@ 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_buffer *buffer;
__DRIimage *pixmap_buffer;
- xcb_connection_t *c = XGetXCBConnection(dpy);
+ xcb_connection_t *c = psc->xcb_connection;
xcb_pixmap_t pixmap;
xcb_sync_fence_t sync_fence;
struct xshmfence *shm_fence;
@@ -979,7 +981,7 @@ 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);
+ xcb_connection_t *c = psc->xcb_connection;
if (buffer->own_pixmap)
xcb_free_pixmap(c, buffer->pixmap);
@@ -999,7 +1001,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_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
/* Check to see if any configuration changes have occurred
* since we were last invoked
@@ -1024,7 +1027,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_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
/* First time through, go get the current drawable geometry
*/
@@ -1064,6 +1068,9 @@ dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
priv->eid,
priv->stamp);
+ /* Make sure the drawable creation is done */
+ XSync(priv->base.psc->dpy, false);
+
geom_cookie = xcb_get_geometry(c, priv->base.xDrawable);
geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
@@ -1148,7 +1155,6 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
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 +1168,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 = psc->xcb_connection;
buffer = calloc(1, sizeof (struct dri3_buffer));
if (!buffer)
@@ -1281,7 +1286,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 = psc->xcb_connection;
struct dri3_buffer *buffer;
int buf_id;
@@ -1522,8 +1527,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 = psc->xcb_connection;
struct dri3_buffer *back;
int64_t ret = 0;
uint32_t options = XCB_PRESENT_OPTION_NONE;
@@ -1636,8 +1640,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_drawable *priv = (struct dri3_drawable *) pdraw;
+ struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+ xcb_connection_t *c = psc->xcb_connection;
int back_id = DRI3_BACK_ID(dri3_find_back(c, priv));
if (back_id < 0 || !priv->buffers[back_id])
@@ -1654,13 +1659,12 @@ dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
* Wrapper around xcb_dri3_open
*/
static int
-dri3_open(Display *dpy,
+dri3_open(xcb_connection_t *c,
Window root,
CARD32 provider)
{
xcb_dri3_open_cookie_t cookie;
xcb_dri3_open_reply_t *reply;
- xcb_connection_t *c = XGetXCBConnection(dpy);
int fd;
cookie = xcb_dri3_open(c,
@@ -1694,6 +1698,7 @@ dri3_destroy_screen(struct glx_screen *base)
(*psc->core->destroyScreen) (psc->driScreen);
driDestroyConfigs(psc->driver_configs);
close(psc->fd);
+ xcb_disconnect(psc->xcb_connection);
free(psc);
}
@@ -1884,7 +1889,7 @@ static const struct glx_screen_vtable dri3_screen_vtable = {
static struct glx_screen *
dri3_create_screen(int screen, struct glx_display * priv)
{
- xcb_connection_t *c = XGetXCBConnection(priv->dpy);
+ xcb_connection_t *c = NULL;
const __DRIconfig **driver_configs;
const __DRIextension **extensions;
const struct dri3_display *const pdp = (struct dri3_display *)
@@ -1893,20 +1898,28 @@ dri3_create_screen(int screen, struct glx_display * priv)
__GLXDRIscreen *psp;
struct glx_config *configs = NULL, *visuals = NULL;
char *driverName, *deviceName, *tmp;
- int i;
+ int screen_num, i;
+
+ /* Create XCB connection for present calls. Do not use the Xlib one,
+ * to prevent issues if application uses Xlib in another thread */
+ screen_num = screen;
+ c = xcb_connect(DisplayString(priv->dpy), &screen_num);
+ if (xcb_connection_has_error(c))
+ return NULL;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
return NULL;
psc->fd = -1;
+ psc->xcb_connection = c;
if (!glx_screen_init(&psc->base, screen, priv)) {
free(psc);
return NULL;
}
- psc->fd = dri3_open(priv->dpy, RootWindow(priv->dpy, screen), None);
+ psc->fd = dri3_open(c, RootWindow(priv->dpy, screen), None);
if (psc->fd < 0) {
int conn_error = xcb_connection_has_error(c);
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index 1604449..a6f3d00 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -139,6 +139,8 @@ struct dri3_screen {
int is_different_gpu;
int show_fps_interval;
+
+ xcb_connection_t *xcb_connection;
};
struct dri3_context
--
2.1.0
More information about the mesa-dev
mailing list