[PATCH] gl: fix wrong references of texture in another gl_ctx
Yuanhan Liu <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
If we do something like following: cr1 = cairo_create(surf1); cr2 = cairo_create(surf2); ... draw something to surf1 ... cairo_set_source_surface(cr2, surf1); cairo_rectangle(cr2, ..... ); cairo_fill(cr2); You will find the current code will reference a texture in cr1 gl context while drawing cr2. Thus it references a null texture and results to wrong rendering. This patch severs as fixing this issue(like gl-surface-source test case) by copying out the texture from cr1, then regenerating a new one to cr2. Signed-off-by: Yuanhan Liu <[email protected]> --- src/cairo-gl-composite.c | 77 +++++++++++++++++++++++++++++++++++++-- src/cairo-gl-glyphs.c | 3 +- src/cairo-gl-private.h | 4 ++- src/cairo-gl-spans-compositor.c | 5 +-- src/cairo-gl-surface.c | 7 ++++ src/cairo-gl-traps-compositor.c | 12 ++---- 6 files changed, 91 insertions(+), 17 deletions(-) diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index bcf41ec..97c6118 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -63,12 +63,83 @@ _cairo_gl_composite_set_source (cairo_gl_composite_t *setup, sample, extents); } +static cairo_status_t +_cairo_gl_composite_set_source_texture_operand (cairo_gl_composite_t *setup, + cairo_surface_t *src) +{ + cairo_gl_context_t *ctx; + cairo_gl_surface_t *src_gl_surf = (cairo_gl_surface_t *)src; + cairo_status_t status; + GLvoid *pixels; + GLuint dst_tex; + GLint src_tex = src_gl_surf->operand.texture.tex; + int width = src_gl_surf->width; + int height = src_gl_surf->height; + int cpp = src_gl_surf->cpp; + GLenum format = src_gl_surf->format; + + + /* + * A flush is a need to keep things in order + * + * FIXME: or we may delay it at the draw time? + */ + cairo_surface_flush(src); + cairo_surface_flush(&setup->dst->base); + + /* Read the texture from src surface first */ + status = _cairo_gl_context_acquire(src->device, &ctx); + if (unlikely(status)) + return status; + + pixels = malloc(width * height * cpp); + glBindTexture(ctx->tex_target, src_tex); + glGetTexImage(ctx->tex_target, 0, format, GL_UNSIGNED_BYTE, pixels); + status = _cairo_gl_context_release(ctx, status); + if (unlikely(status)) + return status; + + + /* regenerate a texture in the dest surface */ + status = _cairo_gl_context_acquire(setup->dst->base.device, &ctx); + if (unlikely(status)) + goto fail; + + glGenTextures(1, &dst_tex); + glBindTexture(ctx->tex_target, dst_tex); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(ctx->tex_target, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, pixels); + + _cairo_gl_operand_destroy(&setup->src); + setup->src = src_gl_surf->operand; + setup->src.texture.tex = dst_tex; + + status = _cairo_gl_context_release(ctx, status); + +fail: + free(pixels); + return status; +} + void _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source) + const cairo_surface_t *src) { - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_operand_copy (&setup->src, source); + cairo_gl_operand_t *operand = source_to_operand(src); + + /* + * When we try to use a texture from another gl_ctx, we should + * handle it in a special way, like extract it from src_gl_ctx, + * then remake a texture in dst_gl_ctx. + */ + if ((operand && operand->type == CAIRO_GL_OPERAND_TEXTURE) && + (src->device && src->device != setup->dst->base.device)) { + _cairo_gl_composite_set_source_texture_operand(setup, src); + } else { + _cairo_gl_operand_destroy (&setup->src); + _cairo_gl_operand_copy (&setup->src, operand); + } } void diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index c2660ac..6afced9 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -252,8 +252,7 @@ render_glyphs (cairo_gl_surface_t *dst, if (source == NULL) { _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE); } else { - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (source)); + _cairo_gl_composite_set_source_operand (&setup, source); } diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index eb75cd9..f354c63 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -159,6 +159,8 @@ struct _cairo_gl_surface { cairo_gl_operand_t operand; int width, height; + int cpp; + GLenum format; GLuint tex; /* GL texture object containing our data. */ GLuint fb; /* GL framebuffer object wrapping our data. */ @@ -506,7 +508,7 @@ _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup, cairo_private void _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source); + const cairo_surface_t *src); cairo_private cairo_int_status_t _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c index 4c5cef6..ae8668f 100644 --- a/src/cairo-gl-spans-compositor.c +++ b/src/cairo-gl-spans-compositor.c @@ -327,7 +327,7 @@ static cairo_int_status_t copy_boxes (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, source_to_operand (src)); + _cairo_gl_composite_set_source_operand (&setup, src); _cairo_gl_operand_translate (&setup.src, -dx, -dy); status = _cairo_gl_composite_begin (&setup, &ctx); @@ -382,8 +382,7 @@ composite_boxes (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, - src_operand); + _cairo_gl_composite_set_source_operand(&setup, abstract_src); _cairo_gl_operand_translate (&setup.src, -src_x, -src_y); _cairo_gl_composite_set_mask_operand (&setup, diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index c2e9687..494363b 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -433,6 +433,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface; GLenum format; GLuint tex; + int cpp; glGenTextures (1, &tex); surface = (cairo_gl_surface_t *) @@ -454,10 +455,12 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, ASSERT_NOT_REACHED; case CAIRO_CONTENT_COLOR_ALPHA: format = GL_RGBA; + cpp = 4; break; case CAIRO_CONTENT_ALPHA: /* We want to be trying GL_ALPHA framebuffer objects here. */ format = GL_RGBA; + cpp = 4; break; case CAIRO_CONTENT_COLOR: /* GL_RGB is almost what we want here -- sampling 1 alpha when @@ -469,12 +472,16 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, * channel with 1 when blending. */ format = GL_RGBA; + cpp = 4; break; } glTexImage2D (ctx->tex_target, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); + surface->format = format; + surface->cpp = cpp; + return &surface->base; } diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c index 776b74c..b0f5bf8 100644 --- a/src/cairo-gl-traps-compositor.c +++ b/src/cairo-gl-traps-compositor.c @@ -172,8 +172,7 @@ composite_boxes (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); + _cairo_gl_composite_set_source_operand (&setup, abstract_src); _cairo_gl_composite_set_mask_operand (&setup, source_to_operand (abstract_mask)); @@ -212,8 +211,7 @@ composite (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); + _cairo_gl_composite_set_source_operand (&setup, abstract_src); _cairo_gl_composite_set_mask_operand (&setup, source_to_operand (abstract_mask)); @@ -354,8 +352,7 @@ composite_traps (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); + _cairo_gl_composite_set_source_operand (&setup, abstract_src); status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask); if (unlikely (status)) goto FAIL; @@ -451,8 +448,7 @@ composite_tristrip (void *_dst, if (unlikely (status)) goto FAIL; - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); + _cairo_gl_composite_set_source_operand (&setup, abstract_src); //_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0); -- 1.7.7.6 -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo