From 8c3b86787acf525df24a3b147da73398b7d1571c Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Fri, 27 Jan 2012 15:30:12 -0800 Subject: [PATCH] gl: Fix gl-source-surface test When painting a GL surface pattern from one context to a a surface of another context, be careful to manage the multiple contexts so that they do not stomp on each other. [ickle: Preserve fast path for GL subsurfaces] --- src/cairo-gl-operand.c | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index bc5e54192..660b407aa 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -86,10 +86,15 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand, sub = (cairo_surface_subsurface_t *) src->surface; - if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_GL) { + if (sub->snapshot && + sub->snapshot->type == CAIRO_SURFACE_TYPE_GL && + sub->snapshot->device == dst->base.device) + { surface = (cairo_gl_surface_t *) cairo_surface_reference (sub->snapshot); - } else { + } + else + { status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; @@ -167,6 +172,8 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand, } surface = (cairo_gl_surface_t *) sub->target; + if (surface->base.device != dst->base.device) + return CAIRO_INT_STATUS_UNSUPPORTED; /* Translate the matrix from * (unnormalized src -> unnormalized src) to @@ -211,6 +218,9 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand, return CAIRO_INT_STATUS_UNSUPPORTED; } + if (surface->base.device != dst->base.device) + return CAIRO_INT_STATUS_UNSUPPORTED; + *operand = surface->operand; attributes = &operand->texture.attributes; @@ -234,6 +244,12 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, cairo_gl_surface_t *surface; cairo_gl_context_t *ctx; cairo_surface_t *image; + cairo_bool_t src_is_gl_surface = FALSE; + + if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface; + src_is_gl_surface = src_surface->type == CAIRO_SURFACE_TYPE_GL; + } status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) @@ -243,22 +259,39 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, _cairo_gl_surface_create_scratch (ctx, CAIRO_CONTENT_COLOR_ALPHA, extents->width, extents->height); - image = cairo_surface_map_to_image (&surface->base, NULL); + + /* If the pattern is a GL surface, it belongs to some other GL context, + so we need to release this device while we paint it to the image. */ + if (src_is_gl_surface) { + status = _cairo_gl_context_release (ctx, status); + if (unlikely (status)) + goto fail; + } + status = _cairo_surface_offset_paint (image, extents->x, extents->y, CAIRO_OPERATOR_SOURCE, _src, NULL); + + if (src_is_gl_surface) { + status = _cairo_gl_context_acquire (dst->base.device, &ctx); + if (unlikely (status)) + goto fail; + } + cairo_surface_unmap_image (&surface->base, image); status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return status; - } + if (unlikely (status)) + goto fail; *operand = surface->operand; operand->texture.owns_surface = surface; operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx; operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy; return CAIRO_STATUS_SUCCESS; + +fail: + cairo_surface_destroy (&surface->base); + return status; } void