mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 03:28:09 +02:00
gl: Make code safe for multithreaded access
The code callss the gl device's acquire/release in cairo_device_acquire/release(). This way, external APIs can use these functions to prepare for rendering GL. Also adds code to unset the glx context if it wasn't set when acquiring the device. This allows multithreaded apps to work fine with just using cairo APIs, but might introduce penalties in single-threaded applications.
This commit is contained in:
parent
8f2e82cea3
commit
712919223d
4 changed files with 60 additions and 4 deletions
|
|
@ -104,6 +104,8 @@ cairo_egl_device_create (EGLDisplay dpy, EGLContext egl)
|
|||
ctx->display = dpy;
|
||||
ctx->context = egl;
|
||||
|
||||
ctx->base.acquire = NULL; /* FIXME */
|
||||
ctx->base.release = NULL; /* FIXME */
|
||||
ctx->base.make_current = _egl_make_current;
|
||||
ctx->base.swap_buffers = _egl_swap_buffers;
|
||||
ctx->base.destroy = _egl_destroy;
|
||||
|
|
|
|||
|
|
@ -136,7 +136,10 @@ typedef struct _cairo_gl_context {
|
|||
cairo_gl_glyph_cache_t glyph_cache[2];
|
||||
cairo_list_t fonts;
|
||||
|
||||
void (*make_current)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*acquire) (void *ctx);
|
||||
void (*release) (void *ctx);
|
||||
|
||||
void (*make_current) (void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*destroy) (void *ctx);
|
||||
} cairo_gl_context_t;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,23 @@ static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
|
|||
return surface->backend == &_cairo_gl_surface_backend;
|
||||
}
|
||||
|
||||
static void
|
||||
_gl_lock (void *device)
|
||||
{
|
||||
cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
|
||||
|
||||
ctx->acquire (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
_gl_unlock (void *device)
|
||||
{
|
||||
cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
|
||||
|
||||
ctx->release (ctx);
|
||||
ctx->current_target = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_gl_destroy (void *device)
|
||||
{
|
||||
|
|
@ -94,7 +111,8 @@ _gl_destroy (void *device)
|
|||
static const cairo_device_backend_t _cairo_gl_device_backend = {
|
||||
CAIRO_DEVICE_TYPE_GL,
|
||||
|
||||
NULL, NULL, /* lock, unlock */
|
||||
_gl_lock,
|
||||
_gl_unlock,
|
||||
|
||||
NULL, /* flush */
|
||||
NULL, /* finish */
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ typedef struct _cairo_glx_context {
|
|||
Display *display;
|
||||
Window dummy_window;
|
||||
GLXContext context;
|
||||
|
||||
GLXContext prev_context;
|
||||
GLXDrawable prev_drawable;
|
||||
} cairo_glx_context_t;
|
||||
|
||||
typedef struct _cairo_glx_surface {
|
||||
|
|
@ -61,8 +64,20 @@ typedef struct _cairo_glx_surface {
|
|||
} cairo_glx_surface_t;
|
||||
|
||||
static void
|
||||
_glx_make_current (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
_glx_acquire (void *abstract_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
|
||||
ctx->prev_context = glXGetCurrentContext ();
|
||||
ctx->prev_drawable = glXGetCurrentDrawable ();
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface;
|
||||
|
|
@ -71,6 +86,18 @@ _glx_make_current (void *abstract_ctx,
|
|||
glXMakeCurrent (ctx->display, surface->win, ctx->context);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_release (void *abstract_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
|
||||
if (ctx->prev_context != glXGetCurrentContext () ||
|
||||
ctx->prev_drawable != glXGetCurrentDrawable ())
|
||||
glXMakeCurrent (ctx->display,
|
||||
ctx->prev_drawable,
|
||||
ctx->prev_context);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_swap_buffers (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
|
|
@ -162,7 +189,11 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx)
|
|||
ctx->display = dpy;
|
||||
ctx->dummy_window = dummy;
|
||||
ctx->context = gl_ctx;
|
||||
ctx->prev_context = NULL;
|
||||
ctx->prev_drawable = None;
|
||||
|
||||
ctx->base.acquire = _glx_acquire;
|
||||
ctx->base.release = _glx_release;
|
||||
ctx->base.make_current = _glx_make_current;
|
||||
ctx->base.swap_buffers = _glx_swap_buffers;
|
||||
ctx->base.destroy = _glx_destroy;
|
||||
|
|
@ -173,6 +204,8 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx)
|
|||
return _cairo_gl_context_create_in_error (status);
|
||||
}
|
||||
|
||||
ctx->base.release (ctx);
|
||||
|
||||
return &ctx->base.base;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue