static cairo_int_status_t composite (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, cairo_surface_t *abstract_mask, 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_gl_composite_t setup; cairo_gl_context_t *ctx; cairo_int_status_t status; status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); _cairo_gl_composite_set_mask_operand (&setup, source_to_operand (abstract_mask)); _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); FAIL: _cairo_gl_composite_fini (&setup); return status; }
static cairo_int_status_t composite_boxes (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, cairo_surface_t *abstract_mask, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, cairo_boxes_t *boxes, const cairo_rectangle_int_t *extents) { cairo_gl_composite_t setup; cairo_gl_context_t *ctx; cairo_int_status_t status; status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); _cairo_gl_composite_set_mask_operand (&setup, source_to_operand (abstract_mask)); _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); FAIL: _cairo_gl_composite_fini (&setup); return status; }
static cairo_int_status_t composite_tristrip (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, int src_x, int src_y, int dst_x, int dst_y, const cairo_rectangle_int_t *extents, cairo_antialias_t antialias, cairo_tristrip_t *strip) { cairo_gl_composite_t setup; cairo_gl_context_t *ctx; cairo_gl_surface_t *mask; cairo_int_status_t status; mask = tristrip_to_surface (_dst, extents, antialias, strip); if (unlikely (mask->base.status)) return mask->base.status; status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); 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 = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+extents->width, dst_y+extents->height); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); FAIL: _cairo_gl_composite_fini (&setup); cairo_surface_destroy (&mask->base); return status; }
static cairo_int_status_t composite_traps (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, int src_x, int src_y, int dst_x, int dst_y, const cairo_rectangle_int_t *extents, cairo_antialias_t antialias, cairo_traps_t *traps) { cairo_gl_composite_t setup; cairo_gl_context_t *ctx; cairo_int_status_t status; status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y); status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask, dst_x, dst_y); if (unlikely (status)) goto FAIL; status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, extents->x-dst_x, extents->y-dst_y, extents->x-dst_x+extents->width, extents->y-dst_y+extents->height); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); FAIL: _cairo_gl_composite_fini (&setup); return status; }
static cairo_status_t render_glyphs (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_bool_t *has_component_alpha, cairo_clip_t *clip, cairo_bool_t via_msaa_compositor) { cairo_format_t last_format = CAIRO_FORMAT_INVALID; cairo_gl_glyph_cache_t *cache = NULL; cairo_gl_context_t *ctx; cairo_gl_composite_t setup; cairo_int_status_t status; int i = 0; cairo_bool_t is_argb32; TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__, info->extents.x, info->extents.y, info->extents.width, info->extents.height)); *has_component_alpha = FALSE; status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; /* Traps compositor never has CLEAR operator. */ is_argb32 = info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL || info->font->options.antialias == CAIRO_ANTIALIAS_BEST; /* If we are invoked by traps compositor, we keep what is in code otherwise, we handle non-subpixel/best directly in msaa compositor. */ if (!via_msaa_compositor) status = _cairo_gl_composite_init (&setup, op, dst, TRUE); else if (info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL || info->font->options.antialias == CAIRO_ANTIALIAS_BEST) status = _cairo_gl_composite_init (&setup, op, dst, TRUE); else status = _cairo_gl_composite_init (&setup, op, dst, FALSE); if (unlikely (status)) goto FINISH; if (source == NULL) { _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE); } else { _cairo_gl_composite_set_source_operand (&setup, source_to_operand (source)); } if (setup.src.type == CAIRO_GL_OPERAND_CONSTANT) setup.src.use_color_attribute = TRUE; _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; double x_offset, y_offset; double x1, x2, y1, y2; status = _cairo_scaled_glyph_lookup (info->font, info->glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (unlikely (status)) goto FINISH; if (scaled_glyph->surface->width == 0 || scaled_glyph->surface->height == 0) { continue; } if (scaled_glyph->surface->format != last_format) { status = cairo_gl_context_get_glyph_cache (ctx, scaled_glyph->surface->format, &cache); if (unlikely (status)) goto FINISH; last_format = scaled_glyph->surface->format; /* In msaa compositor, clear operator needs component alpha, we need to reset to FALSE if previously clear operator has set it to TRUE. */ if (via_msaa_compositor) { if (op == CAIRO_OPERATOR_CLEAR || is_argb32) cache->surface->operand.texture.attributes.has_component_alpha = TRUE; else cache->surface->operand.texture.attributes.has_component_alpha = FALSE; } _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand); *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha; /* XXX Shoot me. */ status = _cairo_gl_composite_begin (&setup, &ctx); status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) goto FINISH; } if (scaled_glyph->dev_private_key != cache) { cairo_scaled_glyph_private_t *priv; priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache); if (priv) { scaled_glyph->dev_private_key = cache; scaled_glyph->dev_private = cairo_container_of (priv, cairo_gl_glyph_t, base); } else { status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { /* Cache is full, so flush existing prims and try again. */ _cairo_gl_composite_flush (ctx); _cairo_gl_glyph_cache_unlock (cache); status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); } if (unlikely (_cairo_int_status_is_error (status))) goto FINISH; } } x_offset = scaled_glyph->surface->base.device_transform.x0; y_offset = scaled_glyph->surface->base.device_transform.y0; x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x); y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y); x2 = x1 + scaled_glyph->surface->width; y2 = y1 + scaled_glyph->surface->height; glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph); _cairo_gl_composite_emit_glyph (ctx, x1, y1, x2, y2, glyph->p1.x, glyph->p1.y, glyph->p2.x, glyph->p2.y); } status = CAIRO_STATUS_SUCCESS; FINISH: status = _cairo_gl_context_release (ctx, status); _cairo_gl_composite_fini (&setup); return status; }
static cairo_status_t render_glyphs (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_bool_t *has_component_alpha, cairo_clip_t *clip) { cairo_format_t last_format = CAIRO_FORMAT_INVALID; cairo_gl_glyph_cache_t *cache = NULL; cairo_gl_context_t *ctx; cairo_gl_emit_glyph_t emit = NULL; cairo_gl_composite_t setup; cairo_int_status_t status; int i = 0; TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__, info->extents.x, info->extents.y, info->extents.width, info->extents.height)); *has_component_alpha = FALSE; status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; status = _cairo_gl_composite_init (&setup, op, dst, TRUE); if (unlikely (status)) goto FINISH; if (source == NULL) { _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE); } else { _cairo_gl_composite_set_source_operand (&setup, 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; double x_offset, y_offset; double x1, x2, y1, y2; status = _cairo_scaled_glyph_lookup (info->font, info->glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (unlikely (status)) goto FINISH; if (scaled_glyph->surface->width == 0 || scaled_glyph->surface->height == 0) { continue; } if (scaled_glyph->surface->format != last_format) { status = cairo_gl_context_get_glyph_cache (ctx, scaled_glyph->surface->format, &cache); if (unlikely (status)) goto FINISH; last_format = scaled_glyph->surface->format; _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand); *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha; /* XXX Shoot me. */ status = _cairo_gl_composite_begin (&setup, &ctx); status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) goto FINISH; emit = _cairo_gl_context_choose_emit_glyph (ctx); } if (scaled_glyph->dev_private_key != cache) { cairo_scaled_glyph_private_t *priv; priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache); if (priv) { scaled_glyph->dev_private_key = cache; scaled_glyph->dev_private = cairo_container_of (priv, cairo_gl_glyph_t, base); } else { status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { /* Cache is full, so flush existing prims and try again. */ _cairo_gl_composite_flush (ctx); _cairo_gl_glyph_cache_unlock (cache); status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); } if (unlikely (_cairo_int_status_is_error (status))) goto FINISH; } } x_offset = scaled_glyph->surface->base.device_transform.x0; y_offset = scaled_glyph->surface->base.device_transform.y0; x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x); y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y); x2 = x1 + scaled_glyph->surface->width; y2 = y1 + scaled_glyph->surface->height; glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph); assert (emit); emit (ctx, x1, y1, x2, y2, glyph->p1.x, glyph->p1.y, glyph->p2.x, glyph->p2.y); } status = CAIRO_STATUS_SUCCESS; FINISH: status = _cairo_gl_context_release (ctx, status); _cairo_gl_composite_fini (&setup); return status; }