[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