mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-22 05:50:41 +02:00
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.
This commit is contained in:
parent
c743e93451
commit
dd850583a7
3 changed files with 152 additions and 49 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue