[cairo] [PATCH] gl: fix bug when the source and destination is the same surface.

Chuanbo Weng strgnm at gmail.com
Mon Dec 26 01:12:08 PST 2011


When the source and destination is the same surface, drawing error
will occur. So we have to create a new surface when init surface
and subsurface operand. This fix issue in self-copy and subsurface
test case (except gl-window).
---
 src/cairo-gl-operand.c |   77 +++++++++++++++++++++++++----------------------
 1 files changed, 41 insertions(+), 36 deletions(-)

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index bc5e541..e32d0a8 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -151,41 +151,10 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 				   const cairo_rectangle_int_t *sample,
 				   const cairo_rectangle_int_t *extents)
 {
-    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
-    cairo_surface_subsurface_t *sub;
-    cairo_gl_surface_t *surface;
-    cairo_surface_attributes_t *attributes;
-
-    sub = (cairo_surface_subsurface_t *) src->surface;
-
-    if (sample->x < 0 || sample->y < 0 ||
-	sample->x + sample->width  > sub->extents.width ||
-	sample->y + sample->height > sub->extents.height)
-    {
-	return _cairo_gl_subsurface_clone_operand_init (operand, _src,
+    /* To avoid the drawing error when the source and destination
+     * is the same surface, we have to create a new surface*/
+    return _cairo_gl_subsurface_clone_operand_init (operand, _src,
 							dst, sample, extents);
-    }
-
-    surface = (cairo_gl_surface_t *) sub->target;
-
-    /* Translate the matrix from
-     * (unnormalized src -> unnormalized src) to
-     * (unnormalized dst -> unnormalized src)
-     */
-    *operand = surface->operand;
-
-    attributes = &operand->texture.attributes;
-    attributes->matrix = src->base.matrix;
-    attributes->matrix.x0 += sub->extents.x;
-    attributes->matrix.y0 += sub->extents.y;
-    cairo_matrix_multiply (&attributes->matrix,
-			   &attributes->matrix,
-			   &surface->operand.texture.attributes.matrix);
-
-    attributes->extend = src->base.extend;
-    attributes->filter = src->base.filter;
-    attributes->has_component_alpha = src->base.has_component_alpha;
-    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -196,9 +165,13 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
 				const cairo_rectangle_int_t *extents)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
-    cairo_gl_surface_t *surface;
+    cairo_gl_surface_t *surface, *temp_surface;
     cairo_surface_attributes_t *attributes;
 
+    cairo_gl_context_t *ctx;
+    cairo_status_t status;
+    cairo_surface_pattern_t local_pattern;
+
     surface = (cairo_gl_surface_t *) src->surface;
     if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -211,7 +184,39 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    *operand = surface->operand;
+    /* To avoid the drawing error when the source and destination
+     * is the same surface, we have to create a new surface*/
+    if(surface == dst){
+	status = _cairo_gl_context_acquire (dst->base.device, &ctx);
+	if (unlikely (status))
+	    return status;
+
+	temp_surface = (cairo_gl_surface_t *)
+	    _cairo_gl_surface_create_scratch (ctx,
+					      surface->base.content,
+					      surface->width, surface->height);
+	if (temp_surface->base.status)
+	    return _cairo_gl_context_release (ctx, temp_surface->base.status);
+
+	_cairo_pattern_init_for_surface (&local_pattern, &surface->base);
+	local_pattern.base.filter = CAIRO_FILTER_NEAREST;
+	status = _cairo_surface_paint (&temp_surface->base,
+				       CAIRO_OPERATOR_SOURCE,
+				       &local_pattern.base,
+				       NULL);
+	_cairo_pattern_fini (&local_pattern.base);
+
+	status = _cairo_gl_context_release (ctx, status);
+	if (unlikely (status)) {
+	    cairo_surface_destroy (&temp_surface->base);
+	    return status;
+	}
+        temp_surface->operand.texture.owns_surface = temp_surface;
+        temp_surface->operand.texture.attributes = surface->operand.texture.attributes;
+	*operand = temp_surface->operand;
+    }
+    else
+	*operand = surface->operand;
 
     attributes = &operand->texture.attributes;
     cairo_matrix_multiply (&attributes->matrix,
-- 
1.7.5.1



More information about the cairo mailing list