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_INT_STATUS_SUCCESS; cairo_traps_t traps; cairo_bool_t use_color_attr = FALSE; 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); } if (_cairo_path_fixed_fill_is_rectilinear (path) && composite->clip != NULL && composite->clip->num_boxes == 1 && composite->clip->path == NULL) { cairo_clip_t *clip = _cairo_clip_copy (composite->clip); clip = _cairo_clip_intersect_rectilinear_path (clip, path, fill_rule, antialias); if (clip->num_boxes) status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor, composite, path, fill_rule, tolerance, antialias, clip); _cairo_clip_destroy (clip); return status; } status = _cairo_gl_composite_init (&setup, composite->op, dst, FALSE /* assume_component_alpha */); if (unlikely (status)) { _cairo_gl_composite_fini (&setup); return status; } _cairo_traps_init (&traps); if (_cairo_path_fixed_fill_is_rectilinear (path)) { status = _cairo_path_fixed_fill_rectilinear_to_traps (path, fill_rule, antialias, &traps); use_color_attr = TRUE; } else status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); if (unlikely (status)) goto cleanup_traps; status = _cairo_gl_composite_set_source (&setup, composite->original_source_pattern, &composite->source_sample_area, &composite->bounded, use_color_attr); if (unlikely (status)) goto cleanup_setup; _cairo_gl_msaa_compositor_set_clip (composite, &setup); status = _cairo_gl_composite_begin_multisample (&setup, &ctx, antialias != CAIRO_ANTIALIAS_NONE); if (unlikely (status)) goto cleanup_setup; 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: _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; cairo_bool_t use_color_attribute; 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; use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) || _cairo_gl_hairline_style_is_hairline (style, ctm); status = _cairo_gl_composite_set_source (&info.setup, composite->original_source_pattern, &composite->source_sample_area, &composite->bounded, use_color_attribute); if (unlikely (status)) goto finish; _cairo_gl_msaa_compositor_set_clip (composite, &info.setup); status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx, antialias != CAIRO_ANTIALIAS_NONE); if (unlikely (status)) goto finish; if (_cairo_gl_hairline_style_is_hairline (style, ctm)) { cairo_gl_hairline_closure_t closure; if (! (_is_continuous_arc (path, style) || _is_continuous_single_line (path, style))) { status = _prevent_overlapping_drawing (info.ctx, &info.setup, composite, path, style, ctm); if (unlikely (status)) goto finish; } closure.ctx = info.ctx; closure.tolerance = tolerance; status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure, style, ctm, ctm_inverse, _cairo_gl_hairline_move_to, style->dash ? _cairo_gl_hairline_line_to_dashed : _cairo_gl_hairline_line_to, _cairo_gl_hairline_curve_to, _cairo_gl_hairline_close_path); goto finish; } if (use_color_attribute) { cairo_traps_t traps; _cairo_traps_init (&traps); status = _cairo_path_fixed_stroke_to_traps (path, style, ctm, ctm_inverse, tolerance, &traps); if (unlikely (status)) { _cairo_traps_fini (&traps); goto finish; } status = _draw_traps (info.ctx, &info.setup, &traps); _cairo_traps_fini (&traps); } else { if (!_is_continuous_single_line (path, style)) { status = _prevent_overlapping_drawing (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_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; }
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->original_source_pattern, 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 || composite->op == CAIRO_OPERATOR_SOURCE; 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, TRUE); _cairo_scaled_font_thaw_cache (scaled_font); finish: if (src) cairo_surface_destroy (src); 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; }