Esempio n. 1
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
				cairo_composite_rectangles_t	*composite,
				const cairo_path_fixed_t	*path,
				cairo_fill_rule_t		 fill_rule,
				double				 tolerance,
				cairo_antialias_t		 antialias)
{
    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 = CAIRO_INT_STATUS_SUCCESS;
    cairo_traps_t traps;
    cairo_bool_t use_color_attr = FALSE;

    if (! can_use_msaa_compositor (dst, antialias))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;


	status = _cairo_compositor_fill (compositor, surface,
					 CAIRO_OPERATOR_SOURCE,
					 &composite->source_pattern.base,
					 path, fill_rule, tolerance,
					 antialias, NULL);

	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    if (_cairo_path_fixed_fill_is_rectilinear (path) &&
	composite->clip != NULL &&
	composite->clip->num_boxes == 1 &&
	composite->clip->path == NULL) {
	cairo_clip_t *clip = _cairo_clip_copy (composite->clip);
	clip = _cairo_clip_intersect_rectilinear_path (clip,
						       path,
						       fill_rule,
						       antialias);
	if (clip->num_boxes)
		status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor,
								     composite,
								     path,
								     fill_rule,
								     tolerance,
								     antialias,
								     clip);
	_cairo_clip_destroy (clip);

	return status;
    }

    status = _cairo_gl_composite_init (&setup,
				       composite->op,
				       dst,
				       FALSE /* assume_component_alpha */);
    if (unlikely (status)) {
        _cairo_gl_composite_fini (&setup);
	return status;
    }

    _cairo_traps_init (&traps);

    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
	status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
							      fill_rule,
							      antialias,
							      &traps);
	use_color_attr = TRUE;
    } else
	status = _cairo_path_fixed_fill_to_traps (path, fill_rule,
						  tolerance, &traps);
    if (unlikely (status))
	goto cleanup_traps;

    status = _cairo_gl_composite_set_source (&setup,
					     composite->original_source_pattern,
					     &composite->source_sample_area,
					     &composite->bounded,
					     use_color_attr);
    if (unlikely (status))
	goto cleanup_setup;

    _cairo_gl_msaa_compositor_set_clip (composite, &setup);

    status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
	antialias != CAIRO_ANTIALIAS_NONE);
    if (unlikely (status))
	goto cleanup_setup;

    status = _draw_traps (ctx, &setup, &traps);
    if (unlikely (status))
        goto cleanup_setup;

cleanup_setup:
    _cairo_gl_composite_fini (&setup);

    if (ctx)
	status = _cairo_gl_context_release (ctx, status);

cleanup_traps:
    _cairo_traps_fini (&traps);

    return status;
}
Esempio n. 2
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
				  cairo_composite_rectangles_t	*composite,
				  const cairo_path_fixed_t	*path,
				  const cairo_stroke_style_t	*style,
				  const cairo_matrix_t		*ctm,
				  const cairo_matrix_t		*ctm_inverse,
				  double			 tolerance,
				  cairo_antialias_t		 antialias)
{
    cairo_int_status_t status;
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
    struct _tristrip_composite_info info;
    cairo_bool_t use_color_attribute;

    if (! can_use_msaa_compositor (dst, antialias))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	status = _cairo_compositor_stroke (compositor, surface,
					   CAIRO_OPERATOR_SOURCE,
					   &composite->source_pattern.base,
					   path, style, ctm, ctm_inverse,
					   tolerance, antialias, NULL);
	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    status = _cairo_gl_composite_init (&info.setup,
				       composite->op,
				       dst,
				       FALSE /* assume_component_alpha */);
    if (unlikely (status))
	return status;

    info.ctx = NULL;
    use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
			  _cairo_gl_hairline_style_is_hairline (style, ctm);

    status = _cairo_gl_composite_set_source (&info.setup,
					     composite->original_source_pattern,
					     &composite->source_sample_area,
					     &composite->bounded,
					     use_color_attribute);
    if (unlikely (status))
	goto finish;

    _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);

    status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx,
	antialias != CAIRO_ANTIALIAS_NONE);
    if (unlikely (status))
	goto finish;

    if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
	cairo_gl_hairline_closure_t closure;

	if (! (_is_continuous_arc (path, style) ||
	       _is_continuous_single_line (path, style))) {
	    status = _prevent_overlapping_drawing (info.ctx, &info.setup,
					           composite, path,
						   style, ctm);
	    if (unlikely (status))
		goto finish;
	}

	closure.ctx = info.ctx;

	closure.tolerance = tolerance;

	status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
							  style, ctm,
							  ctm_inverse,
							  _cairo_gl_hairline_move_to,
							  style->dash ?
							  _cairo_gl_hairline_line_to_dashed :
							  _cairo_gl_hairline_line_to,
							  _cairo_gl_hairline_curve_to,
							  _cairo_gl_hairline_close_path);
	goto finish;
    }

    if (use_color_attribute) {
	cairo_traps_t traps;

	_cairo_traps_init (&traps);

	status = _cairo_path_fixed_stroke_to_traps (path, style,
						    ctm, ctm_inverse,
						    tolerance, &traps);
	if (unlikely (status)) {
	    _cairo_traps_fini (&traps);
	    goto finish;
	}

	status = _draw_traps (info.ctx, &info.setup, &traps);
	_cairo_traps_fini (&traps);
    } else {
	if (!_is_continuous_single_line (path, style)) {
	    status = _prevent_overlapping_drawing (info.ctx, &info.setup,
						   composite, path,
						   style, ctm);
	    if (unlikely (status))
		goto finish;
	}

	status =
	    _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
						style,
						ctm,
						ctm_inverse,
						tolerance,
						_stroke_shaper_add_triangle,
						_stroke_shaper_add_triangle_fan,
						_stroke_shaper_add_quad,
						&info);
	if (unlikely (status))
	    goto finish;
    }
