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]
This commit is contained in:
Martin Robinson 2012-01-27 15:30:12 -08:00 committed by Chris Wilson
parent b52296a435
commit 8c3b86787a

View file

@ -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