コード例 #1
0
cairo_int_status_t
_cairo_gl_surface_fill_rectangles (void			   *abstract_dst,
				   cairo_operator_t	    op,
				   const cairo_color_t     *color,
				   cairo_rectangle_int_t   *rects,
				   int			    num_rects)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_solid_pattern_t solid;
    cairo_gl_context_t *ctx;
    cairo_status_t status;
    cairo_gl_composite_t setup;
    int i;

    status = _cairo_gl_surface_deferred_clear (dst);
    if (unlikely (status))
	    return status;

    status = _cairo_gl_composite_init (&setup, op, dst,
                                       FALSE,
                                       /* XXX */ NULL);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_pattern_init_solid (&solid, color);
    status = _cairo_gl_composite_set_source (&setup, &solid.base,
                                             0, 0,
                                             0, 0,
                                             0, 0,
                                             FALSE);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_mask (&setup, NULL,
                                           0, 0,
                                           0, 0,
                                           0, 0);
    if (unlikely (status))
        goto CLEANUP;

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

    for (i = 0; i < num_rects; i++) {
        _cairo_gl_composite_emit_rect (ctx,
                                       rects[i].x,
                                       rects[i].y,
                                       rects[i].x + rects[i].width,
                                       rects[i].y + rects[i].height,
                                       0);
    }

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    return status;
}
コード例 #2
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;
}
コード例 #3
0
/* The first pass, we use mask as source, to get dst1 = (1 - ma) * dst) with
 * DEST_OUT operator.  In the second pass, we use ADD operator to achieve
 * result = (src * ma) + dst1.  Combining two passes, we have
 * 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;
    cairo_traps_t traps;

    _cairo_traps_init (&traps);

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

    _gl_pattern_fix_reference_count (composite->original_mask_pattern);

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

    status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
    if (unlikely (status))
	goto finish;

    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_gl_composite_fini (&setup);
    status = _cairo_gl_context_release (ctx, status);
    ctx = NULL;
    if (unlikely (status))
        return status;

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

    _gl_pattern_fix_reference_count (composite->original_source_pattern);

    status = _cairo_gl_composite_set_source (&setup,
					     &composite->source_pattern.base,
					     &composite->source_sample_area,
					     &composite->bounded,
					     FALSE);
    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;

    /* 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;

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

finish:
    _cairo_traps_fini (&traps);
    _cairo_gl_composite_fini (&setup);

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

    return status;
}
コード例 #4
0
cairo_int_status_t
_cairo_gl_surface_composite (cairo_operator_t		  op,
			     const cairo_pattern_t	 *src,
			     const cairo_pattern_t	 *mask,
			     void			 *abstract_dst,
			     int			  src_x,
			     int			  src_y,
			     int			  mask_x,
			     int			  mask_y,
			     int			  dst_x,
			     int			  dst_y,
			     unsigned int		  width,
			     unsigned int		  height,
			     cairo_region_t		 *clip_region)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_gl_context_t *ctx;
    cairo_status_t status;
    cairo_gl_composite_t setup;
    cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
    int dx, dy;

    status = _cairo_gl_surface_deferred_clear (dst);
    if (unlikely (status))
	    return status;

    if (op == CAIRO_OPERATOR_SOURCE &&
        mask == NULL &&
        src->type == CAIRO_PATTERN_TYPE_SURFACE &&
        _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) &&
        _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) {
        cairo_image_surface_t *image = (cairo_image_surface_t *)
            ((cairo_surface_pattern_t *) src)->surface;
        dx += src_x;
        dy += src_y;
        if (dx >= 0 &&
            dy >= 0 &&
            dx + width <= (unsigned int) image->width &&
            dy + height <= (unsigned int) image->height) {
            status = _cairo_gl_surface_draw_image (dst, image,
                                                   dx, dy,
                                                   width, height,
                                                   dst_x, dst_y);
            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
                return status;
        }
    }

    status = _cairo_gl_composite_init (&setup, op, dst,
                                       mask && mask->has_component_alpha,
                                       &rect);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_source (&setup, src,
                                             src_x, src_y,
                                             dst_x, dst_y,
                                             width, height);
    if (unlikely (status))
        goto CLEANUP;

    status = _cairo_gl_composite_set_mask (&setup, mask,
                                           mask_x, mask_y,
                                           dst_x, dst_y,
                                           width, height);
    if (unlikely (status))
        goto CLEANUP;

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

    if (clip_region != NULL) {
        int i, num_rectangles;

        num_rectangles = cairo_region_num_rectangles (clip_region);

	for (i = 0; i < num_rectangles; i++) {
	    cairo_rectangle_int_t rect;

	    cairo_region_get_rectangle (clip_region, i, &rect);
            _cairo_gl_composite_emit_rect (ctx,
                                           rect.x,              rect.y,
                                           rect.x + rect.width, rect.y + rect.height,
                                           0);
	}
    } else {
        _cairo_gl_composite_emit_rect (ctx,
                                       dst_x,         dst_y,
                                       dst_x + width, dst_y + height,
                                       0);
    }

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    return status;
}
コード例 #5
0
/* 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;

    cairo_clip_t *clip = composite->clip;
    cairo_traps_t traps;

    /* If we have a non-rectangular clip, we can avoid using the stencil buffer
     * for clipping and just draw the clip polygon. */
    if (clip) {
        status = _clip_to_traps (clip, &traps);
        if (unlikely (status)) {
            _cairo_traps_fini (&traps);
            return 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,
             FALSE);
    if (unlikely (status))
        goto finish;
    _cairo_gl_composite_set_multisample (&setup);
    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
        goto finish;

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

    /* 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,
             FALSE);
    if (unlikely (status))
        goto finish;
    status = _cairo_gl_composite_set_mask (&setup,
                                           &composite->mask_pattern.base,
                                           &composite->source_sample_area,
                                           &composite->bounded,
                                           FALSE);
    if (unlikely (status))
        goto finish;
    status = _cairo_gl_set_operands_and_operator (&setup, ctx);
    if (unlikely (status))
        goto finish;

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

finish:
    _cairo_gl_composite_fini (&setup);
    if (ctx)
        status = _cairo_gl_context_release (ctx, status);
    if (clip)
        _cairo_traps_fini (&traps);

    return status;
}