[cairo] [PATCH] gl: fix wrong references of texture in another gl_ctx
Yuanhan Liu
yuanhan.liu at linux.intel.com
Thu May 24 04:37:49 PDT 2012
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 <yuanhan.liu at linux.intel.com>
---
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
More information about the cairo
mailing list