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

Martin Robinson mrobinson at igalia.com
Sun Dec 30 10:05:35 PST 2012


commit d404ed57bc88042d6da0e64b72c7a976ae624ec5
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 6731886..dbd4e02 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 d96d746..03bc658 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -153,14 +153,11 @@ _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;
@@ -180,14 +177,24 @@ _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
      * option.
      */
 
-    _cairo_traps_init (&traps);
-    status = _cairo_bentley_ottmann_tessellate_polygon (&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;
+
+    _cairo_traps_init (&traps);
+    status = _clip_to_traps (clip, &traps);
     if (unlikely (status))
 	return status;
-
     status = _draw_traps (ctx, setup, &traps);
 
     _cairo_traps_fini (&traps);
@@ -303,6 +310,22 @@ _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;
+    cairo_bool_t draw_clip_traps;
+
+    /* If we have a non-rectangular clip, we can avoid using the stencil buffer
+     * for clipping and just draw the clip polygon. */
+    draw_clip_traps = clip && ! _cairo_gl_can_use_scissor_for_clip (clip);
+    if (draw_clip_traps) {
+	_cairo_traps_init (&traps);
+	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,
@@ -315,13 +338,19 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
 					     &composite->bounded);
     if (unlikely (status))
 	goto finish;
-    _cairo_gl_composite_set_clip (&setup, composite->clip);
+
+    if (draw_clip_traps)
+	_cairo_gl_composite_set_clip (&setup, clip);
+
     _cairo_gl_composite_set_multisample (&setup);
     status = _cairo_gl_composite_begin (&setup, &ctx);
     if (unlikely (status))
 	goto finish;
 
-    _draw_int_rect (ctx, &setup, &composite->bounded);
+    if (! draw_clip_traps)
+	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 +373,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 (! draw_clip_traps)
+	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 (draw_clip_traps)
+	_cairo_traps_fini (&traps);
 
     return status;
 }
@@ -364,6 +398,9 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     cairo_int_status_t status;
     cairo_operator_t op = composite->op;
 
+    cairo_clip_t *clip = composite->clip;
+    cairo_bool_t draw_clip_traps;
+
     if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -436,7 +473,11 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     if (unlikely (status))
 	goto finish;
 
-    _cairo_gl_msaa_compositor_set_clip (composite, &setup);
+    /* If we have a non-rectangular clip, we can avoid using the stencil buffer
+     * for clipping and just draw the clip polygon. */
+    draw_clip_traps = clip && ! _cairo_gl_can_use_scissor_for_clip (clip);
+    if (! draw_clip_traps)
+	_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. */
@@ -446,7 +487,10 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
     if (unlikely (status))
 	goto finish;
 
-    _draw_int_rect (ctx, &setup, &composite->bounded);
+    if (! draw_clip_traps)
+	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 1a4d40e..56f55ea 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -802,6 +802,13 @@ _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