gl/msaa: Implement glyph rendering

Instead of falling back to the traps compositor to do glyph
rendering, handle it in the MSAA compositor. This allows using
the stencil buffer or scissor to clip and simplifies the MSAA
code path.
This commit is contained in:
Martin Robinson 2012-03-12 15:28:23 -07:00
parent e3f5b14fba
commit 4b3ad4e8da
3 changed files with 128 additions and 22 deletions

View file

@ -220,12 +220,13 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
}
static cairo_status_t
render_glyphs (cairo_gl_surface_t *dst,
render_glyphs (cairo_gl_surface_t *dst,
int dst_x, int dst_y,
cairo_operator_t op,
cairo_surface_t *source,
cairo_operator_t op,
cairo_surface_t *source,
cairo_composite_glyphs_info_t *info,
cairo_bool_t *has_component_alpha)
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;
@ -255,6 +256,9 @@ render_glyphs (cairo_gl_surface_t *dst,
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;
@ -344,7 +348,8 @@ render_glyphs_via_mask (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_composite_glyphs_info_t *info,
cairo_clip_t *clip)
{
cairo_surface_t *mask;
cairo_status_t status;
@ -363,7 +368,7 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst,
status = render_glyphs ((cairo_gl_surface_t *) mask,
info->extents.x, info->extents.y,
CAIRO_OPERATOR_ADD, NULL,
info, &has_component_alpha);
info, &has_component_alpha, NULL);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
cairo_surface_pattern_t mask_pattern;
cairo_surface_pattern_t source_pattern;
@ -384,7 +389,7 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst,
status = _cairo_surface_mask (&dst->base, op,
&source_pattern.base,
&mask_pattern.base,
NULL);
clip);
_cairo_pattern_fini (&mask_pattern.base);
_cairo_pattern_fini (&source_pattern.base);
@ -412,14 +417,15 @@ _cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
}
cairo_int_status_t
_cairo_gl_composite_glyphs (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info)
_cairo_gl_composite_glyphs_with_clip (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info,
cairo_clip_t *clip)
{
cairo_gl_surface_t *dst = _dst;
cairo_bool_t has_component_alpha;
@ -440,12 +446,28 @@ _cairo_gl_composite_glyphs (void *_dst,
if (info->use_mask) {
return render_glyphs_via_mask (dst, dst_x, dst_y,
op, _src, info);
op, _src, info, clip);
} else {
return render_glyphs (dst, dst_x, dst_y,
op, _src, info,
&has_component_alpha);
&has_component_alpha,
clip);
}
}
cairo_int_status_t
_cairo_gl_composite_glyphs (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info)
{
return _cairo_gl_composite_glyphs_with_clip (_dst, op, _src, src_x, src_y,
dst_x, dst_y, info, NULL);
}
void

View file

@ -47,10 +47,6 @@
#include "cairo-gl-private.h"
#include "cairo-traps-private.h"
static void
_scissor_to_rectangle (cairo_gl_surface_t *surface,
const cairo_rectangle_int_t *rect);
static cairo_bool_t
should_fall_back (cairo_gl_surface_t *surface,
cairo_antialias_t antialias);
@ -655,6 +651,83 @@ cleanup_traps:
return status;
}
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->source_pattern.base,
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;
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);
_cairo_scaled_font_thaw_cache (scaled_font);
finish:
if (src)
cairo_surface_destroy (src);
return status;
}
static void
_cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
const cairo_compositor_t *delegate)
@ -665,7 +738,7 @@ _cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
compositor->mask = _cairo_gl_msaa_compositor_mask;
compositor->fill = _cairo_gl_msaa_compositor_fill;
compositor->stroke = _cairo_gl_msaa_compositor_stroke;
/* always fallback to common glyph cache implmentation */
compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
}
const cairo_compositor_t *

View file

@ -740,6 +740,17 @@ _cairo_gl_composite_glyphs (void *_dst,
int dst_y,
cairo_composite_glyphs_info_t *info);
cairo_int_status_t
_cairo_gl_composite_glyphs_with_clip (void *_dst,
cairo_operator_t op,
cairo_surface_t *_src,
int src_x,
int src_y,
int dst_x,
int dst_y,
cairo_composite_glyphs_info_t *info,
cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
cairo_content_t content,