[cairo-commit] boilerplate/cairo-boilerplate-xcb.c src/cairo-boxes-intersect.c src/cairo-clip.c src/cairo-clip-private.h src/cairo-composite-rectangles.c src/cairo-composite-rectangles-private.h src/cairo-debug.c src/cairo-xcb-private.h src/cairo-xcb-surface.c src/cairo-xcb-surface-render.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Jul 20 06:46:49 PDT 2011


 boilerplate/cairo-boilerplate-xcb.c      |   92 ++-
 src/cairo-boxes-intersect.c              |    5 
 src/cairo-clip-private.h                 |    3 
 src/cairo-clip.c                         |   32 +
 src/cairo-composite-rectangles-private.h |    4 
 src/cairo-composite-rectangles.c         |   33 +
 src/cairo-debug.c                        |   10 
 src/cairo-xcb-private.h                  |    1 
 src/cairo-xcb-surface-render.c           |  777 +++++++++++++++++++++----------
 src/cairo-xcb-surface.c                  |    1 
 10 files changed, 691 insertions(+), 267 deletions(-)

New commits:
commit d5d4a0f24031580db93d3b7909482687458718e2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 19 11:29:49 2011 +0100

    xcb: Take advantage of clip-boxes
    
    A demonstration of step 2, improves performance for selected benchmarks
    on selected GPUs by up to 30%.
    
    firefox-fishbowl on snb {i5-2520m): 42s -> 29s.
    firefox-talos-gfx on snb: 7.6 -> 5.2s.
    firefox-fishbowl on pnv (n450): 380 -> 360s.
    
    Whist this looks like it is getting close to as good as we can achieve,
    we are constrained by both our API and Xrender and fishbowl is about 50%
    slower than peak performance (on snb).
    
    And it fixes the older performance regression in firefox-planet-gnome.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index 8ce0e8a..b607a29 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -186,25 +186,40 @@ static void _destroy_similar (void *closure)
     free (similar);
 }
 
+struct xcb_info {
+	xcb_render_query_pict_formats_reply_t *formats;
+	xcb_render_pictforminfo_t *render_format[3];
+};
+
 static cairo_surface_t *
 _cairo_boilerplate_xcb_create_similar (cairo_surface_t *other,
 				       cairo_content_t content,
 				       int width, int height)
 {
+    cairo_device_t *device = cairo_surface_get_device (other);
+    struct xcb_info *info = cairo_device_get_user_data (device, &key);
     xcb_screen_t *root;
     cairo_surface_t *surface;
     struct similar *similar;
     xcb_render_pictforminfo_t *render_format;
     int depth;
-    void *formats;
 
     similar = malloc (sizeof (*similar));
 
     switch (content) {
     default:
-    case CAIRO_CONTENT_COLOR_ALPHA: depth = 32; break;
-    case CAIRO_CONTENT_COLOR: depth = 24; break;
-    case CAIRO_CONTENT_ALPHA: depth = 8; break;
+    case CAIRO_CONTENT_COLOR_ALPHA:
+	    depth = 32;
+	    render_format = info->render_format[0];
+	    break;
+    case CAIRO_CONTENT_COLOR:
+	    depth = 24;
+	    render_format = info->render_format[1];
+	    break;
+    case CAIRO_CONTENT_ALPHA:
+	    depth = 8;
+	    render_format = info->render_format[2];
+	    break;
     }
 
     similar->connection =
@@ -216,17 +231,12 @@ _cairo_boilerplate_xcb_create_similar (cairo_surface_t *other,
 		       similar->pixmap, root->root,
 		       width, height);
 
-    render_format = find_depth (similar->connection, depth, &formats);
-    if (render_format == NULL)
-	return NULL;
-
     surface = cairo_xcb_surface_create_with_xrender_format (similar->connection,
 							    root,
 							    similar->pixmap,
 							    render_format,
 							    width, height);
     cairo_surface_set_user_data (surface, &key, similar, _destroy_similar);
-    free(formats);
 
     return surface;
 }
@@ -245,14 +255,17 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
     xcb_screen_t *root;
     xcb_target_closure_t *xtc;
     xcb_connection_t *c;
+    xcb_render_query_pict_formats_cookie_t formats_cookie;
     xcb_render_pictforminfo_t *render_format;
+    xcb_render_pictforminfo_iterator_t i;
+    struct xcb_info *info;
     int depth;
     xcb_void_cookie_t cookie;
     cairo_surface_t *surface;
     cairo_status_t status;
-    void *formats;
 
     *closure = xtc = xmalloc (sizeof (xcb_target_closure_t));
+    info = xcalloc (1, sizeof (struct xcb_info));
 
     if (width == 0)
 	width = 1;
@@ -266,6 +279,7 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
     }
 
     root = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
+    formats_cookie = xcb_render_query_pict_formats (c);
 
     xtc->surface = NULL;
     xtc->is_pixmap = TRUE;
@@ -273,16 +287,10 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
     switch (content) {
     case CAIRO_CONTENT_COLOR:
 	depth = 24;
-	cookie = xcb_create_pixmap_checked (c, depth,
-					    xtc->drawable, root->root,
-					    width, height);
 	break;
 
     case CAIRO_CONTENT_COLOR_ALPHA:
 	depth = 32;
-	cookie = xcb_create_pixmap_checked (c, depth,
-					    xtc->drawable, root->root,
-					    width, height);
 	break;
 
     case CAIRO_CONTENT_ALPHA:  /* would be XCB_PICT_STANDARD_A_8 */
@@ -292,6 +300,10 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
 	return NULL;
     }
 
+    cookie = xcb_create_pixmap_checked (c, depth,
+					xtc->drawable, root->root,
+					width, height);
+
     /* slow, but sure */
     if (xcb_request_check (c, cookie) != NULL) {
 	xcb_disconnect (c);
@@ -299,19 +311,53 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
 	return NULL;
     }
 
