[cairo-commit] 9 commits - src/cairo-compositor-private.h src/cairo-gl-composite.c src/cairo-gl-glyphs.c src/cairo-gl-msaa-compositor.c src/cairo-gl-operand.c src/cairo-gl-private.h src/cairo-gl-spans-compositor.c src/cairo-gl-surface.c src/cairo-gl-traps-compositor.c src/cairo-image-compositor.c src/cairo-traps-compositor.c src/cairo-xlib-render-compositor.c src/test-null-compositor-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Nov 24 02:18:23 PST 2011


 src/cairo-compositor-private.h     |    3 
 src/cairo-gl-composite.c           |   29 +++-----
 src/cairo-gl-glyphs.c              |   59 +++++++++--------
 src/cairo-gl-msaa-compositor.c     |   21 ++----
 src/cairo-gl-operand.c             |  128 ++++++++++++++++++++++++-------------
 src/cairo-gl-private.h             |  116 +++++++++++++++++----------------
 src/cairo-gl-spans-compositor.c    |   51 ++++++++------
 src/cairo-gl-surface.c             |   59 +++++++++++++----
 src/cairo-gl-traps-compositor.c    |   75 +++++++++++++--------
 src/cairo-image-compositor.c       |    8 ++
 src/cairo-traps-compositor.c       |   20 +++++
 src/cairo-xlib-render-compositor.c |   13 +++
 src/test-null-compositor-surface.c |    8 ++
 13 files changed, 366 insertions(+), 224 deletions(-)

New commits:
commit 2c4f6bbfbcaacea41386c36f42210120ee815055
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 24 01:08:30 2011 +0000

    gl: Prevent the traps compositor from exploding
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-compositor-private.h b/src/cairo-compositor-private.h
index 72507b2..ff4b93b 100644
--- a/src/cairo-compositor-private.h
+++ b/src/cairo-compositor-private.h
@@ -211,6 +211,9 @@ struct cairo_traps_compositor {
 				 cairo_boxes_t		*boxes);
 
     cairo_int_status_t
+	(*check_composite) (const cairo_composite_rectangles_t *extents);
+
+    cairo_int_status_t
 	(*composite)		(void			*dst,
 				 cairo_operator_t	 op,
 				 cairo_surface_t	*src,
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a27b596..90c189a 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -476,8 +476,9 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
 
     glEnable (GL_BLEND);
 
-    component_alpha = ((setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) &&
-                       setup->mask.texture.attributes.has_component_alpha);
+    component_alpha =
+	setup->mask.type == CAIRO_GL_OPERAND_TEXTURE &&
+	setup->mask.texture.attributes.has_component_alpha;
 
     /* Do various magic for component alpha */
     if (component_alpha) {
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 1fe4bb3..395222c 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -59,11 +59,15 @@ typedef struct _cairo_gl_glyph {
 } cairo_gl_glyph_t;
 
 static void
-_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *_priv,
+_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
 		      cairo_scaled_glyph_t *scaled_glyph,
 		      cairo_scaled_font_t  *scaled_font)
 {
-    cairo_gl_glyph_t *priv = cairo_container_of (_priv, cairo_gl_glyph_t, base);
+    cairo_gl_glyph_t *priv = cairo_container_of (glyph_private,
+						 cairo_gl_glyph_t,
+						 base);
+
+    cairo_list_del (&glyph_private->link);
 
     priv->node.owner = NULL;
     if (! priv->node.pinned) {
@@ -302,7 +306,7 @@ render_glyphs (cairo_gl_surface_t	*dst,
 		scaled_glyph->dev_private_key = cache;
 		scaled_glyph->dev_private = cairo_container_of (priv,
 								cairo_gl_glyph_t,
-								base);;
+								base);
 	    } else {
 		status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
 
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index e75f812..31776ff 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -127,6 +127,7 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
 
     attributes->extend = src->base.extend;
     attributes->filter = src->base.filter;
+    attributes->has_component_alpha = src->base.has_component_alpha;
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -186,6 +187,7 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
 
     attributes->extend = src->base.extend;
     attributes->filter = src->base.filter;
+    attributes->has_component_alpha = src->base.has_component_alpha;
     return CAIRO_STATUS_SUCCESS;
 }
 
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index a439a7b..3a3a09d 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -355,6 +355,8 @@ _cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
     cairo_gl_operand_t *operand = &surface->operand;
     cairo_surface_attributes_t *attributes = &operand->texture.attributes;
 
+    memset (operand, 0, sizeof (cairo_gl_operand_t));
+
     operand->type = CAIRO_GL_OPERAND_TEXTURE;
     operand->texture.surface = surface;
     operand->texture.tex = surface->tex;
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index 3e22f2f..eb8f7ff 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -176,6 +176,9 @@ pattern_to_surface (cairo_surface_t *dst,
     cairo_gl_source_t *source;
     cairo_int_status_t status;
 
+    if (pattern == NULL)
+	return _cairo_gl_white_source ();
+
     source = malloc (sizeof (*source));
     if (unlikely (source == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -201,7 +204,7 @@ static inline cairo_gl_operand_t *
 source_to_operand (cairo_surface_t *surface)
 {
     cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
-    return &source->operand;
+    return surface ? &source->operand : NULL;
 }
 
 static cairo_int_status_t
@@ -320,15 +323,17 @@ lerp (void			*dst,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_gl_surface_t *
-traps_to_surface (void *_dst,
+static cairo_int_status_t
+traps_to_operand (void *_dst,
 		  const cairo_rectangle_int_t *extents,
 		  cairo_antialias_t	antialias,
-		  cairo_traps_t		*traps)
+		  cairo_traps_t		*traps,
+		  cairo_gl_operand_t	*operand)
 {
     pixman_format_code_t pixman_format;
     pixman_image_t *pixman_image;
     cairo_surface_t *image, *mask;
+    cairo_surface_pattern_t pattern;
     cairo_status_t status;
 
     pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
@@ -337,22 +342,23 @@ traps_to_surface (void *_dst,
 					     extents->height,
 					     NULL, 0);
     if (unlikely (pixman_image == NULL))
-	return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     _pixman_image_add_traps (pixman_image, extents->x, extents->y, traps);
     image = _cairo_image_surface_create_for_pixman_image (pixman_image,
 							  pixman_format);
     if (unlikely (image->status)) {
 	pixman_image_unref (pixman_image);
-	return (cairo_gl_surface_t *)image;
+	return image->status;
     }
 
-    mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
+    mask = _cairo_surface_create_similar_scratch (_dst,
+						  CAIRO_CONTENT_COLOR_ALPHA,
 						  extents->width,
 						  extents->height);
     if (unlikely (mask->status)) {
 	cairo_surface_destroy (image);
-	return (cairo_gl_surface_t *)mask;
+	return mask->status;
     }
 
     status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
@@ -363,10 +369,21 @@ traps_to_surface (void *_dst,
     cairo_surface_destroy (image);
     if (unlikely (status)) {
 	cairo_surface_destroy (mask);
-	return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status);
+	return status;
     }
 
-    return (cairo_gl_surface_t*)mask;
+    _cairo_pattern_init_for_surface (&pattern, mask);
+    cairo_matrix_init_translate (&pattern.base.matrix,
+				 -extents->x, -extents->y);
+    pattern.base.filter = CAIRO_FILTER_NEAREST;
+    pattern.base.extend = CAIRO_EXTEND_NONE;
+    status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
+				     &_cairo_unbounded_rectangle,
+				     &_cairo_unbounded_rectangle);
+    _cairo_pattern_fini (&pattern.base);
+    cairo_surface_destroy (mask);
+
+    return status;
 }
 
 static cairo_int_status_t
@@ -383,21 +400,17 @@ composite_traps (void			*_dst,
 {
     cairo_gl_composite_t setup;
     cairo_gl_context_t *ctx;
-    cairo_gl_surface_t *mask;
     cairo_int_status_t status;
 
-    mask = traps_to_surface (_dst, extents, antialias, traps);
-    if (unlikely (mask->base.status))
-	return mask->base.status;
-
     status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
     if (unlikely (status))
         goto FAIL;
 
     _cairo_gl_composite_set_source_operand (&setup,
 					    source_to_operand (abstract_src));
-
-    //_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0);
+    status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask);
+    if (unlikely (status))
+	goto FAIL;
 
     status = _cairo_gl_composite_begin (&setup, &ctx);
     if (unlikely (status))
@@ -412,7 +425,6 @@ composite_traps (void			*_dst,
 
 FAIL:
     _cairo_gl_composite_fini (&setup);
-    cairo_surface_destroy (&mask->base);
     return status;
 }
 
@@ -443,7 +455,8 @@ tristrip_to_surface (void *_dst,
 	return (cairo_gl_surface_t *)image;
     }
 
-    mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
+    mask = _cairo_surface_create_similar_scratch (_dst,
+						  CAIRO_CONTENT_COLOR_ALPHA,
 						  extents->width,
 						  extents->height);
     if (unlikely (mask->status)) {
@@ -512,6 +525,15 @@ FAIL:
     return status;
 }
 
+static cairo_int_status_t
+check_composite (const cairo_composite_rectangles_t *extents)
+{
+    if (! _cairo_gl_operator_is_supported (extents->op))
+	return UNSUPPORTED ("unsupported operator");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 const cairo_compositor_t *
 _cairo_gl_traps_compositor_get (void)
 {
@@ -526,7 +548,7 @@ _cairo_gl_traps_compositor_get (void)
 	compositor.draw_image_boxes = draw_image_boxes;
 	//compositor.copy_boxes = copy_boxes;
 	compositor.fill_boxes = fill_boxes;
-	//compositor.check_composite = check_composite;
+	compositor.check_composite = check_composite;
 	compositor.composite = composite;
 	compositor.lerp = lerp;
 	//compositor.check_composite_boxes = check_composite_boxes;
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index d299c9f..6c409e9 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -971,6 +971,12 @@ composite_glyphs (void				*_dst,
     return status;
 }
 
+static cairo_int_status_t
+check_composite (const cairo_composite_rectangles_t *extents)
+{
+    return CAIRO_STATUS_SUCCESS;
+}
+
 const cairo_compositor_t *
 _cairo_image_traps_compositor_get (void)
 {
@@ -986,7 +992,7 @@ _cairo_image_traps_compositor_get (void)
 	compositor.draw_image_boxes = draw_image_boxes;
 	//compositor.copy_boxes = copy_boxes;
 	compositor.fill_boxes = fill_boxes;
-	//compositor.check_composite = check_composite;
+	compositor.check_composite = check_composite;
 	compositor.composite = composite;
 	compositor.lerp = lerp;
 	//compositor.check_composite_boxes = check_composite_boxes;
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index 0df3b78..0371c80 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -1797,6 +1797,10 @@ _cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
     cairo_boxes_t boxes;
     cairo_int_status_t status;
 
+    status = compositor->check_composite (extents);
+    if (unlikely (status))
+	return status;
+
      _cairo_clip_steal_boxes (extents->clip, &boxes);
      status = clip_and_composite_boxes (compositor, extents, &boxes);
      _cairo_clip_unsteal_boxes (extents->clip, &boxes);
@@ -1811,6 +1815,10 @@ _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
     cairo_int_status_t status;
 
+    status = compositor->check_composite (extents);
+    if (unlikely (status))
+	return status;
+
     if (extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
 	extents->clip->path == NULL) {
 	status = clip_and_composite (compositor, extents,
@@ -1853,6 +1861,10 @@ _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    status = compositor->check_composite (extents);
+    if (unlikely (status))
+	return status;
+
     status = CAIRO_INT_STATUS_UNSUPPORTED;
     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
 	cairo_boxes_t boxes;
@@ -1912,6 +1924,10 @@ _cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    status = compositor->check_composite (extents);
+    if (unlikely (status))
+	return status;
+
     status = CAIRO_INT_STATUS_UNSUPPORTED;
     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
 	cairo_boxes_t boxes;
@@ -1995,6 +2011,10 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t	*_compositor,
     const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
     cairo_int_status_t status;
 
+    status = compositor->check_composite (extents);
+    if (unlikely (status))
+	return status;
+
     _cairo_scaled_font_freeze_cache (scaled_font);
     status = compositor->check_composite_glyphs (extents,
 						 scaled_font, glyphs,
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 5dd7668..6dad822 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -1664,6 +1664,17 @@ composite_tristrip (void		*abstract_dst,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_int_status_t
+check_composite (const cairo_composite_rectangles_t *extents)
+{
+    cairo_xlib_display_t *display = ((cairo_xlib_surface_t *)extents->surface)->display;
+
+    if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 const cairo_compositor_t *
 _cairo_xlib_traps_compositor_get (void)
 {
@@ -1680,7 +1691,7 @@ _cairo_xlib_traps_compositor_get (void)
 	compositor.draw_image_boxes = draw_image_boxes;
 	compositor.copy_boxes = copy_boxes;
 	compositor.fill_boxes = fill_boxes;
-	//compositor.check_composite = check_composite;
+	compositor.check_composite = check_composite;
 	compositor.composite = composite;
 	compositor.lerp = lerp;
 	//compositor.check_composite_boxes = check_composite_boxes;
diff --git a/src/test-null-compositor-surface.c b/src/test-null-compositor-surface.c
index df2eda0..e94c8a7 100644
--- a/src/test-null-compositor-surface.c
+++ b/src/test-null-compositor-surface.c
@@ -392,6 +392,12 @@ no_fallback_compositor_get (void)
     return &__cairo_no_compositor;
 }
 
+static cairo_int_status_t
+check_composite (const cairo_composite_rectangles_t *extents)
+{
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static const cairo_compositor_t *
 no_traps_compositor_get (void)
 {
@@ -408,7 +414,7 @@ no_traps_compositor_get (void)
 	compositor.draw_image_boxes = draw_image_boxes;
 	//compositor.copy_boxes = copy_boxes;
 	compositor.fill_boxes = fill_boxes;
-	//compositor.check_composite = check_composite;
+	compositor.check_composite = check_composite;
 	compositor.composite = composite;
 	compositor.lerp = lerp;
 	//compositor.check_composite_boxes = check_composite_boxes;
commit 5e4a0bd892263a5801fdaaa9fa5dbbcfc14c211a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 23 23:05:14 2011 +0000

    gl: Embed a operand into the surface for pass-through
    
    The traps compositor expects to be able to pass either in a surface or a
    source to its composite functions, so make it so.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 8b8e502..77b58ad 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -94,6 +94,8 @@
 /* VBO size that we allocate, smaller size means we gotta flush more often */
 #define CAIRO_GL_VBO_SIZE 16384
 
+typedef struct _cairo_gl_surface cairo_gl_surface_t;
+
 /* GL flavor */
 typedef enum cairo_gl_flavor {
     CAIRO_GL_FLAVOR_NONE = 0,
@@ -109,9 +111,53 @@ enum {
     CAIRO_GL_TEXCOORD1_ATTRIB_INDEX = CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + 1
 };
 
-typedef struct _cairo_gl_surface {
+typedef enum cairo_gl_operand_type {
+    CAIRO_GL_OPERAND_NONE,
+    CAIRO_GL_OPERAND_CONSTANT,
+    CAIRO_GL_OPERAND_TEXTURE,
+    CAIRO_GL_OPERAND_LINEAR_GRADIENT,
+    CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0,
+    CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE,
+    CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT,
+
+    CAIRO_GL_OPERAND_COUNT
+} cairo_gl_operand_type_t;
+
+/* This union structure describes a potential source or mask operand to the
+ * compositing equation.
+ */
+typedef struct cairo_gl_operand {
+    cairo_gl_operand_type_t type;
+    union {
+	struct {
+	    GLuint tex;
+	    cairo_gl_surface_t *surface;
+	    cairo_surface_attributes_t attributes;
+	} texture;
+	struct {
+	    GLfloat color[4];
+	} constant;
+	struct {
+	    cairo_gl_gradient_t *gradient;
+	    cairo_matrix_t m;
+	    cairo_circle_double_t circle_d;
+	    double radius_0, a;
+	    cairo_extend_t extend;
+	} gradient;
+    };
+    unsigned int vertex_offset;
+} cairo_gl_operand_t;
+
+typedef struct cairo_gl_source {
     cairo_surface_t base;
 
+    cairo_gl_operand_t operand;
+} cairo_gl_source_t;
+
+struct _cairo_gl_surface {
+    cairo_surface_t base;
+    cairo_gl_operand_t operand;
+
     int width, height;
 
     GLuint tex; /* GL texture object containing our data. */
@@ -119,7 +165,7 @@ typedef struct _cairo_gl_surface {
     GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */
     int owns_tex;
     cairo_bool_t needs_update;
-} cairo_gl_surface_t;
+};
 
 typedef struct cairo_gl_glyph_cache {
     cairo_rtree_t rtree;
@@ -132,18 +178,6 @@ typedef enum cairo_gl_tex {
     CAIRO_GL_TEX_TEMP = 2
 } cairo_gl_tex_t;
 
-typedef enum cairo_gl_operand_type {
-    CAIRO_GL_OPERAND_NONE,
-    CAIRO_GL_OPERAND_CONSTANT,
-    CAIRO_GL_OPERAND_TEXTURE,
-    CAIRO_GL_OPERAND_LINEAR_GRADIENT,
-    CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0,
-    CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE,
-    CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT,
-
-    CAIRO_GL_OPERAND_COUNT
-} cairo_gl_operand_type_t;
-
 typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
 
 typedef struct cairo_gl_shader {
@@ -167,37 +201,6 @@ typedef enum cairo_gl_var_type {
 #define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 3) | ((mask) << 2 | (src << 1) | (dest))
 #define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_TEXCOORDS << 3) | (CAIRO_GL_VAR_TEXCOORDS << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
 
-/* This union structure describes a potential source or mask operand to the
- * compositing equation.
- */
-typedef struct cairo_gl_operand {
-    cairo_gl_operand_type_t type;
-    union {
-	struct {
-	    GLuint tex;
-	    cairo_gl_surface_t *surface;
-	    cairo_surface_attributes_t attributes;
-	} texture;
-	struct {
-	    GLfloat color[4];
-	} constant;
-	struct {
-	    cairo_gl_gradient_t *gradient;
-	    cairo_matrix_t m;
-	    cairo_circle_double_t circle_d;
-	    double radius_0, a;
-	    cairo_extend_t extend;
-	} gradient;
-    };
-    unsigned int vertex_offset;
-} cairo_gl_operand_t;
-
-typedef struct cairo_gl_source {
-    cairo_surface_t base;
-
-    cairo_gl_operand_t operand;
-} cairo_gl_source_t;
-
 typedef void (*cairo_gl_generic_func_t)(void);
 typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname);
 
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 4906632..a439a7b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -349,6 +349,28 @@ _cairo_gl_operator_is_supported (cairo_operator_t op)
     return op < CAIRO_OPERATOR_SATURATE;
 }
 
+static void
+_cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
+{
+    cairo_gl_operand_t *operand = &surface->operand;
+    cairo_surface_attributes_t *attributes = &operand->texture.attributes;
+
+    operand->type = CAIRO_GL_OPERAND_TEXTURE;
+    operand->texture.surface = surface;
+    operand->texture.tex = surface->tex;
+
+    if (_cairo_gl_device_requires_power_of_two_textures (surface->base.device)) {
+	cairo_matrix_init_identity (&attributes->matrix);
+    } else {
+	cairo_matrix_init_scale (&attributes->matrix,
+				 1.0 / surface->width,
+				 1.0 / surface->height);
+    }
+
+    attributes->extend = CAIRO_EXTEND_NONE;
+    attributes->filter = CAIRO_FILTER_NEAREST;
+}
+
 void
 _cairo_gl_surface_init (cairo_device_t *device,
 			cairo_gl_surface_t *surface,
@@ -363,6 +385,8 @@ _cairo_gl_surface_init (cairo_device_t *device,
     surface->width = width;
     surface->height = height;
     surface->needs_update = FALSE;
+
+    _cairo_gl_surface_embedded_operand_init (surface);
 }
 
 static cairo_surface_t *
commit 4cf001244a589b5bf1b3745327948f87c397c22f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 23 22:53:50 2011 +0000

    gl: Avoid cleaning up an uninitialised composite upon UNSUPPORTED
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index 4c01171..710cbe2 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -477,6 +477,9 @@ _cairo_gl_span_renderer_fini (cairo_abstract_span_renderer_t *_r,
 {
     cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *) _r;
 
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
+
     if (status == CAIRO_INT_STATUS_SUCCESS)
 	r->base.finish (r);
 
commit 5edb3a29b9210fda9e2dc95f7a999675402b471c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 23 22:08:03 2011 +0000

    gl: Fallback for complex subsurfaces
    
    In the process we need to supply the sampled area and operation extents
    into the operands.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 17732d3..a27b596 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -55,16 +55,12 @@
 cairo_int_status_t
 _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
 			        const cairo_pattern_t *pattern,
-                                int src_x, int src_y,
-                                int dst_x, int dst_y,
-                                int width, int height)
+				const cairo_rectangle_int_t *sample,
+				const cairo_rectangle_int_t *extents)
 {
     _cairo_gl_operand_destroy (&setup->src);
-    return _cairo_gl_operand_init (&setup->src, pattern,
-                                   setup->dst,
-                                   src_x, src_y,
-                                   dst_x, dst_y,
-                                   width, height);
+    return _cairo_gl_operand_init (&setup->src, pattern, setup->dst,
+				   sample, extents);
 }
 
 void
@@ -86,19 +82,15 @@ _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
 cairo_int_status_t
 _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
 			      const cairo_pattern_t *pattern,
-                              int src_x, int src_y,
-                              int dst_x, int dst_y,
-                              int width, int height)
+			      const cairo_rectangle_int_t *sample,
+			      const cairo_rectangle_int_t *extents)
 {
     _cairo_gl_operand_destroy (&setup->mask);
     if (pattern == NULL)
         return CAIRO_STATUS_SUCCESS;
 
-    return _cairo_gl_operand_init (&setup->mask, pattern,
-                                   setup->dst,
-                                   src_x, src_y,
-                                   dst_x, dst_y,
-                                   width, height);
+    return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
+				   sample, extents);
 }
 
 void
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index f5af94d..1fe4bb3 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -277,7 +277,8 @@ render_glyphs (cairo_gl_surface_t	*dst,
 
             status = _cairo_gl_composite_set_mask (&setup,
                                                    &cache->pattern.base,
-                                                   0, 0, 0, 0, 0, 0);
+						   &_cairo_unbounded_rectangle,
+						   &_cairo_unbounded_rectangle);
             if (unlikely (status))
                 goto FINISH;
 
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 316dfc8..5746513 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -287,12 +287,8 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
 
     status = _cairo_gl_composite_set_source (&info.setup,
 					     &composite->source_pattern.base,
-					     composite->bounded.x,
-					     composite->bounded.y,
-					     composite->bounded.x,
-					     composite->bounded.y,
-					     composite->bounded.width,
-					     composite->bounded.height);
+					     &composite->source_sample_area,
+					     &composite->bounded);
     if (unlikely (status))
 	goto finish;
 
@@ -367,12 +363,8 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
 
     status = _cairo_gl_composite_set_source (&setup,
 					     &composite->source_pattern.base,
-					     composite->bounded.x,
-					     composite->bounded.y,
-					     composite->bounded.x,
-					     composite->bounded.y,
-					     composite->bounded.width,
-					     composite->bounded.height);
+					     &composite->source_sample_area,
+					     &composite->bounded);
     if (unlikely (status))
 	goto cleanup_setup;
 
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index c544532..e75f812 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -70,12 +70,72 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
 }
 
 static cairo_status_t
+_cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
+				   const cairo_pattern_t *_src,
+				   cairo_gl_surface_t *dst,
+				   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;
+    cairo_matrix_t m;
+
+    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_INT_STATUS_UNSUPPORTED;
+    }
+
+    surface = (cairo_gl_surface_t *) sub->target;
+
+    attributes = &operand->texture.attributes;
+
+    operand->type = CAIRO_GL_OPERAND_TEXTURE;
+    operand->texture.surface =
+	(cairo_gl_surface_t *) cairo_surface_reference (&surface->base);
+    operand->texture.tex = surface->tex;
+
+    /* Translate the matrix from
+     * (unnormalized src -> unnormalized src) to
+     * (unnormalized dst -> unnormalized src)
+     */
+    attributes->matrix = src->base.matrix;
+    attributes->matrix.x0 += sub->extents.x;
+    attributes->matrix.y0 += sub->extents.y;
+
+    /* Translate the matrix from
+     * (unnormalized dst -> unnormalized src) to
+     * (unnormalized dst -> normalized src)
+     */
+    if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
+	cairo_matrix_init_scale (&m,
+				 1.0,
+				 1.0);
+    } else {
+	cairo_matrix_init_scale (&m,
+				 1.0 / surface->width,
+				 1.0 / surface->height);
+    }
+    cairo_matrix_multiply (&attributes->matrix,
+			   &attributes->matrix,
+			   &m);
+
+    attributes->extend = src->base.extend;
+    attributes->filter = src->base.filter;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
 				const cairo_pattern_t *_src,
 				cairo_gl_surface_t *dst,
-				int src_x, int src_y,
-				int dst_x, int dst_y,
-				int width, int height)
+				const cairo_rectangle_int_t *sample,
+				const cairo_rectangle_int_t *extents)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_gl_surface_t *surface;
@@ -85,11 +145,13 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
     surface = (cairo_gl_surface_t *) src->surface;
     if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
-	if (_cairo_surface_is_subsurface (&surface->base)) {
-	    surface = (cairo_gl_surface_t *)
-		_cairo_surface_subsurface_get_target_with_offset (&surface->base, &src_x, &src_y);
-	}
+	if (_cairo_surface_is_subsurface (&surface->base))
+	    return _cairo_gl_subsurface_operand_init (operand, _src, dst,
+						      sample, extents);
+
+	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     attributes = &operand->texture.attributes;
@@ -103,8 +165,7 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
      * (unnormalized src -> unnormalized src) to
      * (unnormalized dst -> unnormalized src)
      */
-    cairo_matrix_init_translate (&m, src_x - dst_x, src_y - dst_y);
-    cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix);
+    attributes->matrix = src->base.matrix;
 
     /* Translate the matrix from
      * (unnormalized dst -> unnormalized src) to
@@ -132,9 +193,7 @@ static cairo_status_t
 _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 				 const cairo_pattern_t *_src,
 				 cairo_gl_surface_t *dst,
-				 int src_x, int src_y,
-				 int dst_x, int dst_y,
-				 int width, int height)
+				 const cairo_rectangle_int_t *extents)
 {
     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
     cairo_status_t status;
@@ -152,12 +211,12 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
     surface = (cairo_gl_surface_t *)
 	_cairo_gl_surface_create_scratch (ctx,
 					  src->surface->content,
-					  width, height);
+					  extents->width, extents->height);
     if (src->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE) {
 	status = _cairo_gl_surface_draw_image (surface,
 				      (cairo_image_surface_t *)src->surface,
 				      0, 0,
-				      width, height,
+				      extents->width, extents->height,
 				      0, 0);
 
 	attributes->extend = src->base.extend;
@@ -184,8 +243,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
      * (unnormalized src -> unnormalized src) to
      * (unnormalized dst -> unnormalized src)
      */
-    cairo_matrix_init_translate (&m, src_x - dst_x, src_y - dst_y);
-    cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix);
+    attributes->matrix = src->base.matrix;
 
     /* Translate the matrix from
      * (unnormalized dst -> unnormalized src) to
@@ -220,9 +278,7 @@ _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
 static cairo_status_t
 _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
                                  const cairo_pattern_t *pattern,
-				 cairo_gl_surface_t *dst,
-				 int src_x, int src_y,
-				 int dst_x, int dst_y)
+				 cairo_gl_surface_t *dst)
 {
     const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern;
     cairo_status_t status;
@@ -304,8 +360,6 @@ _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
 			       &m);
     }
 
-    cairo_matrix_translate (&operand->gradient.m, src_x - dst_x, src_y - dst_y);
-
     operand->gradient.extend = pattern->extend;
 
     return CAIRO_STATUS_SUCCESS;
@@ -363,9 +417,8 @@ cairo_int_status_t
 _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        const cairo_pattern_t *pattern,
 		        cairo_gl_surface_t *dst,
-		        int src_x, int src_y,
-		        int dst_x, int dst_y,
-		        int width, int height)
+			const cairo_rectangle_int_t *sample,
+			const cairo_rectangle_int_t *extents)
 {
     cairo_int_status_t status;
 
@@ -375,11 +428,8 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 				      &((cairo_solid_pattern_t *) pattern)->color);
 	return CAIRO_STATUS_SUCCESS;
     case CAIRO_PATTERN_TYPE_SURFACE:
-	status = _cairo_gl_surface_operand_init (operand,
-						 pattern, dst,
-						 src_x, src_y,
-						 dst_x, dst_y,
-						 width, height);
+	status = _cairo_gl_surface_operand_init (operand, pattern, dst,
+						 sample, extents);
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	    break;
 
@@ -387,10 +437,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	status = _cairo_gl_gradient_operand_init (operand,
-						  pattern, dst,
-						  src_x, src_y,
-						  dst_x, dst_y);
+	status = _cairo_gl_gradient_operand_init (operand, pattern, dst);
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	    break;
 
@@ -401,11 +448,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 	break;
     }
 
-    return _cairo_gl_pattern_texture_setup (operand,
-					    pattern, dst,
-					    src_x, src_y,
-					    dst_x, dst_y,
-					    width, height);
+    return _cairo_gl_pattern_texture_setup (operand, pattern, dst, extents);
 }
 
 cairo_filter_t
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index f87f13a..8b8e502 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -455,9 +455,9 @@ _cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
 cairo_private cairo_int_status_t
 _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
 			        const cairo_pattern_t *pattern,
-                                int src_x, int src_y,
-                                int dst_x, int dst_y,
-                                int width, int height);
+				const cairo_rectangle_int_t *sample,
+				const cairo_rectangle_int_t *extents);
+
 cairo_private void
 _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
 				      const cairo_color_t *color);
@@ -469,9 +469,8 @@ _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
 cairo_private cairo_int_status_t
 _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
 			      const cairo_pattern_t *pattern,
-                              int src_x, int src_y,
-                              int dst_x, int dst_y,
-                              int width, int height);
+			      const cairo_rectangle_int_t *sample,
+			      const cairo_rectangle_int_t *extents);
 
 cairo_private void
 _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
@@ -625,9 +624,9 @@ cairo_private cairo_int_status_t
 _cairo_gl_operand_init (cairo_gl_operand_t *operand,
 		        const cairo_pattern_t *pattern,
 		        cairo_gl_surface_t *dst,
-		        int src_x, int src_y,
-		        int dst_x, int dst_y,
-		        int width, int height);
+			const cairo_rectangle_int_t *sample,
+			const cairo_rectangle_int_t *extents);
+
 cairo_private void
 _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
 	                      const cairo_color_t *color);
diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index e36286c..4c01171 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -315,10 +315,9 @@ pattern_to_surface (cairo_surface_t *dst,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     *src_x = *src_y = 0;
-    status = _cairo_gl_operand_init (&source->operand, pattern, (cairo_gl_surface_t *)dst,
-				     extents->x, extents->y,
-				     extents->x, extents->y,
-				     extents->width, extents->height);
+    status = _cairo_gl_operand_init (&source->operand, pattern,
+				     (cairo_gl_surface_t *)dst,
+				     sample, extents);
     if (unlikely (status)) {
 	cairo_surface_destroy (&source->base);
 	return _cairo_surface_create_in_error (status);
@@ -425,12 +424,8 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t	*_r,
         goto FAIL;
 
     status = _cairo_gl_composite_set_source (&r->setup, source,
-					     composite->unbounded.x,
-					     composite->unbounded.y,
-					     composite->unbounded.x,
-					     composite->unbounded.y,
-					     composite->unbounded.width,
-					     composite->unbounded.height);
+					     &composite->source_sample_area,
+					     &composite->unbounded);
     if (unlikely (status))
         goto FAIL;
 
@@ -440,12 +435,8 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t	*_r,
     } else {
 	status = _cairo_gl_composite_set_mask (&r->setup,
 					       &composite->mask_pattern.base,
-					       composite->unbounded.x,
-					       composite->unbounded.y,
-					       composite->unbounded.x,
-					       composite->unbounded.y,
-					       composite->unbounded.width,
-					       composite->unbounded.height);
+					       &composite->mask_sample_area,
+					       &composite->unbounded);
 	if (unlikely (status))
 	    goto FAIL;
     }
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index d999959..3e22f2f 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -186,10 +186,9 @@ pattern_to_surface (cairo_surface_t *dst,
 			 CAIRO_CONTENT_COLOR_ALPHA);
 
     *src_x = *src_y = 0;
-    status = _cairo_gl_operand_init (&source->operand, pattern, (cairo_gl_surface_t *)dst,
-				     extents->x, extents->y,
-				     extents->x, extents->y,
-				     extents->width, extents->height);
+    status = _cairo_gl_operand_init (&source->operand, pattern,
+				     (cairo_gl_surface_t *)dst,
+				     sample, extents);
     if (unlikely (status)) {
 	cairo_surface_destroy (&source->base);
 	return _cairo_surface_create_in_error (status);
commit 12b8f941612d131793cc053d49cd7759aa5c97ca
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 23 21:39:25 2011 +0000

    gl: Correctly offset sub-image uploads
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index c781ec4..4906632 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -801,8 +801,6 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
     if (unlikely (status))
 	goto FAIL;
 
-    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
-	glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
     if (_cairo_gl_surface_is_texture (dst)) {
 	void *data_start = src->data + src_y * src->stride + src_x * cpp;
 	void *data_start_gles2 = NULL;
@@ -825,10 +823,14 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 							   &data_start_gles2);
 	    if (unlikely (status))
 		goto FAIL;
+
+	    data_start = data_start_gles2;
 	}
 	else
 	{
 	    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+	    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+		glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
 	}
 
         _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
@@ -837,9 +839,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
 	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexSubImage2D (ctx->tex_target, 0,
 			 dst_x, dst_y, width, height,
-			 format, type,
-			 data_start_gles2 != NULL ? data_start_gles2 :
-						    data_start);
+			 format, type, data_start);
 
 	free (data_start_gles2);
 
@@ -858,10 +858,9 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
         tmp = _cairo_gl_surface_create_scratch (ctx,
                                                 dst->base.content,
                                                 width, height);
-        if (unlikely (tmp->status)) {
-            cairo_surface_destroy (tmp);
+        if (unlikely (tmp->status))
             goto FAIL;
-        }
+
         status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
                                                src,
                                                src_x, src_y,
@@ -869,12 +868,25 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
                                                0, 0);
         if (status == CAIRO_INT_STATUS_SUCCESS) {
             cairo_surface_pattern_t tmp_pattern;
+	    cairo_rectangle_int_t r;
+	    cairo_clip_t *clip;
 
             _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
+	    cairo_matrix_init_translate (&tmp_pattern.base.matrix,
+					 -dst_x, -dst_y);
+	    tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
+	    tmp_pattern.base.extend = CAIRO_EXTEND_NONE;
+
+	    r.x = dst_x;
+	    r.y = dst_y;
+	    r.width = width;
+	    r.height = height;
+	    clip = _cairo_clip_intersect_rectangle (NULL, &r);
 	    status = _cairo_surface_paint (&dst->base,
 					   CAIRO_OPERATOR_SOURCE,
 					   &tmp_pattern.base,
-					   NULL);
+					   clip);
+	    _cairo_clip_destroy (clip);
             _cairo_pattern_fini (&tmp_pattern.base);
         }
 
@@ -882,9 +894,6 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
     }
 
 FAIL:
-    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
-	glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
-
     status = _cairo_gl_context_release (ctx, status);
 
     if (clone)
commit e280e67b86040b5c0b256d24c0cc644f13761d89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Nov 23 21:20:21 2011 +0000

    gl: Update glyphs to use cairo_gl_source_t
    
    It was being passed into the function but then interpreted as a
    cairo_pattern_t. Fix it!
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 1e94720..f5af94d 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -213,11 +213,18 @@ _cairo_gl_font_fini (cairo_scaled_font_private_t *_priv,
     free (priv);
 }
 
+static inline cairo_gl_operand_t *
+source_to_operand (cairo_surface_t *surface)
+{
+    cairo_gl_source_t *source = (cairo_gl_source_t *) surface;
+    return &source->operand;
+}
+
 static cairo_status_t
 render_glyphs (cairo_gl_surface_t	*dst,
 	       int dst_x, int dst_y,
 	       cairo_operator_t	 op,
-	       const cairo_pattern_t	*source,
+	       cairo_surface_t	*source,
 	       cairo_composite_glyphs_info_t *info,
 	       cairo_bool_t		*has_component_alpha)
 {
@@ -238,17 +245,8 @@ render_glyphs (cairo_gl_surface_t	*dst,
     if (unlikely (status))
 	goto FINISH;
 
-    status = _cairo_gl_composite_set_source (&setup, source,
-                                             info->extents.x,
-					     info->extents.y,
-                                             dst_x, dst_y,
-                                             info->extents.width,
-                                             info->extents.height);
-    if (unlikely (status))
-	goto FINISH;
-
-
-    //_cairo_gl_composite_set_clip_region (&setup, _cairo_clip_get_region (extents->clip));
+    _cairo_gl_composite_set_source_operand (&setup,
+					    source_to_operand (source));
 
     for (i = 0; i < info->num_glyphs; i++) {
 	cairo_scaled_glyph_t *scaled_glyph;
@@ -368,7 +366,7 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst,
 
     status = render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
 			    CAIRO_OPERATOR_ADD,
-			    &_cairo_pattern_white.base,
+			    _cairo_gl_white_source (),
 			    info, &has_component_alpha);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
 	cairo_surface_pattern_t mask_pattern;
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 19c7c1f..f87f13a 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -192,6 +192,12 @@ typedef struct cairo_gl_operand {
     unsigned int vertex_offset;
 } cairo_gl_operand_t;
 
+typedef struct cairo_gl_source {
+    cairo_surface_t base;
+
+    cairo_gl_operand_t operand;
+} cairo_gl_source_t;
+
 typedef void (*cairo_gl_generic_func_t)(void);
 typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname);
 
@@ -692,6 +698,9 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
 				  int			width,
 				  int			height);
 
+cairo_private cairo_surface_t *
+_cairo_gl_white_source (void);
+
 slim_hidden_proto (cairo_gl_surface_create);
 slim_hidden_proto (cairo_gl_surface_create_for_texture);
 
diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index 3e52f28..e36286c 100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -279,12 +279,6 @@ FAIL:
     return status;
 }
 
-typedef struct cairo_gl_source {
-    cairo_surface_t base;
-
-    cairo_gl_operand_t operand;
-} cairo_gl_source_t;
-
 static cairo_status_t
 _cairo_gl_source_finish (void *abstract_surface)
 {
@@ -333,6 +327,25 @@ pattern_to_surface (cairo_surface_t *dst,
     return &source->base;
 }
 
+cairo_surface_t *
+_cairo_gl_white_source (void)
+{
+    cairo_gl_source_t *source;
+
+    source = malloc (sizeof (*source));
+    if (unlikely (source == NULL))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    _cairo_surface_init (&source->base,
+			 &cairo_gl_source_backend,
+			 NULL, /* device */
+			 CAIRO_CONTENT_COLOR_ALPHA);
+
+    _cairo_gl_solid_operand_init (&source->operand, CAIRO_COLOR_WHITE);
+
+    return &source->base;
+}
+
 static inline cairo_gl_operand_t *
 source_to_operand (cairo_surface_t *surface)
 {
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index afc74d0..d999959 100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -150,12 +150,6 @@ FAIL:
     return status;
 }
 
-typedef struct cairo_gl_source {
-    cairo_surface_t base;
-
-    cairo_gl_operand_t operand;
-} cairo_gl_source_t;
-
 static cairo_status_t
 _cairo_gl_source_finish (void *abstract_surface)
 {
commit d99ebe9862743c99ebe263ea0e8526a5a082d6db
Author: Martin Robinson <mrobinson at igalia.com>
Date:   Fri Nov 11 14:25:56 2011 -0800

    gl: Properly prepare the source when compositing glyphs with a mask.
    
    After the architecture rewrite, glyph compositing via a mask was
    disabled. This change reinstates that.

diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index ee5c543..1e94720 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -343,10 +343,10 @@ render_glyphs (cairo_gl_surface_t	*dst,
 }
 
 static cairo_int_status_t
-render_glyphs_via_mask (cairo_gl_surface_t	*dst,
-			   cairo_operator_t	 op,
-			   const cairo_surface_t	*source,
-			   cairo_composite_glyphs_info_t *info)
+render_glyphs_via_mask (cairo_gl_surface_t *dst,
+			cairo_operator_t  op,
+			cairo_surface_t *source,
+			cairo_composite_glyphs_info_t *info)
 {
     cairo_surface_t *mask;
     cairo_status_t status;
@@ -371,19 +371,23 @@ render_glyphs_via_mask (cairo_gl_surface_t	*dst,
 			    &_cairo_pattern_white.base,
 			    info, &has_component_alpha);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	/* XXX composite */
-#if 0
 	cairo_surface_pattern_t mask_pattern;
-        mask->is_clear = FALSE;
+	cairo_surface_pattern_t source_pattern;
+
+	mask->is_clear = FALSE;
 	_cairo_pattern_init_for_surface (&mask_pattern, mask);
 	mask_pattern.base.has_component_alpha = has_component_alpha;
+
 	cairo_matrix_init_translate (&mask_pattern.base.matrix,
 		                     -info->extents.x, -info->extents.y);
+
+	_cairo_pattern_init_for_surface (&source_pattern, source);
 	status = _cairo_surface_mask (&dst->base, op,
-		                      source, &mask_pattern.base,
+		                      &source_pattern.base, &mask_pattern.base,
 				      NULL);
+
 	_cairo_pattern_fini (&mask_pattern.base);
-#endif
+	_cairo_pattern_fini (&source_pattern.base);
     } else {
 	for (i = 0; i < info->num_glyphs; i++) {
 	    info->glyphs[i].x += info->extents.x;
commit 33c59030b566ef647c007858b81af6317a8d8740
Author: Martin Robinson <mrobinson at webkit.org>
Date:   Thu Oct 13 15:52:57 2011 -0700

    gl: Fix offset for non-texture surface patterns
    
    Instead of drawing only a portion of the image into the intermediate
    texture, draw the entire image and adjust the translation matrix to
    compensate.

diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index a7e187e..c544532 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -156,7 +156,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
     if (src->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE) {
 	status = _cairo_gl_surface_draw_image (surface,
 				      (cairo_image_surface_t *)src->surface,
-				      src_x, src_y,
+				      0, 0,
 				      width, height,
 				      0, 0);
 
@@ -166,9 +166,8 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
 	cairo_surface_t *image;
 
 	image = cairo_surface_map_to_image (&surface->base, NULL);
-	status = _cairo_surface_offset_paint (image, src_x, src_y,
-					      CAIRO_OPERATOR_SOURCE, _src,
-					      NULL);
+	status = _cairo_surface_paint (image, CAIRO_OPERATOR_SOURCE,
+				       _src, NULL);
 	cairo_surface_unmap_image (&surface->base, image);
 
 	attributes->extend = CAIRO_EXTEND_NONE;
@@ -185,7 +184,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
      * (unnormalized src -> unnormalized src) to
      * (unnormalized dst -> unnormalized src)
      */
-    cairo_matrix_init_translate (&m, -dst_x, -dst_y);
+    cairo_matrix_init_translate (&m, src_x - dst_x, src_y - dst_y);
     cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix);
 
     /* Translate the matrix from
commit c94c3eede088fed36866c934a2637ea49e687a1c
Author: Martin Robinson <mrobinson at igalia.com>
Date:   Thu Oct 27 11:50:18 2011 -0700

    gl/msaa: Fix scissor bounds
    
    Scissor bounds should depend on both the height and y coordinate
    of the bounding box. Also remove _cairo_gl_y_flip() since we were
    the last caller.

diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 2210da6..316dfc8 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -251,8 +251,9 @@ static void
 _scissor_to_rectangle (cairo_gl_surface_t *surface,
 		       const cairo_rectangle_int_t *r)
 {
-    int y = _cairo_gl_y_flip (surface, r->y);
-
+    int y = r->y;
+    if (_cairo_gl_surface_is_texture (surface) == FALSE)
+	y = surface->height - (r->y + r->height);
     glScissor (r->x, y, r->width, r->height);
     glEnable (GL_SCISSOR_TEST);
 }
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index cd7c8ae..19c7c1f 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -542,15 +542,6 @@ _cairo_gl_surface_show_glyphs (void			*abstract_dst,
 			       const cairo_clip_t	*clip,
 			       int			*remaining_glyphs);
 
-static inline int
-_cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
-{
-    if (surface->fb)
-	return y;
-    else
-	return (surface->height - 1) - y;
-}
-
 cairo_private cairo_status_t
 _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
 


More information about the cairo-commit mailing list