[cairo-commit] 3 commits - src/cairo-gl-composite.c src/cairo-gl-msaa-compositor.c src/cairo-gl-private.h

Martin Robinson mrobinson at kemper.freedesktop.org
Thu Jan 3 16:59:42 PST 2013


 src/cairo-gl-composite.c       |  125 +++++++++++++++++-----------
 src/cairo-gl-msaa-compositor.c |  182 +++++++++++++++++++++++++++++++++++------
 src/cairo-gl-private.h         |   13 ++
 3 files changed, 247 insertions(+), 73 deletions(-)

New commits:
commit 9dde964553f74ccbc037b13ca83d0abb46adb194
Author: Henry Song <henry.song at samsung.com>
Date:   Thu Jan 3 16:03:55 2013 -0800

    gl/msaa: Only clear parts of the stencil buffer we will use
    
    Writing to the stencil buffer can be expensive, so when using the
    stencil buffer for clipping only clear the clip extent. When using the
    stencil buffer to prevent overlapping rendering during stroking, only
    clear the approximate stroke extents.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 4ebe966..486ab60 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -501,8 +501,8 @@ _scissor_to_doubles (cairo_gl_surface_t	*surface,
     glEnable (GL_SCISSOR_TEST);
 }
 
-static void
-_scissor_to_rectangle (cairo_gl_surface_t *surface,
+void
+_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
 		       const cairo_rectangle_int_t *r)
 {
     _scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height);
@@ -555,19 +555,22 @@ _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
 	goto disable_stencil_buffer_and_return;
     }
 
-    /* If we cannot reduce the clip to a rectangular region,
-       we clip using the stencil buffer. */
-    glDisable (GL_SCISSOR_TEST);
-
     if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) {
 	status = CAIRO_INT_STATUS_UNSUPPORTED;
 	goto disable_stencil_buffer_and_return;
     }
 
+    /* The clip is not rectangular, so use the stencil buffer. */
     glDepthMask (GL_TRUE);
     glEnable (GL_STENCIL_TEST);
+
+    /* Clear the stencil buffer, but only the areas that we are
+     * going to be drawing to. */
+    _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));
     glClearStencil (0);
     glClear (GL_STENCIL_BUFFER_BIT);
+    glDisable (GL_SCISSOR_TEST);
+
     glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
     glStencilFunc (GL_EQUAL, 1, 0xffffffff);
     glColorMask (0, 0, 0, 0);
@@ -787,7 +790,7 @@ _cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx,
 
 	cairo_region_get_rectangle (ctx->clip_region, i, &rect);
 
-	_scissor_to_rectangle (ctx->current_target, &rect);
+	_cairo_gl_scissor_to_rectangle (ctx->current_target, &rect);
 	_cairo_gl_composite_draw_triangles (ctx, count);
     }
 }
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index b2375e1..4d7ab62 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -533,10 +533,15 @@ _stroke_shaper_add_quad (void			*closure,
 }
 
 static cairo_int_status_t
-_prevent_overlapping_drawing (cairo_gl_context_t *ctx,
-			      cairo_gl_composite_t *setup,
-			      cairo_composite_rectangles_t *composite)
+_prevent_overlapping_strokes (cairo_gl_context_t 		*ctx,
+			      cairo_gl_composite_t 		*setup,
+			      cairo_composite_rectangles_t 	*composite,
+			      const cairo_path_fixed_t		*path,
+			      const cairo_stroke_style_t	*style,
+			      const cairo_matrix_t		*ctm)
 {
+    cairo_rectangle_int_t stroke_extents;
+
     if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -545,13 +550,33 @@ _prevent_overlapping_drawing (cairo_gl_context_t *ctx,
 	return CAIRO_INT_STATUS_SUCCESS;
 
    if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
+	cairo_bool_t scissor_was_enabled;
+
+       /* In case we have pending operations we have to flush before
+	  adding the stencil buffer. */
+       _cairo_gl_composite_flush (ctx);
+
 	/* Enable the stencil buffer, even if we are not using it for clipping,
 	   so we can use it below to prevent overlapping shapes. We initialize
 	   it all to one here which represents infinite clip. */
 	glDepthMask (GL_TRUE);
 	glEnable (GL_STENCIL_TEST);
+
+	/* We scissor here so that we don't have to clear the entire stencil
+	 * buffer. If the scissor test is already enabled, it was enabled
+	 * for clipping. In that case, instead of calculating an intersection,
+	 * we just reuse it, and risk clearing too much. */
+	scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
+	if (! scissor_was_enabled) {
+	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
+							  &stroke_extents);
+	    _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
+	}
 	glClearStencil (1);
 	glClear (GL_STENCIL_BUFFER_BIT);
+	if (! scissor_was_enabled)
+	    glDisable (GL_SCISSOR_TEST);
+
 	glStencilFunc (GL_EQUAL, 1, 1);
     }
 
@@ -655,7 +680,8 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
     if (unlikely (status))
 	goto finish;
 
-    status = _prevent_overlapping_drawing (info.ctx, &info.setup, composite);
+    status = _prevent_overlapping_strokes (info.ctx, &info.setup,
+					   composite, path, style, ctm);
     if (unlikely (status))
 	goto finish;
 
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 5aab17c..1da5084 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -799,6 +799,10 @@ _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
 cairo_private cairo_surface_t *
 _cairo_gl_white_source (void);
 
+cairo_private void
+_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
+				const cairo_rectangle_int_t *r);
+
 static inline cairo_gl_operand_t *
 source_to_operand (cairo_surface_t *surface)
 {
commit 5e9083f882859201c5df18fc870577a224f88cbb
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-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);
commit dd850583a7f57a666da6af218841bb10b536df46
Author: Henry Song <henry.song at samsung.com>
Date:   Tue Mar 13 08:43:24 2012 -0700

    gl/msaa: Add full support for masking with the SOURCE operator
    
    Since OpenGL does not have a means to represent a masking SOURCE
    operation in one step, we use two steps combined with the ADD
    operator.

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 39dec54..4ebe966 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -629,24 +629,13 @@ _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup,
 }
 
 cairo_status_t
-_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
-			   cairo_gl_context_t **ctx_out)
+_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
+				     cairo_gl_context_t *ctx)
 {
     unsigned int dst_size, src_size, mask_size, vertex_size;
-    cairo_gl_context_t *ctx;
     cairo_status_t status;
-    cairo_bool_t component_alpha;
     cairo_gl_shader_t *shader;
-
-    assert (setup->dst);
-
-    status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx);
-    if (unlikely (status))
-	return status;
-
-    _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample);
-
-    glEnable (GL_BLEND);
+    cairo_bool_t component_alpha;
 
     component_alpha =
 	setup->mask.type == CAIRO_GL_OPERAND_TEXTURE &&
@@ -654,40 +643,40 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
 
     /* Do various magic for component alpha */
     if (component_alpha) {
-        status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
-        if (unlikely (status))
-            goto FAIL;
-    } else {
-        if (ctx->pre_shader) {
-            _cairo_gl_composite_flush (ctx);
-            ctx->pre_shader = NULL;
-        }
+	status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
+	if (unlikely (status))
+	    return status;
+     } else {
+	if (ctx->pre_shader) {
+	    _cairo_gl_composite_flush (ctx);
+	    ctx->pre_shader = NULL;
+	}
     }
 
     status = _cairo_gl_get_shader_by_type (ctx,
 					   &setup->src,
 					   &setup->mask,
 					   setup->spans,
-                                           component_alpha ?
+					   component_alpha ?
 					   CAIRO_GL_SHADER_IN_CA_SOURCE :
 					   CAIRO_GL_SHADER_IN_NORMAL,
                                            &shader);
     if (unlikely (status)) {
-        ctx->pre_shader = NULL;
-        goto FAIL;
+	ctx->pre_shader = NULL;
+	return status;
     }
     if (ctx->current_shader != shader)
         _cairo_gl_composite_flush (ctx);
 
     status = CAIRO_STATUS_SUCCESS;
 
-    dst_size  = 2 * sizeof (GLfloat);
-    src_size  = _cairo_gl_operand_get_vertex_size (setup->src.type);
+    dst_size = 2 * sizeof (GLfloat);
+    src_size = _cairo_gl_operand_get_vertex_size (setup->src.type);
     mask_size = _cairo_gl_operand_get_vertex_size (setup->mask.type);
     vertex_size = dst_size + src_size + mask_size;
 
     if (setup->spans)
-	    vertex_size += sizeof (GLfloat);
+	vertex_size += sizeof (GLfloat);
 
     _cairo_gl_composite_setup_vbo (ctx, vertex_size);
 
@@ -700,15 +689,35 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
     _cairo_gl_set_operator (ctx, setup->op, component_alpha);
 
     if (_cairo_gl_context_is_flushed (ctx)) {
-        if (ctx->pre_shader) {
-            _cairo_gl_set_shader (ctx, ctx->pre_shader);
-            _cairo_gl_composite_bind_to_shader (ctx, setup);
-        }
-        _cairo_gl_set_shader (ctx, shader);
-        _cairo_gl_composite_bind_to_shader (ctx, setup);
+	if (ctx->pre_shader) {
+	    _cairo_gl_set_shader (ctx, ctx->pre_shader);
+	    _cairo_gl_composite_bind_to_shader (ctx, setup);
+	}
+	_cairo_gl_set_shader (ctx, shader);
+	_cairo_gl_composite_bind_to_shader (ctx, setup);
     }
 
-    status = _cairo_gl_composite_setup_clipping (setup, ctx, vertex_size);
+    return status;
+}
+
+cairo_status_t
+_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
+			   cairo_gl_context_t **ctx_out)
+{
+    cairo_gl_context_t *ctx;
+    cairo_status_t status;
+
+    assert (setup->dst);
+
+    status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx);
+    if (unlikely (status))
+	return status;
+
+    _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample);
+    glEnable (GL_BLEND);
+    _cairo_gl_set_operands_and_operator (setup, ctx);
+
+    status = _cairo_gl_composite_setup_clipping (setup, ctx, ctx->vertex_size);
     if (unlikely (status))
 	goto FAIL;
 
@@ -1072,13 +1081,10 @@ _cairo_gl_composite_fini (cairo_gl_composite_t *setup)
 }
 
 cairo_status_t
