summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-04-19 18:45:44 +0200
committerBenjamin Otte <otte@redhat.com>2010-04-23 23:34:45 +0200
commit263d7eaf860b84a99d31a7aae2ba11148571d03f (patch)
tree4ab076caee422243a8ed957abf5371e889850680
parentda34cf0b77422abe739ac4b6e060d68956dfedbb (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.h2
-rw-r--r--src/cairo-device.c10
-rw-r--r--src/cairo-gl-private.h2
-rw-r--r--src/cairo-gl-surface.c13
-rw-r--r--src/cairo-glx-context.c36
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;