-    render_format = find_depth (c, depth, &formats);
-    if (render_format == NULL) {
-	xcb_disconnect (c);
-	free (xtc);
+    info->formats = xcb_render_query_pict_formats_reply (c, formats_cookie, 0);
+    if (info->formats == NULL)
 	return NULL;
+
+    for (i = xcb_render_query_pict_formats_formats_iterator (info->formats);
+	 i.rem;
+	 xcb_render_pictforminfo_next (&i))
+    {
+	if (XCB_RENDER_PICT_TYPE_DIRECT != i.data->type)
+	    continue;
+
+	if (i.data->depth == 32) {
+		if (info->render_format[0] == 0)
+			info->render_format[0] = i.data;
+	} else if (i.data->depth == 24) {
+		if (info->render_format[1] == 0)
+			info->render_format[1] = i.data;
+	} else if (i.data->depth == 8) {
+		if (info->render_format[2] == 0)
+			info->render_format[2] = i.data;
+	}
+    }
+
+    assert (info->render_format[0]);
+    assert (info->render_format[1]);
+    assert (info->render_format[2]);
+
+    switch (content) {
+    default:
+    case CAIRO_CONTENT_COLOR_ALPHA:
+	    render_format = info->render_format[0];
+	    break;
+
+    case CAIRO_CONTENT_COLOR:
+	    render_format = info->render_format[1];
+	    break;
+
+    case CAIRO_CONTENT_ALPHA:  /* would be XCB_PICT_STANDARD_A_8 */
+	    render_format = info->render_format[2];
+	    break;
     }
 
     surface = cairo_xcb_surface_create_with_xrender_format (c, root,
 							    xtc->drawable,
 							    render_format,
 							    width, height);
-    free (formats);
-
+    cairo_device_set_user_data (cairo_surface_get_device (surface), &key, info, free);
     if (mode != CAIRO_BOILERPLATE_MODE_PERF)
 	_cairo_boilerplate_xcb_setup_test_surface(surface);
 
@@ -566,6 +612,7 @@ _cairo_boilerplate_xcb_create_render_0_0 (const char		    *name,
 	free (xtc);
 	return NULL;
     }
+    xcb_flush (c);
 
     render_format = find_depth (c, depth, &formats);
     if (render_format == NULL) {
@@ -593,7 +640,6 @@ _cairo_boilerplate_xcb_create_render_0_0 (const char		    *name,
 							    xtc->drawable,
 							    render_format,
 							    width, height);
-    free (formats);
     cairo_surface_destroy (tmp);
 
     assert (cairo_surface_get_device (surface) == xtc->device);
diff --git a/src/cairo-boxes-intersect.c b/src/cairo-boxes-intersect.c
index 831abc1..230c6f0 100644
--- a/src/cairo-boxes-intersect.c
+++ b/src/cairo-boxes-intersect.c
@@ -572,14 +572,13 @@ _cairo_boxes_intersect (const cairo_boxes_t *a,
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    if (unlikely (a->num_boxes == 1)) {
+    if (a->num_boxes == 1) {
 	cairo_box_t box = a->chunks.base[0];
 	return _cairo_boxes_intersect_with_box (b, &box, out);
     }
-    if (unlikely (b->num_boxes == 1)) {
+    if (b->num_boxes == 1) {
 	cairo_box_t box = b->chunks.base[0];
 	return _cairo_boxes_intersect_with_box (a, &box, out);
-	/* XXX */
     }
 
     rectangles = stack_rectangles;
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 861be63..2ad53ef 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -95,6 +95,9 @@ cairo_private cairo_clip_t *
 _cairo_clip_copy (const cairo_clip_t *clip);
 
 cairo_private cairo_clip_t *
+_cairo_clip_copy_region (const cairo_clip_t *clip);
+
+cairo_private cairo_clip_t *
 _cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty);
 
 cairo_private cairo_bool_t
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 99d7cd4..e5979d5 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -176,6 +176,38 @@ _cairo_clip_copy (const cairo_clip_t *clip)
 }
 
 cairo_clip_t *
+_cairo_clip_copy_region (const cairo_clip_t *clip)
+{
+    cairo_clip_t *copy;
+    int i;
+
+    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+	return (cairo_clip_t *) clip;
+
+    assert (clip->num_boxes);
+
+    copy = _cairo_clip_create ();
+    copy->extents = clip->extents;
+
+    copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+    if (unlikely (copy->boxes == NULL))
+	return _cairo_clip_set_all_clipped (copy);
+
+    for (i = 0; i < clip->num_boxes; i++) {
+	copy->boxes[i].p1.x = _cairo_fixed_floor (clip->boxes[i].p1.x);
+	copy->boxes[i].p1.y = _cairo_fixed_floor (clip->boxes[i].p1.y);
+	copy->boxes[i].p2.x = _cairo_fixed_ceil (clip->boxes[i].p2.x);
+	copy->boxes[i].p2.y = _cairo_fixed_ceil (clip->boxes[i].p2.y);
+    }
+    copy->num_boxes = clip->num_boxes;
+
+    copy->region = cairo_region_reference (clip->region);
+    copy->is_region = TRUE;
+
+    return copy;
+}
+
+cairo_clip_t *
 _cairo_clip_intersect_path (cairo_clip_t       *clip,
 			    const cairo_path_fixed_t *path,
 			    cairo_fill_rule_t   fill_rule,
diff --git a/src/cairo-composite-rectangles-private.h b/src/cairo-composite-rectangles-private.h
index 2b4bdba..62244b2 100644
--- a/src/cairo-composite-rectangles-private.h
+++ b/src/cairo-composite-rectangles-private.h
@@ -104,6 +104,10 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
 					     const cairo_clip_t		*clip,
 					     cairo_bool_t		*overlap);
 
+cairo_private cairo_int_status_t
+_cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t *extents,
+						    const cairo_box_t *box);
+
 cairo_private void
 _cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents);
 
diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index cab7c0c..7f288cb 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -112,6 +112,9 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
     if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
+    if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE))
+	extents->unbounded = extents->bounded;
+
     extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
     if (_cairo_clip_is_all_clipped (extents->clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
@@ -120,6 +123,36 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
 }
 
 cairo_int_status_t
+_cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t *extents,
+					      const cairo_box_t *box)
+{
+    cairo_rectangle_int_t mask;
+    cairo_int_status_t status;
+    cairo_clip_t *clip;
+
+    _cairo_box_round_to_rectangle (box, &mask);
+    if (mask.x == extents->mask.x &&
+	mask.y == extents->mask.y &&
+	mask.width  == extents->mask.width &&
+	mask.height == extents->mask.height)
+    {
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    _cairo_rectangle_intersect (&extents->mask, &mask);
+
+    extents->mask = mask;
+    clip = extents->clip;
+
+    status = _cairo_composite_rectangles_intersect (extents, clip);
+
+    if (clip != extents->clip)
+	_cairo_clip_destroy (clip);
+
+    return status;
+}
+
+cairo_int_status_t
 _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
 					   int surface_width, int surface_height,
 					   cairo_operator_t		 op,
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 99289e3..9e68748 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -269,6 +269,16 @@ _cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon)
 	    _cairo_fixed_to_double (polygon->extents.p1.y),
 	    _cairo_fixed_to_double (polygon->extents.p2.x),
 	    _cairo_fixed_to_double (polygon->extents.p2.y));
