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

Martin Robinson <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
commit d404ed57bc88042d6da0e64b72c7a976ae624ec5
Author: Alejandro G. Castro <[email protected]>
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);
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.