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 _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; }
/* The first pass, we use mask as source, to get dst1 = (1 - ma) * dst) with * DEST_OUT operator. In the second pass, we use ADD operator to achieve * result = (src * ma) + dst1. Combining two passes, we have * 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_traps_t traps; _cairo_traps_init (&traps); status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_DEST_OUT, dst, FALSE /* assume_component_alpha */); if (unlikely (status)) goto finish; _gl_pattern_fix_reference_count (composite->original_mask_pattern); status = _cairo_gl_composite_set_source (&setup, &composite->mask_pattern.base, &composite->mask_sample_area, &composite->bounded, FALSE); if (unlikely (status)) goto finish; status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE); if (unlikely (status)) goto finish; 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_gl_composite_fini (&setup); status = _cairo_gl_context_release (ctx, status); ctx = NULL; if (unlikely (status)) return status; /* second pass */ status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_ADD, dst, FALSE /* assume_component_alpha */); if (unlikely (status)) goto finish; _gl_pattern_fix_reference_count (composite->original_source_pattern); 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); 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; if (! composite->clip) status = _draw_int_rect (ctx, &setup, &composite->bounded); else status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps); finish: _cairo_traps_fini (&traps); _cairo_gl_composite_fini (&setup); if (ctx) status = _cairo_gl_context_release (ctx, status); return status; }
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; }
/* 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; }