From 1e72a3552e52c6e448006ec27d628bf3846cfa19 Mon Sep 17 00:00:00 2001
From: Henry (Yu) Song <hsong@sisa.samsung.com>
Date: Fri, 14 Oct 2011 14:32:28 -0700
Subject: [PATCH 3/3] gl/msaa: Support for masking

Add support for masking in the OpenGL MSAA compositor. This is
accomplished simply by properly setting up the masking source,
emitting the entire bounded composite region, and unforking
vertex emission.
---
 src/cairo-gl-composite.c       |   40 +++++++++-----------
 src/cairo-gl-msaa-compositor.c |   79 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 96 insertions(+), 23 deletions(-)

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index d3a7588..38e2f3d 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -694,6 +694,17 @@ _cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
     ctx->vb_offset += ctx->vertex_size;
 }
 
+static void
+_cairo_gl_composite_emit_point (cairo_gl_context_t	*ctx,
+				const cairo_point_t	*point,
+				uint8_t alpha)
+{
+    _cairo_gl_composite_emit_vertex (ctx,
+				     _cairo_fixed_to_double (point->x),
+				     _cairo_fixed_to_double (point->y),
+				     alpha);
+}
+
 void
 _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
                                GLfloat x1,
@@ -787,21 +798,6 @@ _cairo_gl_composite_init (cairo_gl_composite_t *setup,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cairo_gl_composite_emit_tristrip_vertex (cairo_gl_context_t	*ctx,
-					  const cairo_point_t	*point)
-{
-    GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
-    GLfloat x = _cairo_fixed_to_double (point->x);
-    GLfloat y = _cairo_fixed_to_double (point->y);
-
-    *vb++ = x;
-    *vb++ = y;
-    _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
-
-    ctx->vb_offset += ctx->vertex_size;
-}
-
 static cairo_int_status_t
 _cairo_gl_composite_append_vertex_indices (cairo_gl_context_t	*ctx,
 					   int			 number_of_new_indices)
@@ -848,14 +844,14 @@ _cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t	*ctx,
 {
     _cairo_gl_composite_prepare_buffer (ctx, 4);
 
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[0]);
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[1]);
+    _cairo_gl_composite_emit_point (ctx, &quad[0], 0);
+    _cairo_gl_composite_emit_point (ctx, &quad[1], 0);
 
     /* Cairo stores quad vertices in counter-clockwise order, but we need to
        emit them from top to bottom in the triangle strip, so we need to reverse
        the order of the last two vertices. */
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[3]);
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[2]);
+    _cairo_gl_composite_emit_point (ctx, &quad[3], 0);
+    _cairo_gl_composite_emit_point (ctx, &quad[2], 0);
 
     return _cairo_gl_composite_append_vertex_indices (ctx, 4);
 }
@@ -867,9 +863,9 @@ _cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t	*ctx,
 {
     _cairo_gl_composite_prepare_buffer (ctx, 3);
 
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &triangle[0]);
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &triangle[1]);
-    _cairo_gl_composite_emit_tristrip_vertex (ctx, &triangle[2]);
+    _cairo_gl_composite_emit_point (ctx, &triangle[0], 0);
+    _cairo_gl_composite_emit_point (ctx, &triangle[1], 0);
+    _cairo_gl_composite_emit_point (ctx, &triangle[2], 0);
     return _cairo_gl_composite_append_vertex_indices (ctx, 3);
 }
 
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 01ef40f..fa94d28 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -47,6 +47,10 @@
 #include "cairo-gl-private.h"
 #include "cairo-traps-private.h"
 
+static void
+_scissor_composite_extents (cairo_gl_surface_t		*surface,
+			    cairo_rectangle_int_t	*rect);
+
 struct _tristrip_composite_info {
     cairo_gl_composite_t	setup;
     cairo_gl_context_t		*ctx;
@@ -99,6 +103,27 @@ _draw_traps (cairo_gl_context_t		*ctx,
 }
 
 static cairo_int_status_t
+_draw_int_rect (cairo_gl_context_t	*ctx,
+		cairo_gl_composite_t	*setup,
+		cairo_rectangle_int_t	*rect)
+{
+    cairo_box_t box;
+    cairo_point_t quad[4];
+
+    _cairo_box_from_rectangle (&box, rect);
+    quad[0].x = box.p1.x;
+    quad[0].y = box.p1.y;
+    quad[1].x = box.p1.x;
+    quad[1].y = box.p2.y;
+    quad[2].x = box.p2.x;
+    quad[2].y = box.p2.y;
+    quad[3].x = box.p2.x;
+    quad[3].y = box.p1.y;
+
+    return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
+}
+
+static cairo_int_status_t
 _draw_triangle_fan (cairo_gl_context_t		*ctx,
 		    cairo_gl_composite_t	*setup,
 		    const cairo_point_t		*midpt,
@@ -214,7 +239,59 @@ static cairo_int_status_t
 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
 				cairo_composite_rectangles_t	*composite)
 {
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    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,
+				       composite->op,
+				       dst,
+				       FALSE, /* assume_component_alpha */
+				       &composite->bounded);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_gl_composite_set_source (&setup,
+					     &composite->source_pattern.base,
+					     composite->bounded.x,
+					     composite->bounded.y,
+					     composite->bounded.x,
+					     composite->bounded.y,
+					     composite->bounded.width,
+					     composite->bounded.height);
+    if (unlikely (status))
+	goto finish;
+
+    status = _cairo_gl_composite_set_mask (&setup,
+					   &composite->mask_pattern.base,
+					   composite->bounded.x,
+					   composite->bounded.y,
+					   composite->bounded.x,
+					   composite->bounded.y,
+					   composite->bounded.width,
+					   composite->bounded.height);
+    if (unlikely (status))
+	goto finish;
+
+    status = _cairo_gl_composite_begin_tristrip (&setup, &ctx);
+    if (unlikely (status))
+	goto finish;
+
+    _scissor_composite_extents (dst, &composite->unbounded);
+    _draw_int_rect (ctx, &setup, &composite->bounded);
+    _cairo_gl_composite_flush (ctx);
+
+finish:
+    _cairo_gl_composite_fini (&setup);
+
+    if (ctx) {
+	glDisable (GL_SCISSOR_TEST);
+	_disable_stencil_buffer ();
+	status = _cairo_gl_context_release (ctx, status);
+    }
+
+    return status;
 }
 
 static cairo_status_t
-- 
1.7.4.1