finish:
    _cairo_gl_composite_fini (&info.setup);

    if (info.ctx)
	status = _cairo_gl_context_release (info.ctx, status);

    return status;
}
Esempio n. 3
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_mask (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;
    cairo_operator_t op = composite->op;
    cairo_traps_t traps;
    cairo_bool_t use_color_attribute = FALSE;

    if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    /* 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_gl_msaa_compositor_mask_source_operator (compositor, composite);
    }

    if (_should_use_unbounded_surface (composite)) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	/* This may be a paint operation. */
	if (composite->original_mask_pattern == NULL) {
	    status = _cairo_compositor_paint (compositor, surface,
					      CAIRO_OPERATOR_SOURCE,
					      &composite->source_pattern.base,
					      NULL);
	} else {
	    status = _cairo_compositor_mask (compositor, surface,
					     CAIRO_OPERATOR_SOURCE,
					     &composite->source_pattern.base,
					     &composite->mask_pattern.base,
					     NULL);
	}

	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    status = _cairo_gl_composite_init (&setup,
				       op,
				       dst,
				       FALSE /* assume_component_alpha */);
    if (unlikely (status))
	goto finish;

    _gl_pattern_fix_reference_count (composite->original_source_pattern);

    if (! composite->clip ||
	(composite->clip->num_boxes == 1 && ! composite->clip->path))
	use_color_attribute = TRUE;

    status = _cairo_gl_composite_set_source (&setup,
					     composite->original_source_pattern,
					     &composite->source_sample_area,
					     &composite->bounded,
					     use_color_attribute);
    if (unlikely (status))
	goto finish;

    if (composite->original_mask_pattern != NULL) {
	status = _cairo_gl_composite_set_mask (&setup,
					       composite->original_mask_pattern,
					       &composite->mask_sample_area,
					       &composite->bounded);
    }
    if (unlikely (status))
	goto finish;

    /* We always use multisampling here, because we do not yet have the smarts
       to calculate when the clip or the source requires it. */
    status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
    if (unlikely (status))
	goto finish;

    _cairo_traps_init (&traps);

    if (! composite->clip)
	status = _draw_int_rect (ctx, &setup, &composite->bounded);
    else
	status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);

    _cairo_traps_fini (&traps);

finish:
    _cairo_gl_composite_fini (&setup);

    if (ctx)
	status = _cairo_gl_context_release (ctx, status);

    return status;
}
Esempio n. 4
0
static cairo_int_status_t
_cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t	*compositor,
				  cairo_composite_rectangles_t	*composite,
				  cairo_scaled_font_t		*scaled_font,
				  cairo_glyph_t			*glyphs,
				  int				 num_glyphs,
				  cairo_bool_t			 overlap)
{
    cairo_int_status_t status;
    cairo_surface_t *src = NULL;
    int src_x, src_y;
    cairo_composite_glyphs_info_t info;

    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;

    query_surface_capabilities (dst);
    if (! dst->supports_stencil)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);

	if (unlikely (surface == NULL))
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	status = _cairo_compositor_glyphs (compositor, surface,
					   CAIRO_OPERATOR_SOURCE,
					   &composite->source_pattern.base,
					   glyphs, num_glyphs,
					   scaled_font, composite->clip);

	if (unlikely (status)) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    src = _cairo_gl_pattern_to_source (&dst->base,
				       composite->original_source_pattern,
				       FALSE,
				       &composite->bounded,
				       &composite->source_sample_area,
				       &src_x, &src_y);
    if (unlikely (src->status)) {
	status = src->status;
	goto finish;
    }

    status = _cairo_gl_check_composite_glyphs (composite,
					       scaled_font, glyphs,
					       &num_glyphs);
    if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
	goto finish;

    info.font = scaled_font;
    info.glyphs = glyphs;
    info.num_glyphs = num_glyphs;
    info.use_mask = overlap || ! composite->is_bounded ||
		    composite->op == CAIRO_OPERATOR_SOURCE;
    info.extents = composite->bounded;

    _cairo_scaled_font_freeze_cache (scaled_font);
    status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
						   src, src_x, src_y,
						   0, 0, &info,
						   composite->clip,
						   TRUE);

    _cairo_scaled_font_thaw_cache (scaled_font);

finish:
    if (src)
	cairo_surface_destroy (src);

    return status;
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
                                cairo_composite_rectangles_t	*composite,
                                const cairo_path_fixed_t	*path,
                                cairo_fill_rule_t		 fill_rule,
                                double				 tolerance,
                                cairo_antialias_t		 antialias)
{
    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;
    cairo_traps_t traps;
    cairo_bool_t draw_path_with_traps;

    if (! can_use_msaa_compositor (dst, antialias))
        return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
        cairo_surface_t* surface = _prepare_unbounded_surface (dst);

        if (unlikely (surface == NULL))
            return CAIRO_INT_STATUS_UNSUPPORTED;


        status = _cairo_compositor_fill (compositor, surface,
                                         CAIRO_OPERATOR_SOURCE,
                                         &composite->source_pattern.base,
                                         path, fill_rule, tolerance,
                                         antialias, NULL);

        if (unlikely (status)) {
            cairo_surface_destroy (surface);
            return status;
        }

        return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);

    if (draw_path_with_traps) {
        _cairo_traps_init (&traps);
        status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
        if (unlikely (status))
            goto cleanup_traps;
    }

    status = _cairo_gl_composite_init (&setup,
                                       composite->op,
                                       dst,
                                       FALSE /* assume_component_alpha */);
    if (unlikely (status))
        goto cleanup_traps;

    status = _cairo_gl_composite_set_source (&setup,
             &composite->source_pattern.base,
             &composite->source_sample_area,
             &composite->bounded,
             FALSE);
    if (unlikely (status))
        goto cleanup_setup;

    _cairo_gl_msaa_compositor_set_clip (composite, &setup);
    if (antialias != CAIRO_ANTIALIAS_NONE)
        _cairo_gl_composite_set_multisample (&setup);

    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
        goto cleanup_setup;

    if (! draw_path_with_traps)
        status = _draw_simple_quad_path (ctx, &setup, path);
    else
        status = _draw_traps (ctx, &setup, &traps);
    if (unlikely (status))
        goto cleanup_setup;

cleanup_setup:
    _cairo_gl_composite_fini (&setup);

    if (ctx)
        status = _cairo_gl_context_release (ctx, status);

cleanup_traps:
    if (draw_path_with_traps)
        _cairo_traps_fini (&traps);

    return status;
}
static cairo_int_status_t
_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
                                  cairo_composite_rectangles_t	*composite,
                                  const cairo_path_fixed_t	*path,
                                  const cairo_stroke_style_t	*style,
                                  const cairo_matrix_t		*ctm,
                                  const cairo_matrix_t		*ctm_inverse,
                                  double			 tolerance,
                                  cairo_antialias_t		 antialias)
{
    cairo_int_status_t status;
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
    struct _tristrip_composite_info info;

    if (! can_use_msaa_compositor (dst, antialias))
        return CAIRO_INT_STATUS_UNSUPPORTED;

    if (composite->is_bounded == FALSE) {
        cairo_surface_t* surface = _prepare_unbounded_surface (dst);

        if (unlikely (surface == NULL))
            return CAIRO_INT_STATUS_UNSUPPORTED;

        status = _cairo_compositor_stroke (compositor, surface,
                                           CAIRO_OPERATOR_SOURCE,
                                           &composite->source_pattern.base,
                                           path, style, ctm, ctm_inverse,
                                           tolerance, antialias, NULL);
        if (unlikely (status)) {
            cairo_surface_destroy (surface);
            return status;
        }

        return _paint_back_unbounded_surface (compositor, composite, surface);
    }

    status = _cairo_gl_composite_init (&info.setup,
                                       composite->op,
                                       dst,
                                       FALSE /* assume_component_alpha */);
    if (unlikely (status))
        return status;

    info.ctx = NULL;

    status = _cairo_gl_composite_set_source (&info.setup,
             &composite->source_pattern.base,
             &composite->source_sample_area,
             &composite->bounded,
             FALSE);
    if (unlikely (status))
        goto finish;

    _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
    if (antialias != CAIRO_ANTIALIAS_NONE)
        _cairo_gl_composite_set_multisample (&info.setup);

    status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
    if (unlikely (status))
        goto finish;

    status = _prevent_overlapping_strokes (info.ctx, &info.setup,
                                           composite, path, style, ctm);
    if (unlikely (status))
        goto finish;

    status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
             style,
             ctm,
             ctm_inverse,
             tolerance,
             _stroke_shaper_add_triangle,
             _stroke_shaper_add_triangle_fan,
             _stroke_shaper_add_quad,
             &info);
    if (unlikely (status))
        goto finish;

finish:
    _cairo_gl_composite_fini (&info.setup);

    if (info.ctx)
        status = _cairo_gl_context_release (info.ctx, status);

    return status;
}