-_cairo_gl_composite_init (cairo_gl_composite_t *setup,
-                          cairo_operator_t op,
-                          cairo_gl_surface_t *dst,
-                          cairo_bool_t assume_component_alpha)
+_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
+				  cairo_operator_t op,
+				  cairo_bool_t assume_component_alpha)
 {
-    memset (setup, 0, sizeof (cairo_gl_composite_t));
-
     if (assume_component_alpha) {
         if (op != CAIRO_OPERATOR_CLEAR &&
             op != CAIRO_OPERATOR_OVER &&
@@ -1089,8 +1095,26 @@ _cairo_gl_composite_init (cairo_gl_composite_t *setup,
             return UNSUPPORTED ("unsupported operator");
     }
 
-    setup->dst = dst;
     setup->op = op;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_gl_composite_init (cairo_gl_composite_t *setup,
+                          cairo_operator_t op,
+                          cairo_gl_surface_t *dst,
+                          cairo_bool_t assume_component_alpha)
+{
+    cairo_status_t status;
+
+    memset (setup, 0, sizeof (cairo_gl_composite_t));
+
+    status = _cairo_gl_composite_set_operator (setup, op,
+					       assume_component_alpha);
+    if (status)
+	return status;
+
+    setup->dst = dst;
     setup->clip_region = dst->clip_region;
 
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 12c416f..5de3449 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -286,6 +286,74 @@ _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
     _cairo_gl_composite_set_clip (setup, composite->clip);
 }
 
+/* Masking with the SOURCE operator requires two passes. In the first
+ * pass we use the mask as the source to get:
+ * result = (1 - ma) * dst
+ * In the second pass we use the add operator to achieve:
+ * result = (src * ma) + dst
+ * Combined this produces:
+ * result = (src * ma) + (1 - ma) * dst
+ */
+static cairo_int_status_t
+_cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
+						cairo_composite_rectangles_t *composite)
+{
+    cairo_gl_composite_t setup;
+    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
+    cairo_gl_context_t *ctx = NULL;
+    cairo_int_status_t status;
+
+    status = _cairo_gl_composite_init (&setup,
+				       CAIRO_OPERATOR_DEST_OUT,
+				       dst,
+				       FALSE /* assume_component_alpha */);
+    if (unlikely (status))
+	return status;
+    status = _cairo_gl_composite_set_source (&setup,
+					     &composite->mask_pattern.base,
+					     &composite->mask_sample_area,
+					     &composite->bounded);
+    if (unlikely (status))
+	goto finish;
+    _cairo_gl_composite_set_clip (&setup, composite->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);
+
+    /* Now draw the second pass. */
+    _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
+				      FALSE /* assume_component_alpha */);
+    if (unlikely (status))
+        goto finish;
+    status = _cairo_gl_composite_set_source (&setup,
+					     &composite->source_pattern.base,
+					     &composite->source_sample_area,
+					     &composite->bounded);
+    if (unlikely (status))
+	goto finish;
+    status = _cairo_gl_composite_set_mask (&setup,
+				           &composite->mask_pattern.base,
+					   &composite->source_sample_area,
+					   &composite->bounded);
+    if (unlikely (status))
+	goto finish;
+    status = _cairo_gl_set_operands_and_operator (&setup, ctx);
+    if (unlikely (status))
+	goto finish;
+
+    _draw_int_rect (ctx, &setup, &composite->bounded);
+
+finish:
+    _cairo_gl_composite_fini (&setup);
+    if (ctx)
+	status = _cairo_gl_context_release (ctx, status);
+
+    return status;
+}
+
 static cairo_int_status_t
 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
 				cairo_composite_rectangles_t	*composite)
@@ -308,12 +376,13 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
 	! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
 				    &composite->mask_sample_area)) {
 
-       /* If the source is opaque the operation reduces to OVER. */
-	if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
-				      &composite->source_sample_area))
-	    op = CAIRO_OPERATOR_OVER;
-	else
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
+				      &composite->source_sample_area)) {
+	    return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
+	}
+
+	/* If the source is opaque the operation reduces to OVER. */
+	op = CAIRO_OPERATOR_OVER;
     }
 
     if (_should_use_unbounded_surface (composite)) {
@@ -713,7 +782,8 @@ _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t	*compositor,
     info.font = scaled_font;
     info.glyphs = glyphs;
     info.num_glyphs = num_glyphs;
-    info.use_mask = overlap || ! composite->is_bounded;
+    info.use_mask = overlap || ! composite->is_bounded ||
+		    composite->op == CAIRO_OPERATOR_SOURCE;
     info.extents = composite->bounded;
 
     _cairo_scaled_font_freeze_cache (scaled_font);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 258fa78..5aab17c 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -526,6 +526,11 @@ _cairo_gl_composite_init (cairo_gl_composite_t *setup,
 cairo_private void
 _cairo_gl_composite_fini (cairo_gl_composite_t *setup);
 
+cairo_status_t
+_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
+				  cairo_operator_t op,
+				  cairo_bool_t assume_component_alpha);
+
 cairo_private void
 _cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
                                      cairo_region_t *clip_region);
@@ -568,6 +573,10 @@ cairo_private cairo_status_t
 _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
                            cairo_gl_context_t **ctx);
 
+cairo_status_t
+_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
+				     cairo_gl_context_t *ctx);
+
 cairo_private void
 _cairo_gl_composite_flush (cairo_gl_context_t *ctx);
 


More information about the cairo-commit mailing list