static cairo_int_status_t
fill_boxes (void		*_dst,
	    cairo_operator_t	 op,
	    const cairo_color_t	*color,
	    cairo_boxes_t	*boxes)
{
    cairo_gl_composite_t setup;
    cairo_gl_context_t *ctx;
    cairo_int_status_t status;

    status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
    if (unlikely (status))
        goto FAIL;

   _cairo_gl_composite_set_solid_source (&setup, color);

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

    emit_aligned_boxes (ctx, boxes);
    status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);

FAIL:
    _cairo_gl_composite_fini (&setup);
    return status;
}
Ejemplo n.º 2
0
static cairo_int_status_t
_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
				      cairo_gl_context_t *ctx,
				      int x, int y,
				      int width, int height)
{
    cairo_gl_composite_t setup;
    cairo_status_t status;

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, dst,
                                       FALSE, NULL);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);

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

    _cairo_gl_composite_emit_rect (ctx, x, y, x + width, y + height, 0);

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

    return status;
}
Ejemplo n.º 3
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;
}
static cairo_int_status_t
composite_tristrip (void		*_dst,
		    cairo_operator_t	op,
		    cairo_surface_t	*abstract_src,
		    int			src_x,
		    int			src_y,
		    int			dst_x,
		    int			dst_y,
		    const cairo_rectangle_int_t *extents,
		    cairo_antialias_t	antialias,
		    cairo_tristrip_t	*strip)
{
    cairo_gl_composite_t setup;
    cairo_gl_context_t *ctx;
    cairo_gl_surface_t *mask;
    cairo_int_status_t status;

    mask = tristrip_to_surface (_dst, extents, antialias, strip);
    if (unlikely (mask->base.status))
	return mask->base.status;

    status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
    if (unlikely (status))
        goto FAIL;

    _cairo_gl_composite_set_source_operand (&setup,
					    source_to_operand (abstract_src));

    //_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0);

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

    /* XXX clip */
    _cairo_gl_context_emit_rect (ctx,
				 dst_x, dst_y,
				 dst_x+extents->width,
				 dst_y+extents->height);
    status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);

FAIL:
    _cairo_gl_composite_fini (&setup);
    cairo_surface_destroy (&mask->base);
    return status;
}
static cairo_int_status_t
composite_traps (void			*_dst,
		 cairo_operator_t	op,
		 cairo_surface_t	*abstract_src,
		 int			src_x,
		 int			src_y,
		 int			dst_x,
		 int			dst_y,
		 const cairo_rectangle_int_t *extents,
		 cairo_antialias_t	antialias,
		 cairo_traps_t		*traps)
{
    cairo_gl_composite_t setup;
    cairo_gl_context_t *ctx;
    cairo_int_status_t status;

    status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
    if (unlikely (status))
        goto FAIL;

    _cairo_gl_composite_set_source_operand (&setup,
					    source_to_operand (abstract_src));
    _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y);
    status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask, dst_x, dst_y);
    if (unlikely (status))
	goto FAIL;

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

    /* XXX clip */
    _cairo_gl_context_emit_rect (ctx,
				 extents->x-dst_x, extents->y-dst_y,
				 extents->x-dst_x+extents->width,
				 extents->y-dst_y+extents->height);
    status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);

FAIL:
    _cairo_gl_composite_fini (&setup);
    return status;
}
static cairo_int_status_t
composite (void			*_dst,
	   cairo_operator_t	op,
	   cairo_surface_t	*abstract_src,
	   cairo_surface_t	*abstract_mask,
	   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_gl_composite_t setup;
    cairo_gl_context_t *ctx;
    cairo_int_status_t status;

    status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
    if (unlikely (status))
        goto FAIL;

    _cairo_gl_composite_set_source_operand (&setup,
					    source_to_operand (abstract_src));
    _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y);

    _cairo_gl_composite_set_mask_operand (&setup,
					  source_to_operand (abstract_mask));
    _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y);

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

    /* XXX clip */
    _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height);
    status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);

FAIL:
    _cairo_gl_composite_fini (&setup);
    return status;
}
static cairo_int_status_t
composite_boxes (void			*_dst,
		 cairo_operator_t	op,
		 cairo_surface_t	*abstract_src,
		 cairo_surface_t	*abstract_mask,
		 int			src_x,
		 int			src_y,
		 int			mask_x,
		 int			mask_y,
		 int			dst_x,
		 int			dst_y,
		 cairo_boxes_t		*boxes,
		 const cairo_rectangle_int_t  *extents)
{
    cairo_gl_composite_t setup;
    cairo_gl_context_t *ctx;
    cairo_int_status_t status;

    status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
    if (unlikely (status))
        goto FAIL;

    _cairo_gl_composite_set_source_operand (&setup,
					    source_to_operand (abstract_src));
    _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y);

    _cairo_gl_composite_set_mask_operand (&setup,
					  source_to_operand (abstract_mask));
    _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y);

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

    emit_aligned_boxes (ctx, boxes);
    status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);

FAIL:
    _cairo_gl_composite_fini (&setup);
    return status;
}
Ejemplo n.º 8
0
static cairo_status_t
render_glyphs (cairo_gl_surface_t *dst,
	       int dst_x, int dst_y,
	       cairo_operator_t op,
	       cairo_surface_t *source,
	       cairo_composite_glyphs_info_t *info,
	       cairo_bool_t *has_component_alpha,
	       cairo_clip_t *clip,
	       cairo_bool_t via_msaa_compositor)
{
    cairo_format_t last_format = CAIRO_FORMAT_INVALID;
    cairo_gl_glyph_cache_t *cache = NULL;
    cairo_gl_context_t *ctx;
    cairo_gl_composite_t setup;
    cairo_int_status_t status;
    int i = 0;
    cairo_bool_t is_argb32;

    TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__,
	    info->extents.x, info->extents.y,
	    info->extents.width, info->extents.height));

    *has_component_alpha = FALSE;

    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
    if (unlikely (status))
	return status;

    /* Traps compositor never has CLEAR operator. */
    is_argb32 =
	info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ||
	info->font->options.antialias == CAIRO_ANTIALIAS_BEST;

    /* If we are invoked by traps compositor, we keep what is in code
       otherwise, we handle non-subpixel/best directly in msaa
       compositor. */
    if (!via_msaa_compositor)
            status = _cairo_gl_composite_init (&setup, op, dst, TRUE);
    else if (info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ||
       info->font->options.antialias == CAIRO_ANTIALIAS_BEST)
        status = _cairo_gl_composite_init (&setup, op, dst, TRUE);
    else
        status = _cairo_gl_composite_init (&setup, op, dst, FALSE);

    if (unlikely (status))
	goto FINISH;

    if (source == NULL) {
	    _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE);
    } else {
	    _cairo_gl_composite_set_source_operand (&setup,
						    source_to_operand (source));

    }

    if (setup.src.type == CAIRO_GL_OPERAND_CONSTANT)
        setup.src.use_color_attribute = TRUE;

    _cairo_gl_composite_set_clip (&setup, clip);

    for (i = 0; i < info->num_glyphs; i++) {
	cairo_scaled_glyph_t *scaled_glyph;
	cairo_gl_glyph_t *glyph;
	double x_offset, y_offset;
	double x1, x2, y1, y2;

	status = _cairo_scaled_glyph_lookup (info->font,
					     info->glyphs[i].index,
					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
					     &scaled_glyph);
	if (unlikely (status))
	    goto FINISH;

	if (scaled_glyph->surface->width  == 0 ||
	    scaled_glyph->surface->height == 0)
	{
	    continue;
	}
	if (scaled_glyph->surface->format != last_format) {
	    status = cairo_gl_context_get_glyph_cache (ctx,
						       scaled_glyph->surface->format,
                                                       &cache);
            if (unlikely (status))
                goto FINISH;

	    last_format = scaled_glyph->surface->format;

	    /* In msaa compositor, clear operator needs component alpha,
	       we need to reset to FALSE if previously clear operator
	       has set it to TRUE. */
	    if (via_msaa_compositor) {
		if (op == CAIRO_OPERATOR_CLEAR || is_argb32)
		    cache->surface->operand.texture.attributes.has_component_alpha = TRUE;
		else
		    cache->surface->operand.texture.attributes.has_component_alpha = FALSE;
	    }
	    _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand);
	    *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha;

	    /* XXX Shoot me. */
            status = _cairo_gl_composite_begin (&setup, &ctx);
            status = _cairo_gl_context_release (ctx, status);
	    if (unlikely (status))
		goto FINISH;
	}

	if (scaled_glyph->dev_private_key != cache) {
	    cairo_scaled_glyph_private_t *priv;

	    priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache);
	    if (priv) {
		scaled_glyph->dev_private_key = cache;
		scaled_glyph->dev_private = cairo_container_of (priv,
								cairo_gl_glyph_t,
								base);
	    } else {
		status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);

		if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
		    /* Cache is full, so flush existing prims and try again. */
		    _cairo_gl_composite_flush (ctx);
		    _cairo_gl_glyph_cache_unlock (cache);
		    status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
		}

		if (unlikely (_cairo_int_status_is_error (status)))
		    goto FINISH;
	    }
	}

	x_offset = scaled_glyph->surface->base.device_transform.x0;
	y_offset = scaled_glyph->surface->base.device_transform.y0;

	x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x);
	y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y);
	x2 = x1 + scaled_glyph->surface->width;
	y2 = y1 + scaled_glyph->surface->height;

	glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
	_cairo_gl_composite_emit_glyph (ctx,
					x1, y1, x2, y2,
                                        glyph->p1.x, glyph->p1.y,
                                        glyph->p2.x, glyph->p2.y);
    }

    status = CAIRO_STATUS_SUCCESS;

  FINISH:
    status = _cairo_gl_context_release (ctx, status);

    _cairo_gl_composite_fini (&setup);
    return status;
}
Ejemplo n.º 9
0
cairo_span_renderer_t *
_cairo_gl_surface_create_span_renderer (cairo_operator_t	 op,
					const cairo_pattern_t	*src,
					void			*abstract_dst,
					cairo_antialias_t	 antialias,
					const cairo_composite_rectangles_t *rects)
{
    cairo_gl_surface_t *dst = abstract_dst;
    cairo_gl_surface_span_renderer_t *renderer;
    cairo_status_t status;
    const cairo_rectangle_int_t *extents;

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

    renderer = calloc (1, sizeof (*renderer));
    if (unlikely (renderer == NULL))
	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);

    renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy;
    if (rects->is_bounded) {
	renderer->base.render_rows = _cairo_gl_render_bounded_spans;
        renderer->base.finish =      _cairo_gl_finish_bounded_spans;
	extents = &rects->bounded;
    } else {
	renderer->base.render_rows = _cairo_gl_render_unbounded_spans;
        renderer->base.finish =      _cairo_gl_finish_unbounded_spans;
	extents = &rects->unbounded;
    }
    renderer->xmin = extents->x;
    renderer->xmax = extents->x + extents->width;
    renderer->ymin = extents->y;
    renderer->ymax = extents->y + extents->height;

    status = _cairo_gl_composite_init (&renderer->setup,
                                       op, dst,
                                       FALSE, extents);
    if (unlikely (status))
        goto FAIL;

    status = _cairo_gl_composite_set_source (&renderer->setup, src,
                                             extents->x, extents->y,
                                             extents->x, extents->y,
                                             extents->width, extents->height);
    if (unlikely (status))
        goto FAIL;

    _cairo_gl_composite_set_spans (&renderer->setup);
    _cairo_gl_composite_set_clip_region (&renderer->setup,
					 _cairo_clip_get_region (rects->clip));

    status = _cairo_gl_composite_begin (&renderer->setup, &renderer->ctx);
    if (unlikely (status))
        goto FAIL;

    return &renderer->base;

