예제 #1
0
cairo_int_status_t
_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
			      const cairo_pattern_t *pattern,
			      const cairo_rectangle_int_t *sample,
			      const cairo_rectangle_int_t *extents)
{
    cairo_int_status_t status;

    _cairo_gl_operand_destroy (&setup->mask);
    if (pattern == NULL)
        return CAIRO_STATUS_SUCCESS;

    /* XXX: shoot me - we need to set component_alpha to be true
       if op is CAIRO_OPERATOR_CLEAR AND pattern is a surface_pattern
     */
    status = _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
                                     sample, extents, FALSE);
    if (unlikely (status))
	return status;

    if (setup->op == CAIRO_OPERATOR_CLEAR &&
	!  _cairo_pattern_is_opaque (pattern, sample))
	setup->mask.texture.attributes.has_component_alpha = TRUE;

    return status;
}
예제 #2
0
static cairo_int_status_t
_prevent_overlapping_strokes (cairo_gl_context_t 		*ctx,
			      cairo_gl_composite_t 		*setup,
			      cairo_composite_rectangles_t 	*composite,
			      const cairo_path_fixed_t		*path,
			      const cairo_stroke_style_t	*style,
			      const cairo_matrix_t		*ctm)
{
    cairo_rectangle_int_t stroke_extents;

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
				  &composite->source_sample_area))
	return CAIRO_INT_STATUS_SUCCESS;

   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
	cairo_bool_t scissor_was_enabled;

       /* In case we have pending operations we have to flush before
	  adding the stencil buffer. */
       _cairo_gl_composite_flush (ctx);

	/* Enable the stencil buffer, even if we are not using it for clipping,
	   so we can use it below to prevent overlapping shapes. We initialize
	   it all to one here which represents infinite clip. */
	glDepthMask (GL_TRUE);
	glEnable (GL_STENCIL_TEST);

	/* We scissor here so that we don't have to clear the entire stencil
	 * buffer. If the scissor test is already enabled, it was enabled
	 * for clipping. In that case, instead of calculating an intersection,
	 * we just reuse it, and risk clearing too much. */
	scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
	if (! scissor_was_enabled) {
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
							  FALSE, /* is_vector */
							  &stroke_extents);
	    _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
	}
	glClearStencil (1);
	glClear (GL_STENCIL_BUFFER_BIT);
	if (! scissor_was_enabled)
	    glDisable (GL_SCISSOR_TEST);

	glStencilFunc (GL_EQUAL, 1, 1);
    }

    /* This means that once we draw to a particular pixel nothing else can
       be drawn there until the stencil buffer is reset or the stencil test
       is disabled. */
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);

    _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
    setup->dst->clip_on_stencil_buffer = NULL;

    return CAIRO_INT_STATUS_SUCCESS;
}
예제 #3
0
static cairo_bool_t
op_reduces_to_source (const cairo_composite_rectangles_t *extents,
		      cairo_bool_t no_mask)
{
    if (extents->op == CAIRO_OPERATOR_SOURCE)
	return TRUE;

    if (extents->surface->is_clear)
	return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;

    if (no_mask && extents->op == CAIRO_OPERATOR_OVER)
	return _cairo_pattern_is_opaque (&extents->source_pattern.base,
					 &extents->source_sample_area);

    return FALSE;
}
static cairo_status_t
draw_boxes (cairo_composite_rectangles_t *composite,
	    cairo_boxes_t *boxes)
{
    cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface);
    cairo_operator_t op = composite->op;
    const cairo_pattern_t *src = &composite->source_pattern.base;
    cairo_int_status_t status;

    TRACE ((stderr, "%s\n", __FUNCTION__));
    if (boxes->num_boxes == 0 && composite->is_bounded)
	return CAIRO_STATUS_SUCCESS;

    if (!boxes->is_pixel_aligned)
	return CAIRO_STATUS_SUCCESS;
	//return CAIRO_INT_STATUS_UNSUPPORTED;

    if (op == CAIRO_OPERATOR_CLEAR)
	op = CAIRO_OPERATOR_SOURCE;

    if (op == CAIRO_OPERATOR_OVER &&
	_cairo_pattern_is_opaque (src, &composite->bounded))
	op = CAIRO_OPERATOR_SOURCE;

    if (dst->win32.base.is_clear &&
	(op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD))
	op = CAIRO_OPERATOR_SOURCE;

    if (op == CAIRO_OPERATOR_SOURCE) {
	status = CAIRO_INT_STATUS_UNSUPPORTED;
	if (src->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    status = copy_boxes (dst, src, boxes);
	    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
		status = upload_boxes (dst, src, boxes);
	} else if (src->type == CAIRO_PATTERN_TYPE_SOLID) {
	    status = fill_boxes (dst, src, boxes);
	}
	return status;
    }

    if (op == CAIRO_OPERATOR_OVER && can_alpha_blend (dst))
	return alpha_blend_boxes (dst, src, boxes, 255);

    return CAIRO_INT_STATUS_UNSUPPORTED;
}
예제 #5
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;
}