mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 14:38:13 +02:00
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:
parent
929a96ed03
commit
b099f8b0c7
2 changed files with 122 additions and 23 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue