[cairo] [PATCH] gl/msaa: Avoid the stencil buffer when possible during masking

Martin Robinson mrobinson at igalia.com
Thu Jan 3 11:13:24 PST 2013


I've reworked this patch a bit to avoid using the scissor test for rectangular clips. This can help avoid flushing in some situations. If no one objects I'll commit these three patches for the MSAA compositor today.

commit c92bd98bc45b5dc395cd77e29e7e85f5e8c8bfd9
Author: Alejandro G. Castro <alex at igalia.com>
Date:   Wed Mar 7 14:38:52 2012 +0100

    gl/msaa: Avoid the stencil buffer when possible during masking
    
    In this case we can draw the clip path and avoid the stencil buffer,
    which can be expensive.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 4ebe966..3adeda8 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -550,7 +550,7 @@ _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
     cairo_gl_surface_t *dst = setup->dst;
     cairo_clip_t *clip = setup->clip;
 
-    if (clip->num_boxes == 1 && clip->path == NULL) {
+    if (_cairo_gl_can_use_scissor_for_clip (clip)) {
 	_scissor_to_box (dst, &clip->boxes[0]);
 	goto disable_stencil_buffer_and_return;
     }
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 5de3449..b2375e1 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -153,18 +153,23 @@ _draw_triangle_fan (cairo_gl_context_t		*ctx,
     return CAIRO_STATUS_SUCCESS;
 }
 
-cairo_int_status_t
-_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
-				     cairo_gl_composite_t *setup,
-				     cairo_clip_t *clip)
+static cairo_int_status_t
+_clip_to_traps (cairo_clip_t *clip,
+		cairo_traps_t *traps)
 {
     cairo_int_status_t status;
-    cairo_traps_t traps;
-
     cairo_polygon_t polygon;
     cairo_antialias_t antialias;
     cairo_fill_rule_t fill_rule;
 
+    _cairo_traps_init (traps);
+
+    if (clip->num_boxes == 1 && clip->path == NULL) {
+	cairo_boxes_t boxes;
+	_cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
+	return _cairo_traps_init_boxes (traps, &boxes);
+    }
+
     status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
     if (unlikely (status))
 	return status;
@@ -180,14 +185,24 @@ _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
      * option.
      */
 
-    _cairo_traps_init (&traps);
-    status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
+    _cairo_traps_init (traps);
+    status = _cairo_bentley_ottmann_tessellate_polygon (traps,
 							&polygon,
 							fill_rule);
-    _cairo_polygon_fini (&polygon);
+    return status;
+}
+
+cairo_int_status_t
+_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
+				     cairo_gl_composite_t *setup,
+				     cairo_clip_t *clip)
+{
+    cairo_int_status_t status;
+    cairo_traps_t traps;
+
+    status = _clip_to_traps (clip, &traps);
     if (unlikely (status))
 	return status;
-
     status = _draw_traps (ctx, setup, &traps);
 
     _cairo_traps_fini (&traps);
@@ -303,6 +318,19 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
     cairo_gl_context_t *ctx = NULL;
     cairo_int_status_t status;
 
+    cairo_clip_t *clip = composite->clip;
+    cairo_traps_t traps;
+
+    /* If we have a non-rectangular clip, we can avoid using the stencil buffer
+     * for clipping and just draw the clip polygon. */
+    if (clip) {
+	status = _clip_to_traps (clip, &traps);
+	if (unlikely (status)) {
+	    _cairo_traps_fini (&traps);
+	    return status;
+	}
+    }
+
     status = _cairo_gl_composite_init (&setup,
 				       CAIRO_OPERATOR_DEST_OUT,
 				       dst,
@@ -321,7 +349,10 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
     if (unlikely (status))
 	goto finish;
 
-    _draw_int_rect (ctx, &setup, &composite->bounded);
+    if (! clip)
+	status = _draw_int_rect (ctx, &setup, &composite->bounded);
+    else
+	status = _draw_traps (ctx, &setup, &traps);
 
     /* Now draw the second pass. */
     _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
@@ -344,12 +375,17 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
     if (unlikely (status))
 	goto finish;
 
-    _draw_int_rect (ctx, &setup, &composite->bounded);
+    if (! clip)
+	status = _draw_int_rect (ctx, &setup, &composite->bounded);
+    else
+	status = _draw_traps (ctx, &setup, &traps);
 
 finish:
     _cairo_gl_composite_fini (&setup);
     if (ctx)
 	status = _cairo_gl_context_release (ctx, status);
+    if (clip)
+	_cairo_traps_fini (&traps);
 
     return status;
 }
@@ -363,6 +399,7 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     cairo_gl_context_t *ctx = NULL;
     cairo_int_status_t status;
     cairo_operator_t op = composite->op;
+    cairo_clip_t *clip = composite->clip;
 
     if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -436,8 +473,6 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     if (unlikely (status))
 	goto finish;
 
-    _cairo_gl_msaa_compositor_set_clip (composite, &setup);
-
     /* We always use multisampling here, because we do not yet have the smarts
        to calculate when the clip or the source requires it. */
      _cairo_gl_composite_set_multisample (&setup);
@@ -446,7 +481,10 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     if (unlikely (status))
 	goto finish;
 
-    _draw_int_rect (ctx, &setup, &composite->bounded);
+    if (! clip)
+	status = _draw_int_rect (ctx, &setup, &composite->bounded);
+    else
+	status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
 
 finish:
     _cairo_gl_composite_fini (&setup);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 5aab17c..dddeab3 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -812,6 +812,12 @@ _cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
     _cairo_rtree_unpin (&cache->rtree);
 }
 
+static inline cairo_bool_t
+_cairo_gl_can_use_scissor_for_clip (cairo_clip_t *clip)
+{
+    return clip->num_boxes == 1 && clip->path == NULL;
+}
+
 
 slim_hidden_proto (cairo_gl_surface_create);
 slim_hidden_proto (cairo_gl_surface_create_for_texture);



More information about the cairo mailing list