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.
This commit is contained in:
Henry (Yu) Song 2011-10-14 14:32:28 -07:00 committed by Martin Robinson
parent 929a96ed03
commit b099f8b0c7
2 changed files with 122 additions and 23 deletions

View file

@ -576,6 +576,19 @@ _cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx)
{
cairo_array_t* indices = &ctx->tristrip_indices;
const int *indices_array = _cairo_array_index_const (indices, 0);
if (ctx->pre_shader) {
cairo_gl_shader_t *prev_shader = ctx->current_shader;
_cairo_gl_set_shader (ctx, ctx->pre_shader);
_cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_INT, indices_array);
_cairo_gl_set_shader (ctx, prev_shader);
_cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
}
glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_INT, indices_array);
_cairo_array_truncate (indices, 0);
}
@ -696,6 +709,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,
@ -789,21 +813,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)
@ -854,14 +863,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);
}
@ -877,8 +886,8 @@ _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);
}

View file

@ -47,6 +47,10 @@
#include "cairo-gl-private.h"
#include "cairo-traps-private.h"
static void
_scissor_to_rectangle (cairo_gl_surface_t *surface,
const cairo_rectangle_int_t *rect);
struct _tristrip_composite_info {
cairo_gl_composite_t setup;
cairo_gl_context_t *ctx;
@ -98,6 +102,27 @@ _draw_traps (cairo_gl_context_t *ctx,
return status;
}
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,
@ -264,7 +289,72 @@ 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_bool_t used_stencil_buffer;
cairo_int_status_t status;
cairo_operator_t op = composite->op;
/* GL compositing operators cannot properly represent a mask operation
using the SOURCE compositing operator in one pass. This only matters if
there actually is a mask (there isn't in a paint operation) and if the
mask isn't totally opaque. */
if (op == CAIRO_OPERATOR_SOURCE &&
composite->original_mask_pattern != NULL &&
! _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;
}
status = _cairo_gl_composite_init (&setup,
op,
dst,
FALSE /* assume_component_alpha */);
if (unlikely (status))
return status;
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_composite_begin (&setup, &ctx);
if (unlikely (status))
goto finish;
status = _scissor_and_clip (ctx, &setup, composite, &used_stencil_buffer);
if (unlikely (status))
goto finish;
_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