mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-03-11 13:00:37 +01:00
gl: Prevent the traps compositor from exploding
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
5e4a0bd892
commit
2c4f6bbfbc
10 changed files with 105 additions and 28 deletions
|
|
@ -210,6 +210,9 @@ struct cairo_traps_compositor {
|
|||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes);
|
||||
|
||||
cairo_int_status_t
|
||||
(*check_composite) (const cairo_composite_rectangles_t *extents);
|
||||
|
||||
cairo_int_status_t
|
||||
(*composite) (void *dst,
|
||||
cairo_operator_t op,
|
||||
|
|
|
|||
|
|
@ -476,8 +476,9 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
|
|||
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
component_alpha = ((setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) &&
|
||||
setup->mask.texture.attributes.has_component_alpha);
|
||||
component_alpha =
|
||||
setup->mask.type == CAIRO_GL_OPERAND_TEXTURE &&
|
||||
setup->mask.texture.attributes.has_component_alpha;
|
||||
|
||||
/* Do various magic for component alpha */
|
||||
if (component_alpha) {
|
||||
|
|
|
|||
|
|
@ -59,11 +59,15 @@ typedef struct _cairo_gl_glyph {
|
|||
} cairo_gl_glyph_t;
|
||||
|
||||
static void
|
||||
_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *_priv,
|
||||
_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_gl_glyph_t *priv = cairo_container_of (_priv, cairo_gl_glyph_t, base);
|
||||
cairo_gl_glyph_t *priv = cairo_container_of (glyph_private,
|
||||
cairo_gl_glyph_t,
|
||||
base);
|
||||
|
||||
cairo_list_del (&glyph_private->link);
|
||||
|
||||
priv->node.owner = NULL;
|
||||
if (! priv->node.pinned) {
|
||||
|
|
@ -302,7 +306,7 @@ render_glyphs (cairo_gl_surface_t *dst,
|
|||
scaled_glyph->dev_private_key = cache;
|
||||
scaled_glyph->dev_private = cairo_container_of (priv,
|
||||
cairo_gl_glyph_t,
|
||||
base);;
|
||||
base);
|
||||
} else {
|
||||
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
|
|||
|
||||
attributes->extend = src->base.extend;
|
||||
attributes->filter = src->base.filter;
|
||||
attributes->has_component_alpha = src->base.has_component_alpha;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +187,7 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
|
|||
|
||||
attributes->extend = src->base.extend;
|
||||
attributes->filter = src->base.filter;
|
||||
attributes->has_component_alpha = src->base.has_component_alpha;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -355,6 +355,8 @@ _cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
|
|||
cairo_gl_operand_t *operand = &surface->operand;
|
||||
cairo_surface_attributes_t *attributes = &operand->texture.attributes;
|
||||
|
||||
memset (operand, 0, sizeof (cairo_gl_operand_t));
|
||||
|
||||
operand->type = CAIRO_GL_OPERAND_TEXTURE;
|
||||
operand->texture.surface = surface;
|
||||
operand->texture.tex = surface->tex;
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ pattern_to_surface (cairo_surface_t *dst,
|
|||
cairo_gl_source_t *source;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (pattern == NULL)
|
||||
return _cairo_gl_white_source ();
|
||||
|
||||
source = malloc (sizeof (*source));
|
||||
if (unlikely (source == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
|
@ -201,7 +204,7 @@ static inline cairo_gl_operand_t *
|
|||
source_to_operand (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
|
||||
return &source->operand;
|
||||
return surface ? &source->operand : NULL;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -320,15 +323,17 @@ lerp (void *dst,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_gl_surface_t *
|
||||
traps_to_surface (void *_dst,
|
||||
static cairo_int_status_t
|
||||
traps_to_operand (void *_dst,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_traps_t *traps)
|
||||
cairo_traps_t *traps,
|
||||
cairo_gl_operand_t *operand)
|
||||
{
|
||||
pixman_format_code_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_surface_t *image, *mask;
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
|
||||
|
|
@ -337,22 +342,23 @@ traps_to_surface (void *_dst,
|
|||
extents->height,
|
||||
NULL, 0);
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_pixman_image_add_traps (pixman_image, extents->x, extents->y, traps);
|
||||
image = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
pixman_format);
|
||||
if (unlikely (image->status)) {
|
||||
pixman_image_unref (pixman_image);
|
||||
return (cairo_gl_surface_t *)image;
|
||||
return image->status;
|
||||
}
|
||||
|
||||
mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
|
||||
mask = _cairo_surface_create_similar_scratch (_dst,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (unlikely (mask->status)) {
|
||||
cairo_surface_destroy (image);
|
||||
return (cairo_gl_surface_t *)mask;
|
||||
return mask->status;
|
||||
}
|
||||
|
||||
status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
|
||||
|
|
@ -363,10 +369,21 @@ traps_to_surface (void *_dst,
|
|||
cairo_surface_destroy (image);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (mask);
|
||||
return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return (cairo_gl_surface_t*)mask;
|
||||
_cairo_pattern_init_for_surface (&pattern, mask);
|
||||
cairo_matrix_init_translate (&pattern.base.matrix,
|
||||
-extents->x, -extents->y);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
pattern.base.extend = CAIRO_EXTEND_NONE;
|
||||
status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
|
||||
&_cairo_unbounded_rectangle,
|
||||
&_cairo_unbounded_rectangle);
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
cairo_surface_destroy (mask);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -383,21 +400,17 @@ composite_traps (void *_dst,
|
|||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_gl_surface_t *mask;
|
||||
cairo_int_status_t status;
|
||||
|
||||
mask = traps_to_surface (_dst, extents, antialias, traps);
|
||||
if (unlikely (mask->base.status))
|
||||
return mask->base.status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
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 = traps_to_operand (_dst, extents, antialias, traps, &setup.mask);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
|
|
@ -412,7 +425,6 @@ composite_traps (void *_dst,
|
|||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
cairo_surface_destroy (&mask->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +455,8 @@ tristrip_to_surface (void *_dst,
|
|||
return (cairo_gl_surface_t *)image;
|
||||
}
|
||||
|
||||
mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
|
||||
mask = _cairo_surface_create_similar_scratch (_dst,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (unlikely (mask->status)) {
|
||||
|
|
@ -512,6 +525,15 @@ FAIL:
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite (const cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
if (! _cairo_gl_operator_is_supported (extents->op))
|
||||
return UNSUPPORTED ("unsupported operator");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_gl_traps_compositor_get (void)
|
||||
{
|
||||
|
|
@ -526,7 +548,7 @@ _cairo_gl_traps_compositor_get (void)
|
|||
compositor.draw_image_boxes = draw_image_boxes;
|
||||
//compositor.copy_boxes = copy_boxes;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
compositor.lerp = lerp;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
|
|
|
|||
|
|
@ -971,6 +971,12 @@ composite_glyphs (void *_dst,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite (const cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_image_traps_compositor_get (void)
|
||||
{
|
||||
|
|
@ -986,7 +992,7 @@ _cairo_image_traps_compositor_get (void)
|
|||
compositor.draw_image_boxes = draw_image_boxes;
|
||||
//compositor.copy_boxes = copy_boxes;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
compositor.lerp = lerp;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
|
|
|
|||
|
|
@ -1797,6 +1797,10 @@ _cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
|
|||
cairo_boxes_t boxes;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = compositor->check_composite (extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_clip_steal_boxes (extents->clip, &boxes);
|
||||
status = clip_and_composite_boxes (compositor, extents, &boxes);
|
||||
_cairo_clip_unsteal_boxes (extents->clip, &boxes);
|
||||
|
|
@ -1811,6 +1815,10 @@ _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
|
|||
const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = compositor->check_composite (extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
extents->clip->path == NULL) {
|
||||
status = clip_and_composite (compositor, extents,
|
||||
|
|
@ -1853,6 +1861,10 @@ _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
|
|||
const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = compositor->check_composite (extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
|
||||
cairo_boxes_t boxes;
|
||||
|
|
@ -1912,6 +1924,10 @@ _cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
|
|||
const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = compositor->check_composite (extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (_cairo_path_fixed_fill_is_rectilinear (path)) {
|
||||
cairo_boxes_t boxes;
|
||||
|
|
@ -1995,6 +2011,10 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
|
|||
const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = compositor->check_composite (extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
status = compositor->check_composite_glyphs (extents,
|
||||
scaled_font, glyphs,
|
||||
|
|
|
|||
|
|
@ -1664,6 +1664,17 @@ composite_tristrip (void *abstract_dst,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite (const cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_xlib_display_t *display = ((cairo_xlib_surface_t *)extents->surface)->display;
|
||||
|
||||
if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_xlib_traps_compositor_get (void)
|
||||
{
|
||||
|
|
@ -1680,7 +1691,7 @@ _cairo_xlib_traps_compositor_get (void)
|
|||
compositor.draw_image_boxes = draw_image_boxes;
|
||||
compositor.copy_boxes = copy_boxes;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
compositor.lerp = lerp;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
|
|
|
|||
|
|
@ -392,6 +392,12 @@ no_fallback_compositor_get (void)
|
|||
return &__cairo_no_compositor;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite (const cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_compositor_t *
|
||||
no_traps_compositor_get (void)
|
||||
{
|
||||
|
|
@ -408,7 +414,7 @@ no_traps_compositor_get (void)
|
|||
compositor.draw_image_boxes = draw_image_boxes;
|
||||
//compositor.copy_boxes = copy_boxes;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
compositor.lerp = lerp;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue