static cairo_gl_gradient_t * _cairo_gl_gradient_lookup (cairo_gl_context_t *ctx, unsigned long hash, unsigned int n_stops, const cairo_gradient_stop_t *stops) { cairo_gl_gradient_t lookup; lookup.cache_entry.hash = hash, lookup.n_stops = n_stops; lookup.stops = stops; return _cairo_cache_lookup (&ctx->gradients, &lookup.cache_entry); }
cairo_status_t _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, cairo_gl_operand_t *source, cairo_gl_operand_t *mask, cairo_bool_t use_coverage, cairo_gl_shader_in_t in, cairo_gl_shader_t **shader) { cairo_shader_cache_entry_t lookup, *entry; char *fs_source; cairo_status_t status; lookup.ctx = ctx; lookup.src = source->type; lookup.mask = mask->type; lookup.dest = CAIRO_GL_OPERAND_NONE; lookup.use_coverage = use_coverage; lookup.in = in; lookup.src_gl_filter = _cairo_gl_operand_get_gl_filter (source); lookup.src_border_fade = _cairo_gl_shader_needs_border_fade (source); lookup.src_extend = _cairo_gl_operand_get_extend (source); lookup.mask_gl_filter = _cairo_gl_operand_get_gl_filter (mask); lookup.mask_border_fade = _cairo_gl_shader_needs_border_fade (mask); lookup.mask_extend = _cairo_gl_operand_get_extend (mask); lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup); lookup.base.size = 1; entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base); if (entry) { assert (entry->shader.program); *shader = &entry->shader; return CAIRO_STATUS_SUCCESS; } status = cairo_gl_shader_get_fragment_source (ctx, in, source, mask, use_coverage, CAIRO_GL_OPERAND_NONE, &fs_source); if (unlikely (status)) return status; entry = malloc (sizeof (cairo_shader_cache_entry_t)); if (unlikely (entry == NULL)) { free (fs_source); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t)); entry->ctx = ctx; _cairo_gl_shader_init (&entry->shader); status = _cairo_gl_shader_compile (ctx, &entry->shader, cairo_gl_operand_get_var_type (source->type), cairo_gl_operand_get_var_type (mask->type), use_coverage, fs_source); free (fs_source); if (unlikely (status)) { free (entry); return status; } _cairo_gl_shader_set_samplers (ctx, &entry->shader); status = _cairo_cache_insert (&ctx->shaders, &entry->base); if (unlikely (status)) { _cairo_gl_shader_fini (ctx, &entry->shader); free (entry); return status; } *shader = &entry->shader; return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, cairo_gl_operand_type_t source, cairo_gl_operand_type_t mask, cairo_gl_shader_in_t in, cairo_gl_shader_t **shader) { cairo_shader_cache_entry_t lookup, *entry; char *fs_source; cairo_status_t status; if (ctx->shader_impl == NULL) { *shader = NULL; return CAIRO_STATUS_SUCCESS; } lookup.src = source; lookup.mask = mask; lookup.dest = CAIRO_GL_OPERAND_NONE; lookup.in = in; lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup); lookup.base.size = 1; entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base); if (entry) { assert (entry->shader.program); *shader = &entry->shader; return CAIRO_STATUS_SUCCESS; } status = cairo_gl_shader_get_fragment_source (ctx->tex_target, in, source, mask, CAIRO_GL_OPERAND_NONE, &fs_source); if (unlikely (status)) return status; entry = malloc (sizeof (cairo_shader_cache_entry_t)); if (unlikely (entry == NULL)) { free (fs_source); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t)); entry->ctx = ctx; _cairo_gl_shader_init (&entry->shader); status = _cairo_gl_shader_compile (ctx, &entry->shader, cairo_gl_operand_get_var_type (source), cairo_gl_operand_get_var_type (mask), fs_source); free (fs_source); if (unlikely (status)) { free (entry); return status; } status = _cairo_cache_insert (&ctx->shaders, &entry->base); if (unlikely (status)) { _cairo_gl_shader_fini (ctx, &entry->shader); free (entry); return status; } *shader = &entry->shader; return CAIRO_STATUS_SUCCESS; }
/** * _cairo_scaled_glyph_lookup: * @scaled_font: a #cairo_scaled_font_t * @index: the glyph to create * @info: a #cairo_scaled_glyph_info_t marking which portions of * the glyph should be filled in. * @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph * is returned. * * Returns a glyph with the requested portions filled in. Glyph * lookup is cached and glyph will be automatically freed along * with the scaled_font so no explicit free is required. * @info can be one or more of: * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space **/ cairo_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, unsigned long index, cairo_scaled_glyph_info_t info, cairo_scaled_glyph_t **scaled_glyph_ret) { cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_cache_entry_t key; cairo_scaled_glyph_t *scaled_glyph; cairo_scaled_glyph_info_t need_info; if (scaled_font->status) return scaled_font->status; CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); key.hash = index; /* * Check cache for glyph */ info |= CAIRO_SCALED_GLYPH_INFO_METRICS; if (!_cairo_cache_lookup (scaled_font->glyphs, &key, (cairo_cache_entry_t **) &scaled_glyph)) { /* * On miss, create glyph and insert into cache */ scaled_glyph = malloc (sizeof (cairo_scaled_glyph_t)); if (scaled_glyph == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP; } _cairo_scaled_glyph_set_index(scaled_glyph, index); scaled_glyph->cache_entry.size = 1; /* XXX */ scaled_glyph->scaled_font = scaled_font; scaled_glyph->surface = NULL; scaled_glyph->path = NULL; scaled_glyph->surface_private = NULL; /* ask backend to initialize metrics and shape fields */ status = (*scaled_font->backend-> scaled_glyph_init) (scaled_font, scaled_glyph, info); if (status) goto CLEANUP; status = _cairo_cache_insert (scaled_font->glyphs, &scaled_glyph->cache_entry); if (status) goto CLEANUP; } /* * Check and see if the glyph, as provided, * already has the requested data and ammend it if not */ need_info = 0; if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 && scaled_glyph->surface == NULL) need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE; if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && scaled_glyph->path == NULL)) need_info |= CAIRO_SCALED_GLYPH_INFO_PATH; if (need_info) { status = (*scaled_font->backend-> scaled_glyph_init) (scaled_font, scaled_glyph, need_info); if (status) goto CLEANUP; } CLEANUP: if (status) { _cairo_scaled_font_set_error (scaled_font, status); if (scaled_glyph) _cairo_scaled_glyph_destroy (scaled_glyph); *scaled_glyph_ret = NULL; } else { *scaled_glyph_ret = scaled_glyph; } CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); return status; }