+    if (polygon->num_limits) {
+	fprintf (stream,
+		 "       : limit=(%f, %f), (%f, %f) x %d\n",
+		 _cairo_fixed_to_double (polygon->limit.p1.x),
+		 _cairo_fixed_to_double (polygon->limit.p1.y),
+		 _cairo_fixed_to_double (polygon->limit.p2.x),
+		 _cairo_fixed_to_double (polygon->limit.p2.y),
+		 polygon->num_limits);
+    }
+
     for (n = 0; n < polygon->num_edges; n++) {
 	cairo_edge_t *edge = &polygon->edges[n];
 
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index d52306e..1a81cef 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -90,6 +90,7 @@ struct _cairo_xcb_surface {
     int use_pixmap;
 
     cairo_bool_t deferred_clear;
+    cairo_color_t deferred_clear_color;
 
     int width;
     int height;
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 66e933e..ac07023 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -55,6 +55,13 @@
  * extension if it is available.
  */
 
+static cairo_status_t
+_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
+			   cairo_operator_t op,
+			   const cairo_pattern_t *src,
+			   cairo_boxes_t *boxes,
+			   cairo_composite_rectangles_t *extents);
+
 static inline cairo_xcb_connection_t *
 _picture_to_connection (cairo_xcb_picture_t *picture)
 {
@@ -1466,7 +1473,7 @@ _composite_traps (void *closure,
 		  const cairo_pattern_t	*pattern,
 		  int dst_x, int dst_y,
 		  const cairo_rectangle_int_t *extents,
-		  cairo_region_t		*clip_region)
+		  cairo_clip_t		*clip)
 {
     composite_traps_info_t *info = closure;
     const cairo_traps_t *traps = &info->traps;
@@ -1475,8 +1482,15 @@ _composite_traps (void *closure,
     xcb_render_pictformat_t xrender_format;
     xcb_render_trapezoid_t *xtraps;
     int render_reference_x, render_reference_y;
+    cairo_status_t status;
     int i;
 
+    if (dst->deferred_clear) {
+	status = _cairo_xcb_surface_clear (dst);
+	if (unlikely (status))
+		return status;
+    }
+
     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
     if (unlikely (src->base.status))
 	return src->base.status;
@@ -1571,7 +1585,85 @@ typedef cairo_status_t
 		    int					 dst_x,
 		    int					 dst_y,
 		    const cairo_rectangle_int_t		*extents,
-		    cairo_region_t			*clip_region);
+		    cairo_clip_t			*clip);
+
+static void do_unaligned_row(void (*blt)(void *closure,
+					 int16_t x, int16_t y,
+					 int16_t w, int16_t h,
+					 uint16_t coverage),
+			     void *closure,
+			     const cairo_box_t *b,
+			     int tx, int y, int h,
+			     int coverage)
+{
+    int x1 = _cairo_fixed_integer_part (b->p1.x) - tx;
+    int x2 = _cairo_fixed_integer_part (b->p2.x) - tx;
+    if (x2 > x1) {
+	if (! _cairo_fixed_is_integer (b->p1.x)) {
+	    blt(closure, x1, y, 1, h,
+		coverage * (256 - _cairo_fixed_fractional_part (b->p1.x)));
+	    x1++;
+	}
+
+	blt(closure, x1, y, x2-x1, h, 256*coverage);
+
+	if (! _cairo_fixed_is_integer (b->p2.x))
+	    blt(closure, x2, y, 1, h,
+		coverage * _cairo_fixed_fractional_part (b->p2.x));
+    } else
+	blt(closure, x1, y, 1, h,
+	    coverage * (b->p2.x - b->p1.x));
+}
+
+static void do_unaligned_box(void (*blt)(void *closure,
+					 int16_t x, int16_t y,
+					 int16_t w, int16_t h,
+					 uint16_t coverage),
+			     void *closure,
+			     const cairo_box_t *b, int tx, int ty)
+{
+    int y1 = _cairo_fixed_integer_part (b->p1.y) - ty;
+    int y2 = _cairo_fixed_integer_part (b->p2.y) - ty;
+    if (y2 > y1) {
+	if (! _cairo_fixed_is_integer (b->p1.y)) {
+	    do_unaligned_row(blt, closure, b, tx, y1, 1,
+			     256 - _cairo_fixed_fractional_part (b->p1.y));
+	    y1++;
+	}
+
+	do_unaligned_row(blt, closure, b, tx, y1, y2-y1, 256);
+
+	if (! _cairo_fixed_is_integer (b->p2.y))
+	    do_unaligned_row(blt, closure, b, tx, y2, 1,
+			     _cairo_fixed_fractional_part (b->p2.y));
+    } else
+	do_unaligned_row(blt, closure, b, tx, y1, 1,
+			 b->p2.y - b->p1.y);
+}
+
+
+static void blt_in(void *closure,
+		   int16_t x, int16_t y,
+		   int16_t w, int16_t h,
+		   uint16_t coverage)
+{
+    cairo_xcb_surface_t *mask = closure;
+    xcb_render_color_t color;
+    xcb_rectangle_t rect;
+
+    color.red = color.green = color.blue = 0;
+    color.alpha = coverage;
+
+    rect.x = x;
+    rect.y = y;
+    rect.width = w;
+    rect.height = h;
+
+    _cairo_xcb_connection_render_fill_rectangles (mask->connection,
+						  XCB_RENDER_PICT_OP_IN,
+						  mask->picture,
+						  color, 1, &rect);
+}
 
 static cairo_xcb_surface_t *
 _create_composite_mask (cairo_clip_t		*clip,
@@ -1581,11 +1673,9 @@ _create_composite_mask (cairo_clip_t		*clip,
 			const cairo_rectangle_int_t*extents)
 {
     cairo_xcb_surface_t *surface;
-    cairo_bool_t clip_surface = FALSE;
+    cairo_bool_t need_clip_combine;
     cairo_status_t status;
 
-    clip_surface = ! _cairo_clip_is_region (clip);
-
     surface = (cairo_xcb_surface_t *)
 	_cairo_xcb_surface_create_similar (dst, CAIRO_CONTENT_ALPHA,
 					   extents->width, extents->height);
@@ -1594,27 +1684,9 @@ _create_composite_mask (cairo_clip_t		*clip,
 
     _cairo_xcb_surface_ensure_picture (surface);
 
-    if (surface->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
-	xcb_render_color_t clear;
-	xcb_rectangle_t xrect;
-
-	clear.red = clear.green = clear.blue = clear.alpha = 0;
-
-	xrect.x = xrect.y = 0;
-	xrect.width  = extents->width;
-	xrect.height = extents->height;
-
-	_cairo_xcb_connection_render_fill_rectangles (surface->connection,
-						      XCB_RENDER_PICT_OP_CLEAR,
-						      surface->picture,
-						      clear, 1, &xrect);
-    } else {
-	status = _cairo_xcb_surface_clear (surface);
-	if (unlikely (status)) {
-	    cairo_surface_destroy (&surface->base);
-	    return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
-	}
-    }
+    surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
+    surface->deferred_clear = TRUE;
+    surface->base.is_clear = TRUE;
 
     /* Is it worth setting the clip region here? */
     status = draw_func (draw_closure, surface,
@@ -1626,7 +1698,26 @@ _create_composite_mask (cairo_clip_t		*clip,
 	return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
     }
 
-    if (clip_surface) {
+    if (surface->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
+	int i;
+
+	for (i = 0; i < clip->num_boxes; i++) {
+	    cairo_box_t *b = &clip->boxes[i];
+
+	    if (! _cairo_fixed_is_integer (b->p1.x) ||
+		! _cairo_fixed_is_integer (b->p1.y) ||
+		! _cairo_fixed_is_integer (b->p2.x) ||
+		! _cairo_fixed_is_integer (b->p2.y))
+	    {
+		do_unaligned_box(blt_in, surface, b, extents->x, extents->y);
+	    }
+	}
+
+	need_clip_combine = clip->path != NULL;
+    } else
+	need_clip_combine = ! _cairo_clip_is_region (clip);
+
+    if (need_clip_combine) {
 	status = _cairo_clip_combine_with_surface (clip, &surface->base,
 						   extents->x, extents->y);
 	if (unlikely (status)) {
@@ -2160,17 +2251,27 @@ _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
     rect.height = dst->height;
 
     if (dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
-	xcb_render_color_t transparent = { 0 };
+	xcb_render_color_t color;
+	uint8_t op;
+
+	color.red   = dst->deferred_clear_color.red_short;
+	color.green = dst->deferred_clear_color.green_short;
+	color.blue  = dst->deferred_clear_color.blue_short;
+	color.alpha = dst->deferred_clear_color.alpha_short;
+
+	if (color.alpha == 0)
+	    op = XCB_RENDER_PICT_OP_CLEAR;
+	else
+	    op = XCB_RENDER_PICT_OP_SRC;
 
 	_cairo_xcb_surface_ensure_picture (dst);
 	_cairo_xcb_connection_render_fill_rectangles (dst->connection,
-						      XCB_RENDER_PICT_OP_CLEAR,
-						      dst->picture,
-						      transparent,
+						      op, dst->picture, color,
 						      1, &rect);
     } else {
 	gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
 
+	/* XXX color */
 	_cairo_xcb_connection_poly_fill_rectangle (dst->connection,
 						   dst->drawable, gc,
 						   1, &rect);
@@ -2184,22 +2285,34 @@ _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
     return CAIRO_STATUS_SUCCESS;
 }
 
+enum {
+    NEED_CLIP_REGION = 0x1,
+    NEED_CLIP_SURFACE = 0x2,
+};
+
 static cairo_bool_t
 need_bounded_clip (cairo_composite_rectangles_t *extents)
 {
-	return ! _cairo_clip_is_region (extents->clip);
+    unsigned int flags = NEED_CLIP_REGION;
+    if (! _cairo_clip_is_region (extents->clip))
+	flags |= NEED_CLIP_SURFACE;
+    return flags;
 }
 
 static cairo_bool_t
 need_unbounded_clip (cairo_composite_rectangles_t *extents)
 {
-    if (! extents->is_bounded)
-	return need_bounded_clip (extents);
-
-    return extents->clip->path != NULL;
+    unsigned int flags = 0;
+    if (! extents->is_bounded) {
+	flags |= NEED_CLIP_REGION;
+	if (! _cairo_clip_is_region (extents->clip))
+	    flags |= NEED_CLIP_SURFACE;
+    }
+    if (extents->clip->path != NULL)
+	flags |= NEED_CLIP_SURFACE;
+    return flags;
 }
 
-
 static cairo_status_t
 _clip_and_composite (cairo_xcb_surface_t	*dst,
 		     cairo_operator_t		 op,
@@ -2207,10 +2320,10 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 		     xcb_draw_func_t		 draw_func,
 		     void			*draw_closure,
 		     cairo_composite_rectangles_t*extents,
-		     cairo_bool_t need_clip_surface)
+		     unsigned int need_clip)
 {
+    cairo_region_t *clip_region = NULL;
     cairo_status_t status;
-    cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
 
     status = _cairo_xcb_connection_acquire (dst->connection);
     if (unlikely (status))
@@ -2226,11 +2339,16 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 
     _cairo_xcb_surface_ensure_picture (dst);
 
-    if (clip_region != NULL) {
-	status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
-	if (unlikely (status)) {
-	    _cairo_xcb_connection_release (dst->connection);
-	    return status;
+    if (need_clip & NEED_CLIP_REGION) {
+	clip_region = _cairo_clip_get_region (extents->clip);
+	if (cairo_region_contains_rectangle (clip_region, &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
+	    clip_region = NULL;
+	if (clip_region != NULL) {
+	    status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
+	    if (unlikely (status)) {
+		_cairo_xcb_connection_release (dst->connection);
+		return status;
+	    }
 	}
     }
 
@@ -2249,7 +2367,7 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 	    src = NULL;
 	}
 
-	if (need_clip_surface) {
+	if (need_clip & NEED_CLIP_SURFACE) {
 	    if (extents->is_bounded) {
 		status = _clip_and_composite_with_mask (extents->clip, op, src,
 							draw_func, draw_closure,
@@ -2264,18 +2382,18 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 				dst, op, src,
 				0, 0,
 				&extents->bounded,
-				clip_region);
+				extents->clip);
 	}
     }
 
     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
-	if (need_clip_surface)
+	if (need_clip & NEED_CLIP_SURFACE)
 	    status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst, extents, extents->clip);
 	else
 	    status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
     }
 
-    if (clip_region != NULL)
+    if (clip_region)
 	_cairo_xcb_surface_clear_clip_region (dst);
 
     _cairo_xcb_connection_release (dst->connection);
@@ -2336,7 +2454,7 @@ _composite_boxes (cairo_xcb_surface_t *dst,
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
+    if (cairo_region_contains_rectangle (clip_region, &extents->bounded) == CAIRO_REGION_OVERLAP_IN)
 	clip_region = NULL;
 
     status = _cairo_xcb_connection_acquire (dst->connection);
@@ -2550,7 +2668,7 @@ _upload_image_inplace (cairo_xcb_surface_t *surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_int_status_t
 trim_extents_to_traps (cairo_composite_rectangles_t *extents,
 		       cairo_traps_t *traps)
 {
@@ -2560,87 +2678,7 @@ trim_extents_to_traps (cairo_composite_rectangles_t *extents,
      * we need to compensate when fixing up the unbounded area.
     */
     _cairo_traps_extents (traps, &box);
-    _cairo_box_round_to_rectangle (&box, &extents->mask);
-    _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
-}
-
-static cairo_status_t
-_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
-			   cairo_operator_t op,
-			   const cairo_pattern_t *src,
-			   cairo_boxes_t *boxes,
-			   cairo_composite_rectangles_t *extents)
-{
-    composite_traps_info_t info;
-    cairo_int_status_t status;
-
-    if (boxes->num_boxes == 0 && extents->is_bounded)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) &&
-	(op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->base.is_clear)))
-    {
-	if (boxes->num_boxes == 1 &&
-	    extents->bounded.width  == dst->width &&
-	    extents->bounded.height == dst->height)
-	{
-	    op = CAIRO_OPERATOR_SOURCE;
-	    dst->deferred_clear = FALSE;
-	}
-
-	status = _upload_image_inplace (dst, src, boxes);
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
-    }
-
-    if (dst->deferred_clear) {
-	status = _cairo_xcb_surface_clear (dst);
-	if (unlikely (status)) {
-	    return status;
-	}
-
-	if (op == CAIRO_OPERATOR_OVER)
-	    op = CAIRO_OPERATOR_SOURCE;
-    }
-
-    if (boxes->is_pixel_aligned &&
-	_cairo_clip_is_region (extents->clip) &&
-	op == CAIRO_OPERATOR_SOURCE) {
-	status = _upload_image_inplace (dst, src, boxes);
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
-    }
-
-    if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
-	return _core_boxes (dst, op, src, boxes, extents);
-
-    if (dst->deferred_clear) {
-	status = _cairo_xcb_surface_clear (dst);
-	if (unlikely (status))
-	    return status;
-    }
-
-    /* Use a fast path if the boxes are pixel aligned */
-    status = _composite_boxes (dst, op, src, boxes, extents);
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	return status;
-
-    if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) == 0)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Otherwise render via a mask and composite in the usual fashion.  */
-    status = _cairo_traps_init_boxes (&info.traps, boxes);
-    if (unlikely (status))
-	return status;
-
-    trim_extents_to_traps (extents, &info.traps);
-    info.antialias = CAIRO_ANTIALIAS_DEFAULT;
-    status = _clip_and_composite (dst, op, src,
-				  _composite_traps, &info,
-				  extents, need_unbounded_clip (extents));
-
-    _cairo_traps_fini (&info.traps);
-    return status;
+    return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
 }
 
 static cairo_bool_t
@@ -2735,6 +2773,206 @@ _boxes_for_traps (cairo_boxes_t *boxes,
 }
 
 static cairo_status_t
+_composite_polygon (cairo_xcb_surface_t *dst,
+		    cairo_operator_t op,
+		    const cairo_pattern_t *source,
+		    cairo_polygon_t *polygon,
+		    cairo_antialias_t antialias,
+		    cairo_fill_rule_t fill_rule,
+		    cairo_composite_rectangles_t *extents)
+{
+    composite_traps_info_t traps;
+    cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
+    cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
+    cairo_status_t status;
+
+    if (polygon->num_edges == 0) {
+	status = CAIRO_STATUS_SUCCESS;
+
+	if (! extents->is_bounded) {
+	    if (cairo_region_contains_rectangle (clip_region, &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
+		clip_region = NULL;
+
+	    if (clip_surface == FALSE) {
+		if (clip_region != NULL) {
+		    status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
+		    if (unlikely (status))
+			return status;
+		}
+
+		status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
+
+		if (clip_region != NULL)
+		    _cairo_xcb_surface_clear_clip_region (dst);
+	    } else {
+		status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst,
+								       extents,
+								       extents->clip);
+	    }
+	}
+
+	return status;
+    }
+
+    _cairo_traps_init (&traps.traps);
+
+    status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
+    if (unlikely (status))
+	goto CLEANUP_TRAPS;
+
+    if (traps.traps.has_intersections) {
+	if (traps.traps.is_rectangular)
+	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
+	else if (traps.traps.is_rectilinear)
+	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
+	else
+	    status = _cairo_bentley_ottmann_tessellate_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
+	if (unlikely (status))
+	    goto CLEANUP_TRAPS;
+    }
+
+    /* Use a fast path if the trapezoids consist of a simple region,
+     * but we can only do this if we do not have a clip surface, or can
+     * substitute the mask with the clip.
+     */
+    if (traps.traps.maybe_region &&
+	_traps_are_pixel_aligned (&traps.traps, antialias) &&
+	(! clip_surface ||
+	 (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
+    {
+	cairo_boxes_t boxes;
+
+	_boxes_for_traps (&boxes, &traps.traps, antialias);
+	status = _clip_and_composite_boxes (dst, op, source,
+					    &boxes, extents);
+    }
+    else
+    {
+	/* Otherwise render the trapezoids to a mask and composite in the usual
+	 * fashion.
+	 */
+	traps.antialias = antialias;
+	status = trim_extents_to_traps (extents, &traps.traps);
+	if (likely (status == CAIRO_STATUS_SUCCESS)) {
+	    status = _clip_and_composite (dst, op, source,
+					  _composite_traps, &traps,
+					  extents, need_unbounded_clip (extents));
+	}
+    }
+
+CLEANUP_TRAPS:
+    _cairo_traps_fini (&traps.traps);
+
+    return status;
+}
+
+
+static cairo_status_t
+_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
+			   cairo_operator_t op,
+			   const cairo_pattern_t *src,
+			   cairo_boxes_t *boxes,
+			   cairo_composite_rectangles_t *extents)
+{
+    composite_traps_info_t info;
+    cairo_int_status_t status;
+
+    if (boxes->num_boxes == 0 && extents->is_bounded)
+	return CAIRO_STATUS_SUCCESS;
+
+    if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) &&
+	(op == CAIRO_OPERATOR_SOURCE ||
+	 (dst->base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD))))
+    {
+	if (boxes->num_boxes == 1 &&
+	    extents->bounded.width  == dst->width &&
+	    extents->bounded.height == dst->height)
+	{
+	    op = CAIRO_OPERATOR_SOURCE;
+	    dst->deferred_clear = FALSE;
+	}
+
+	status = _upload_image_inplace (dst, src, boxes);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
+
+    /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
+    if (extents->clip->path != NULL && extents->is_bounded) {
+	cairo_polygon_t polygon;
+	cairo_fill_rule_t fill_rule;
+	cairo_antialias_t antialias;
+	cairo_clip_t *clip ;
+
+	clip = _cairo_clip_copy (extents->clip);
+	clip = _cairo_clip_intersect_boxes (clip, boxes);
+	status = _cairo_clip_get_polygon (clip, &polygon,
+					  &fill_rule, &antialias);
+	_cairo_clip_path_destroy (clip->path);
+	clip->path = NULL;
+	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
+	    cairo_clip_t *saved_clip = extents->clip;
+	    extents->clip = clip;
+	    status = _composite_polygon (dst, op, src,
+					 &polygon,
+					 antialias,
+					 fill_rule,
+					 extents);
+	    if (extents->clip != clip)
+		clip = NULL;
+	    extents->clip = saved_clip;
+	    _cairo_polygon_fini (&polygon);
+	}
+	if (clip)
+	    _cairo_clip_destroy (clip);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
+
+    if (dst->deferred_clear) {
+	status = _cairo_xcb_surface_clear (dst);
+	if (unlikely (status))
+	    return status;
+    }
+
+    if (boxes->is_pixel_aligned &&
+	_cairo_clip_is_region (extents->clip) &&
+	op == CAIRO_OPERATOR_SOURCE) {
+	status = _upload_image_inplace (dst, src, boxes);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
+
+    if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
+	return _core_boxes (dst, op, src, boxes, extents);
+
+    /* Use a fast path if the boxes are pixel aligned */
+    status = _composite_boxes (dst, op, src, boxes, extents);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) == 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Otherwise render via a mask and composite in the usual fashion.  */
+    status = _cairo_traps_init_boxes (&info.traps, boxes);
+    if (unlikely (status))
+	return status;
+
+    info.antialias = CAIRO_ANTIALIAS_DEFAULT;
+    status = trim_extents_to_traps (extents, &info.traps);
+    if (status == CAIRO_INT_STATUS_SUCCESS) {
+	status = _clip_and_composite (dst, op, src,
+				      _composite_traps, &info,
+					  extents, need_unbounded_clip (extents));
+    }
+
+    _cairo_traps_fini (&info.traps);
+    return status;
+}
+
+static cairo_status_t
 _composite_mask (void				*closure,
 		 cairo_xcb_surface_t		*dst,
 		 cairo_operator_t		 op,
@@ -2742,10 +2980,25 @@ _composite_mask (void				*closure,
 		 int				 dst_x,
 		 int				 dst_y,
 		 const cairo_rectangle_int_t	*extents,
-		 cairo_region_t			*clip_region)
+		 cairo_clip_t			*clip)
 {
     const cairo_pattern_t *mask_pattern = closure;
     cairo_xcb_picture_t *src, *mask = NULL;
+    cairo_status_t status;
+
+    if (dst->base.is_clear) {
+	if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
+	    op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (op == CAIRO_OPERATOR_SOURCE && clip == NULL)
+	dst->deferred_clear = FALSE;
+
+    if (dst->deferred_clear) {
+	status = _cairo_xcb_surface_clear (dst);
+	if (unlikely (status))
+		return status;
+    }
 
     if (src_pattern != NULL) {
 	src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
@@ -2789,6 +3042,105 @@ _composite_mask (void				*closure,
     return CAIRO_STATUS_SUCCESS;
 }
 
+struct composite_opacity_info {
+    uint8_t op;
+    cairo_xcb_surface_t *dst;
+    cairo_xcb_picture_t *src;
+    double opacity;
+};
+
+static void composite_opacity(void *closure,
+			      int16_t x, int16_t y,
+			      int16_t w, int16_t h,
+			      uint16_t coverage)
+{
+    struct composite_opacity_info *info = closure;
+    cairo_solid_pattern_t mask_pattern;
+    cairo_xcb_picture_t *mask;
+    cairo_color_t color;
+
+    color.red = color.green = color.blue = 0;
+    color.alpha = info->opacity * coverage;
+    _cairo_pattern_init_solid (&mask_pattern, &color);
+
+    mask = _cairo_xcb_picture_for_pattern (info->dst, &mask_pattern.base, NULL);
+    if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
+	if (info->src) {
+	    _cairo_xcb_connection_render_composite (info->dst->connection,
+						    info->op,
+						    info->src->picture,
+						    mask->picture,
+						    info->dst->picture,
+						    x + info->src->x,  y + info->src->y,
+						    0,                 0,
+						    x,                 y,
+						    w,                 h);
+	} else {
+	    _cairo_xcb_connection_render_composite (info->dst->connection,
+						    info->op,
+						    mask->picture,
+						    XCB_NONE,
+						    info->dst->picture,
+						    0,                 0,
+						    0,                 0,
+						    x,                 y,
+						    w,                 h);
+	}
+    }
+
+    cairo_surface_destroy (&mask->base);
+}
+
+static cairo_status_t
+_composite_opacity_boxes (void				*closure,
+			  cairo_xcb_surface_t		*dst,
+			  cairo_operator_t		 op,
+			  const cairo_pattern_t		*src_pattern,
+			  int				 dst_x,
+			  int				 dst_y,
+			  const cairo_rectangle_int_t	*extents,
+			  cairo_clip_t			*clip)
+{
+    const cairo_solid_pattern_t *mask_pattern = closure;
+    struct composite_opacity_info info;
+    cairo_status_t status;
+    int i;
+
+    if (dst->base.is_clear) {
+	if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
+	    op = CAIRO_OPERATOR_SOURCE;
+    }
+
+    if (op == CAIRO_OPERATOR_SOURCE && clip == NULL)
+	dst->deferred_clear = FALSE;
+
+    if (dst->deferred_clear) {
+	status = _cairo_xcb_surface_clear (dst);
+	if (unlikely (status))
+	    return status;
+    }
+
+    info.op = _render_operator (op);
+    info.dst = dst;
+
+    if (src_pattern != NULL) {
+	info.src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
+	if (unlikely (info.src->base.status))
+	    return info.src->base.status;
+    } else
+	info.src = NULL;
+
+    info.opacity = mask_pattern->color.alpha;
+
+    /* XXX for lots of boxes create a clip region for the fully opaque areas */
+    for (i = 0; i < clip->num_boxes; i++)
+	do_unaligned_box(composite_opacity, &info,
+			 &clip->boxes[i], dst_x, dst_y);
+    cairo_surface_destroy (&info.src->base);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 /* high level rasteriser -> compositor */
 
 cairo_int_status_t
@@ -2812,6 +3164,19 @@ _cairo_xcb_surface_render_paint (cairo_xcb_surface_t	*surface,
 
     if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
 	surface->deferred_clear = TRUE;
+	surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (clip == NULL &&
+	source->type == CAIRO_PATTERN_TYPE_SOLID &&
+	(op == CAIRO_OPERATOR_SOURCE ||
+	 (surface->base.is_clear &&
+	  (op == CAIRO_OPERATOR_ADD || op == CAIRO_OPERATOR_OVER))))
+    {
+	cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
+	surface->deferred_clear = TRUE;
+	surface->deferred_clear_color = solid->color;
 	return CAIRO_STATUS_SUCCESS;
     }
 
@@ -2856,103 +3221,19 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-    status = _clip_and_composite (surface, op, source,
-				  _composite_mask, (void *) mask,
-				  &extents, need_bounded_clip (&extents));
-
-    _cairo_composite_rectangles_fini (&extents);
-
-    return status;
-}
-
-static cairo_status_t
-_cairo_xcb_surface_render_composite_polygon (cairo_xcb_surface_t *dst,
-					     cairo_operator_t op,
-					     const cairo_pattern_t *source,
-					     cairo_polygon_t *polygon,
-					     cairo_antialias_t antialias,
-					     cairo_fill_rule_t fill_rule,
-					     cairo_composite_rectangles_t *extents)
-{
-    composite_traps_info_t traps;
-    cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
-    cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
-    cairo_status_t status;
-
-    if (polygon->num_edges == 0) {
-	status = CAIRO_STATUS_SUCCESS;
-
-	if (! extents->is_bounded) {
-		if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
-		    clip_region = NULL;
-
-	    if (clip_surface == FALSE) {
-		if (clip_region != NULL) {
-		    status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
-		    if (unlikely (status))
-			return status;
-		}
-
-		status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
-
-		if (clip_region != NULL)
-		    _cairo_xcb_surface_clear_clip_region (dst);
-	    } else {
-		status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst,
-								       extents,
-								       extents->clip);
-	    }
-	}
-
-	return status;
-    }
-
-    _cairo_traps_init (&traps.traps);
-
-    status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
-    if (unlikely (status))
-	goto CLEANUP_TRAPS;
-
-    if (traps.traps.has_intersections) {
-	if (traps.traps.is_rectangular)
-	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
-	else if (traps.traps.is_rectilinear)
-	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
-	else
-	    status = _cairo_bentley_ottmann_tessellate_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
-	if (unlikely (status))
-	    goto CLEANUP_TRAPS;
-    }
-
-    /* Use a fast path if the trapezoids consist of a simple region,
-     * but we can only do this if we do not have a clip surface, or can
-     * substitute the mask with the clip.
-     */
-    if (traps.traps.maybe_region &&
-	_traps_are_pixel_aligned (&traps.traps, antialias) &&
-	(! clip_surface ||
-	 (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
-    {
-	cairo_boxes_t boxes;
-
-	_boxes_for_traps (&boxes, &traps.traps, antialias);
-	status = _clip_and_composite_boxes (dst, op, source,
-					    &boxes, extents);
-    }
-    else
-    {
-	/* Otherwise render the trapezoids to a mask and composite in the usual
-	 * fashion.
-	 */
-	trim_extents_to_traps (extents, &traps.traps);
-	traps.antialias = antialias;
-	status = _clip_and_composite (dst, op, source,
-				      _composite_traps, &traps,
-				      extents, need_unbounded_clip (extents));
+    if (mask->type == CAIRO_PATTERN_TYPE_SOLID &&
+	extents.clip->path == NULL &&
+	! _cairo_clip_is_region (extents.clip)) {
+	status = _clip_and_composite (surface, op, source,
+				      _composite_opacity_boxes, (void *) mask,
+				      &extents, need_unbounded_clip (&extents));
+    } else {
+	status = _clip_and_composite (surface, op, source,
+				      _composite_mask, (void *) mask,
+				      &extents, need_bounded_clip (&extents));
     }
 
-CLEANUP_TRAPS:
-    _cairo_traps_fini (&traps.traps);
+    _cairo_composite_rectangles_fini (&extents);
 
     return status;
 }
@@ -2979,10 +3260,10 @@ _cairo_xcb_surface_render_stroke_as_polygon (cairo_xcb_surface_t	*dst,
 						  tolerance,
 						  &polygon);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	status = _cairo_xcb_surface_render_composite_polygon (dst, op, source,
-							      &polygon, antialias,
-							      CAIRO_FILL_RULE_WINDING,
-							      extents);
+	status = _composite_polygon (dst, op, source,
+				     &polygon, antialias,
+				     CAIRO_FILL_RULE_WINDING,
+				     extents);
     }
     _cairo_polygon_fini (&polygon);
 
@@ -3011,6 +3292,7 @@ _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t		*dst,
 {
     cairo_surface_t *image;
     cairo_status_t status;
+    cairo_clip_t *clip;
     int x, y;
 
     x = extents->bounded.x;
@@ -3023,13 +3305,15 @@ _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t		*dst,
 
     _clear_image (image);
 
+    clip = _cairo_clip_copy_region (extents->clip);
     status = _cairo_surface_offset_stroke (image, x, y,
 					   CAIRO_OPERATOR_ADD,
 					   &_cairo_pattern_white.base,
 					   path, stroke_style,
 					   ctm, ctm_inverse,
 					   tolerance, antialias,
-					   NULL);
+					   clip);
+    _cairo_clip_destroy (clip);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
 	cairo_surface_pattern_t mask;
 
@@ -3082,7 +3366,6 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t	*surface,
     if (unlikely (status))
 	return status;
 
-
     status = CAIRO_INT_STATUS_UNSUPPORTED;
     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
 	cairo_boxes_t boxes;
@@ -3139,11 +3422,11 @@ _cairo_xcb_surface_render_fill_as_polygon (cairo_xcb_surface_t	*dst,
     _cairo_polygon_init_with_clip (&polygon, extents->clip);
     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	status = _cairo_xcb_surface_render_composite_polygon (dst, op, source,
-							      &polygon,
-							      antialias,
-							      fill_rule,
-							      extents);
+	status = _composite_polygon (dst, op, source,
+				     &polygon,
+				     antialias,
+				     fill_rule,
+				     extents);
     }
     _cairo_polygon_fini (&polygon);
 
@@ -3162,6 +3445,7 @@ _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t	*dst,
 {
     cairo_surface_t *image;
     cairo_status_t status;
+    cairo_clip_t *clip;
     int x, y;
 
     x = extents->bounded.x;
@@ -3175,11 +3459,13 @@ _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t	*dst,
 
     _clear_image (image);
 
+    clip = _cairo_clip_copy_region (extents->clip);
     status = _cairo_surface_offset_fill (image, x, y,
 					 CAIRO_OPERATOR_ADD,
 					 &_cairo_pattern_white.base,
 					 path, fill_rule, tolerance, antialias,
-					 NULL);
+					 clip);
+    _cairo_clip_destroy (clip);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
 	cairo_surface_pattern_t mask;
 
@@ -3277,6 +3563,7 @@ _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t		*dst,
     cairo_surface_t *image;
     cairo_content_t content;
     cairo_status_t status;
+    cairo_clip_t *clip;
     int x, y;
 
     content = CAIRO_CONTENT_ALPHA;
@@ -3293,11 +3580,13 @@ _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t		*dst,
 
     _clear_image (image);
 
+    clip = _cairo_clip_copy_region (extents->clip);
     status = _cairo_surface_offset_glyphs (image, x, y,
 					   CAIRO_OPERATOR_ADD,
 					   &_cairo_pattern_white.base,
 					   scaled_font, glyphs, num_glyphs,
-					   NULL);
+					   clip);
+    _cairo_clip_destroy (clip);
     if (likely (status == CAIRO_STATUS_SUCCESS)) {
 	cairo_surface_pattern_t mask;
 
@@ -4007,7 +4296,7 @@ _composite_glyphs (void				*closure,
 		  int				 dst_x,
 		  int				 dst_y,
 		  const cairo_rectangle_int_t	*extents,
-		  cairo_region_t		*clip_region)
+		  cairo_clip_t			*clip)
 {
     composite_glyphs_info_t *info = closure;
     cairo_scaled_glyph_t *glyph_cache[64];
@@ -4023,6 +4312,12 @@ _composite_glyphs (void				*closure,
     unsigned int request_size = 0;
     int i;
 
+    if (dst->deferred_clear) {
+	status = _cairo_xcb_surface_clear (dst);
+	if (unlikely (status))
+		return status;
+    }
+
     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
     if (unlikely (src->base.status))
 	return src->base.status;
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 6738cdd..200c4c0 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -927,6 +927,7 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t		*screen,
     surface->use_pixmap = 0;
 
     surface->deferred_clear = FALSE;
+    surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
 
     surface->width  = width;
     surface->height = height;


More information about the cairo-commit mailing list