FAIL:
    _cairo_gl_composite_fini (&renderer->setup);
    free (renderer);
    return _cairo_span_renderer_create_in_error (status);
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
static cairo_status_t
render_glyphs (cairo_gl_surface_t *dst,
	       int dst_x, int dst_y,
	       cairo_operator_t op,
	       cairo_surface_t *source,
	       cairo_composite_glyphs_info_t *info,
	       cairo_bool_t *has_component_alpha,
	       cairo_clip_t *clip)
{
    cairo_format_t last_format = CAIRO_FORMAT_INVALID;
    cairo_gl_glyph_cache_t *cache = NULL;
    cairo_gl_context_t *ctx;
    cairo_gl_emit_glyph_t emit = NULL;
    cairo_gl_composite_t setup;
    cairo_int_status_t status;
    int i = 0;

    TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__,
	    info->extents.x, info->extents.y,
	    info->extents.width, info->extents.height));

    *has_component_alpha = FALSE;

    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
    if (unlikely (status))
	return status;

    status = _cairo_gl_composite_init (&setup, op, dst, TRUE);
    if (unlikely (status))
	goto FINISH;

    if (source == NULL) {
	    _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE);
    } else {
	    _cairo_gl_composite_set_source_operand (&setup,
						    source_to_operand (source));

    }

    _cairo_gl_composite_set_clip (&setup, clip);

    for (i = 0; i < info->num_glyphs; i++) {
	cairo_scaled_glyph_t *scaled_glyph;
	cairo_gl_glyph_t *glyph;
	double x_offset, y_offset;
	double x1, x2, y1, y2;

	status = _cairo_scaled_glyph_lookup (info->font,
					     info->glyphs[i].index,
					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
					     &scaled_glyph);
	if (unlikely (status))
	    goto FINISH;

	if (scaled_glyph->surface->width  == 0 ||
	    scaled_glyph->surface->height == 0)
	{
	    continue;
	}
	if (scaled_glyph->surface->format != last_format) {
	    status = cairo_gl_context_get_glyph_cache (ctx,
						       scaled_glyph->surface->format,
                                                       &cache);
            if (unlikely (status))
                goto FINISH;

	    last_format = scaled_glyph->surface->format;

	    _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand);
	    *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha;

	    /* XXX Shoot me. */
            status = _cairo_gl_composite_begin (&setup, &ctx);
            status = _cairo_gl_context_release (ctx, status);
	    if (unlikely (status))
		goto FINISH;

	    emit = _cairo_gl_context_choose_emit_glyph (ctx);
	}

	if (scaled_glyph->dev_private_key != cache) {
	    cairo_scaled_glyph_private_t *priv;

	    priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache);
	    if (priv) {
		scaled_glyph->dev_private_key = cache;
		scaled_glyph->dev_private = cairo_container_of (priv,
								cairo_gl_glyph_t,
								base);
	    } else {
		status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);

		if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
		    /* Cache is full, so flush existing prims and try again. */
		    _cairo_gl_composite_flush (ctx);
		    _cairo_gl_glyph_cache_unlock (cache);
		    status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
		}

		if (unlikely (_cairo_int_status_is_error (status)))
		    goto FINISH;
	    }
	}

	x_offset = scaled_glyph->surface->base.device_transform.x0;
	y_offset = scaled_glyph->surface->base.device_transform.y0;

	x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x);
	y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y);
	x2 = x1 + scaled_glyph->surface->width;
	y2 = y1 + scaled_glyph->surface->height;

	glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
	assert (emit);
	emit (ctx,
	      x1, y1, x2, y2,
	      glyph->p1.x, glyph->p1.y,
	      glyph->p2.x, glyph->p2.y);
    }

    status = CAIRO_STATUS_SUCCESS;
  FINISH:
    status = _cairo_gl_context_release (ctx, status);

    _cairo_gl_composite_fini (&setup);
    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;
}
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_clip_t *clip = composite->clip;

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

    if (composite->op == CAIRO_OPERATOR_CLEAR &&
            composite->original_mask_pattern != NULL)
        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 (! _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)) {
        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))
        return status;

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

    if (composite->original_mask_pattern != NULL) {
        status = _cairo_gl_composite_set_mask (&setup,
                                               &composite->mask_pattern.base,
                                               &composite->mask_sample_area,
                                               &composite->bounded,
                                               FALSE);
    }
    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. */
    _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 = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);

finish:
    _cairo_gl_composite_fini (&setup);

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

    return status;
}
/* 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;
}