diff options
author | Benjamin Otte <otte@redhat.com> | 2010-04-19 18:45:44 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-04-23 23:34:45 +0200 |
commit | 263d7eaf860b84a99d31a7aae2ba11148571d03f (patch) | |
tree | 4ab076caee422243a8ed957abf5371e889850680 | |
parent | da34cf0b77422abe739ac4b6e060d68956dfedbb (diff) |
glx: Make _glx_acquire/release() lock the X device
This avoids crashes when GLX and X are used at the same time.
-rw-r--r-- | src/cairo-device-private.h | 2 | ||||
-rw-r--r-- | src/cairo-device.c | 10 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 2 | ||||
-rw-r--r-- | src/cairo-gl-surface.c | 13 | ||||
-rw-r--r-- | src/cairo-glx-context.c | 36 |
5 files changed, 52 insertions, 11 deletions
diff --git a/src/cairo-device-private.h b/src/cairo-device-private.h index 54ca4c04..91dfdf95 100644 --- a/src/cairo-device-private.h +++ b/src/cairo-device-private.h @@ -57,7 +57,7 @@ struct _cairo_device { struct _cairo_device_backend { cairo_device_type_t type; - void (*lock) (void *device); + cairo_status_t (*lock) (void *device); void (*unlock) (void *device); void (*flush) (void *device); diff --git a/src/cairo-device.c b/src/cairo-device.c index 9befb59a..9a5059c4 100644 --- a/src/cairo-device.c +++ b/src/cairo-device.c @@ -229,8 +229,14 @@ cairo_device_acquire (cairo_device_t *device) CAIRO_MUTEX_LOCK (device->mutex); if (device->mutex_depth++ == 0) { - if (device->backend->lock != NULL) - device->backend->lock (device); + if (device->backend->lock != NULL) { + cairo_status_t status = device->backend->lock (device); + if (unlikely (status)) { + device->mutex_depth--; + CAIRO_MUTEX_UNLOCK (device->mutex); + return status; + } + } } return CAIRO_STATUS_SUCCESS; diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index 8512ab59..90f0ebaf 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -137,7 +137,7 @@ typedef struct _cairo_gl_context { cairo_gl_glyph_cache_t glyph_cache[2]; cairo_list_t fonts; - void (*acquire) (void *ctx); + cairo_status_t (*acquire) (void *ctx); void (*release) (void *ctx); void (*make_current) (void *ctx, cairo_gl_surface_t *surface); diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index d4028d57..7af90175 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -67,12 +67,12 @@ static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface) return surface->backend == &_cairo_gl_surface_backend; } -static void +static cairo_status_t _gl_lock (void *device) { cairo_gl_context_t *ctx = (cairo_gl_context_t *) device; - ctx->acquire (ctx); + return ctx->acquire (ctx); } static void @@ -1031,7 +1031,12 @@ static cairo_status_t _cairo_gl_surface_finish (void *abstract_surface) { cairo_gl_surface_t *surface = abstract_surface; - cairo_gl_context_t *ctx = (cairo_gl_context_t *) surface->base.device; + cairo_gl_context_t *ctx; + cairo_status_t status; + + status = _cairo_gl_context_acquire (surface->base.device, &ctx); + if (unlikely (status)) + return status; glDeleteFramebuffersEXT (1, &surface->fb); if (surface->owns_tex) @@ -1040,6 +1045,8 @@ _cairo_gl_surface_finish (void *abstract_surface) if (ctx->current_target == surface) ctx->current_target = NULL; + _cairo_gl_context_release (ctx); + return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-glx-context.c b/src/cairo-glx-context.c index e261cf88..c59eb214 100644 --- a/src/cairo-glx-context.c +++ b/src/cairo-glx-context.c @@ -42,6 +42,8 @@ #include "cairo-error-private.h" +#include <cairo-xlib.h> + #include <X11/Xutil.h> /* XXX needs hooking into XCloseDisplay() */ @@ -49,6 +51,7 @@ typedef struct _cairo_glx_context { cairo_gl_context_t base; + cairo_device_t *xdevice; Display *display; Window dummy_window; GLXContext context; @@ -63,10 +66,15 @@ typedef struct _cairo_glx_surface { Window win; } cairo_glx_surface_t; -static void +static cairo_status_t _glx_acquire (void *abstract_ctx) { cairo_glx_context_t *ctx = abstract_ctx; + cairo_status_t status; + + status = cairo_device_acquire (ctx->xdevice); + if (unlikely (status)) + return status; ctx->prev_context = glXGetCurrentContext (); ctx->prev_drawable = glXGetCurrentDrawable (); @@ -74,6 +82,8 @@ _glx_acquire (void *abstract_ctx) /* XXX: This is necessary with current code, but shouldn't be */ if (ctx->prev_context != ctx->context) glXMakeCurrent (ctx->display, ctx->dummy_window, ctx->context); + + return CAIRO_STATUS_SUCCESS; } static void @@ -96,6 +106,8 @@ _glx_release (void *abstract_ctx) glXMakeCurrent (ctx->display, ctx->prev_drawable, ctx->prev_context); + + cairo_device_release (ctx->xdevice); } static void @@ -113,10 +125,16 @@ _glx_destroy (void *abstract_ctx) { cairo_glx_context_t *ctx = abstract_ctx; - if (ctx->dummy_window != None) - XDestroyWindow (ctx->display, ctx->dummy_window); + if (! cairo_device_acquire (ctx->xdevice)) { + if (ctx->dummy_window != None) + XDestroyWindow (ctx->display, ctx->dummy_window); + + glXMakeCurrent (ctx->display, 0, 0); + + cairo_device_release (ctx->xdevice); + } - glXMakeCurrent (ctx->display, 0, 0); + cairo_device_destroy (ctx->xdevice); } static cairo_status_t @@ -177,6 +195,12 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx) cairo_glx_context_t *ctx; cairo_status_t status; Window dummy = None; + cairo_device_t *xdevice; + + xdevice = cairo_xlib_device_create (dpy); + status = cairo_device_acquire (xdevice); + if (unlikely (status)) + return _cairo_gl_context_create_in_error (status); status = _glx_dummy_ctx (dpy, gl_ctx, &dummy); if (unlikely (status)) @@ -186,6 +210,7 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx) if (unlikely (ctx == NULL)) return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); + ctx->xdevice = xdevice; ctx->display = dpy; ctx->dummy_window = dummy; ctx->context = gl_ctx; @@ -201,9 +226,12 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx) status = _cairo_gl_context_init (&ctx->base); if (unlikely (status)) { free (ctx); + cairo_device_release (xdevice); + cairo_device_destroy (xdevice); return _cairo_gl_context_create_in_error (status); } + /* releases the previously acquired xdevice */ ctx->base.release (ctx); return &ctx->base.base; |