diff --git a/src/cairo-compositor-private.h b/src/cairo-compositor-private.h index 72507b218..ff4b93b17 100644 --- a/src/cairo-compositor-private.h +++ b/src/cairo-compositor-private.h @@ -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, diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index a27b596ed..90c189aab 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -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) { diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index 1fe4bb34b..395222c68 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -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); diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index e75f81276..31776ff4a 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -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; } diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index a439a7b88..3a3a09d29 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -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; diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c index 3e22f2ffc..eb8f7ff98 100644 --- a/src/cairo-gl-traps-compositor.c +++ b/src/cairo-gl-traps-compositor.c @@ -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; diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c index d299c9f8f..6c409e93c 100644 --- a/src/cairo-image-compositor.c +++ b/src/cairo-image-compositor.c @@ -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; diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c index 0df3b7840..0371c807f 100644 --- a/src/cairo-traps-compositor.c +++ b/src/cairo-traps-compositor.c @@ -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, diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c index 5dd7668d6..6dad822df 100644 --- a/src/cairo-xlib-render-compositor.c +++ b/src/cairo-xlib-render-compositor.c @@ -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; diff --git a/src/test-null-compositor-surface.c b/src/test-null-compositor-surface.c index df2eda0e0..e94c8a74f 100644 --- a/src/test-null-compositor-surface.c +++ b/src/test-null-compositor-surface.c @@ -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;