cairo_status_t
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
{
    static const char *fill_fs_source =
	"#ifdef GL_ES\n"
	"precision mediump float;\n"
	"#endif\n"
	"uniform vec4 color;\n"
	"void main()\n"
	"{\n"
	"	gl_FragColor = color;\n"
	"}\n";
    cairo_status_t status;

    if (_cairo_gl_get_version () >= CAIRO_GL_VERSION_ENCODE (2, 0) ||
	(_cairo_gl_has_extension ("GL_ARB_shader_objects") &&
	 _cairo_gl_has_extension ("GL_ARB_fragment_shader") &&
	 _cairo_gl_has_extension ("GL_ARB_vertex_shader")))
    {
	ctx->shader_impl = &shader_impl_core_2_0;
    }
    else
    {
	ctx->shader_impl = NULL;
	fprintf (stderr, "Error: The cairo gl backend requires shader support!\n");
	return CAIRO_STATUS_DEVICE_ERROR;
    }

    memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders));

    status = _cairo_cache_init (&ctx->shaders,
                                ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ?
				    _cairo_gl_shader_cache_equal_desktop :
				    _cairo_gl_shader_cache_equal_gles2,
                                NULL,
                                _cairo_gl_shader_cache_destroy,
                                CAIRO_GL_MAX_SHADERS_PER_CONTEXT);
    if (unlikely (status))
	return status;

    _cairo_gl_shader_init (&ctx->fill_rectangles_shader);
    status = _cairo_gl_shader_compile (ctx,
				       &ctx->fill_rectangles_shader,
				       CAIRO_GL_VAR_NONE,
				       CAIRO_GL_VAR_NONE,
				       FALSE,
				       fill_fs_source);
    if (unlikely (status))
	return status;

    return CAIRO_STATUS_SUCCESS;
}
Exemple #2
0
cairo_status_t
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
{
    static const char *fill_fs_source =
	"uniform vec4 color;\n"
	"void main()\n"
	"{\n"
	"	gl_FragColor = color;\n"
	"}\n";
    cairo_status_t status;

    /* XXX multiple device support? */
    if (GLEW_VERSION_2_0) {
        ctx->shader_impl = &shader_impl_core_2_0;
    } else if (GLEW_ARB_shader_objects &&
               GLEW_ARB_fragment_shader &&
               GLEW_ARB_vertex_program) {
        ctx->shader_impl = &shader_impl_arb;
    } else {
        ctx->shader_impl = NULL;
    }

    memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders));

    status = _cairo_cache_init (&ctx->shaders,
                                _cairo_gl_shader_cache_equal,
                                NULL,
                                _cairo_gl_shader_cache_destroy,
                                CAIRO_GL_MAX_SHADERS_PER_CONTEXT);
    if (unlikely (status))
	return status;

    if (ctx->shader_impl != NULL) {
	_cairo_gl_shader_init (&ctx->fill_rectangles_shader);
	status = _cairo_gl_shader_compile (ctx,
					   &ctx->fill_rectangles_shader,
					   CAIRO_GL_VAR_NONE,
					   CAIRO_GL_VAR_NONE,
					   fill_fs_source);
	if (unlikely (status))
	    return status;
    }

    return CAIRO_STATUS_SUCCESS;
}
Exemple #3
0
/**
 * _cairo_cache_create:
 * @keys_equal: a function to return %TRUE if two keys are equal
 * @entry_destroy: destroy notifier for cache entries
 * @max_size: the maximum size for this cache
 * Returns: the newly created #cairo_cache_t
 *
 * Creates a new cache using the keys_equal() function to determine
 * the equality of entries.
 *
 * Data is provided to the cache in the form of user-derived version
 * of #cairo_cache_entry_t. A cache entry must be able to hold hash
 * code, a size, and the key/value pair being stored in the
 * cache. Sometimes only the key will be necessary, (as in
 * _cairo_cache_lookup()), and in these cases the value portion of the
 * entry need not be initialized.
 *
 * The units for max_size can be chosen by the caller, but should be
 * consistent with the units of the size field of cache entries. When
 * adding an entry with _cairo_cache_insert() if the total size of
 * entries in the cache would exceed max_size then entries will be
 * removed at random until the new entry would fit or the cache is
 * empty. Then the new entry is inserted.
 *
 * There are cases in which the automatic removal of entries is
 * undesired. If the cache entries have reference counts, then it is a
 * simple matter to use the reference counts to ensure that entries
 * continue to live even after being ejected from the cache. However,
 * in some cases the memory overhead of adding a reference count to
 * the entry would be objectionable. In such cases, the
 * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
 * used to establish a window during which no automatic removal of
 * entries will occur.
 **/
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
                     cairo_destroy_func_t	   entry_destroy,
                     unsigned long		   max_size)
{
    cairo_status_t status;
    cairo_cache_t *cache;

    cache = malloc (sizeof (cairo_cache_t));
    if (unlikely (cache == NULL)) {
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
        return NULL;
    }

    status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
    if (unlikely (status)) {
        free (cache);
        return NULL;
    }

    return cache;
}
cairo_cache_t *
_cairo_get_global_image_glyph_cache (void)
{
    if (_global_image_glyph_cache == NULL) {
	_global_image_glyph_cache = malloc (sizeof (cairo_cache_t));
	
	if (_global_image_glyph_cache == NULL)
	    goto FAIL;
	
	if (_cairo_cache_init (_global_image_glyph_cache,
			       &cairo_image_cache_backend,
			       0))
	    goto FAIL;
    }

    return _global_image_glyph_cache;
    
 FAIL:
    if (_global_image_glyph_cache)
	free (_global_image_glyph_cache);
    _global_image_glyph_cache = NULL;
    return NULL;
}
Exemple #5
0
cairo_status_t
_cairo_gl_context_init (cairo_gl_context_t *ctx)
{
    cairo_status_t status;
    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
    int gl_version = _cairo_gl_get_version ();
    cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor ();
    int n;

    _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);

    /* XXX The choice of compositor should be made automatically at runtime.
     * However, it is useful to force one particular compositor whilst
     * testing.
     */
     if (_cairo_gl_msaa_compositor_enabled ())
	ctx->compositor = _cairo_gl_msaa_compositor_get ();
    else
	ctx->compositor = _cairo_gl_span_compositor_get ();


    ctx->thread_aware = TRUE;

    memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
    cairo_list_init (&ctx->fonts);

    /* Support only GL version >= 1.3 */
    if (gl_version < CAIRO_GL_VERSION_ENCODE (1, 3))
	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);

    /* Check for required extensions */
    if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
	if (_cairo_gl_has_extension ("GL_ARB_texture_non_power_of_two")) {
	    ctx->tex_target = GL_TEXTURE_2D;
	    ctx->has_npot_repeat = TRUE;
	} else if (_cairo_gl_has_extension ("GL_ARB_texture_rectangle")) {
	    ctx->tex_target = GL_TEXTURE_RECTANGLE;
	    ctx->has_npot_repeat = FALSE;
	} else
	    return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
    } else {
	ctx->tex_target = GL_TEXTURE_2D;
	if (_cairo_gl_has_extension ("GL_OES_texture_npot"))
	    ctx->has_npot_repeat = TRUE;
	else
	    ctx->has_npot_repeat = FALSE;
    }

    if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP &&
	gl_version < CAIRO_GL_VERSION_ENCODE (2, 1) &&
	! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object"))
	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);

    if (gl_flavor == CAIRO_GL_FLAVOR_ES &&
	! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888"))
	return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);

    ctx->has_map_buffer = (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
			   (gl_flavor == CAIRO_GL_FLAVOR_ES &&
			    _cairo_gl_has_extension ("GL_OES_mapbuffer")));

    ctx->has_mesa_pack_invert =
	_cairo_gl_has_extension ("GL_MESA_pack_invert");

    ctx->has_packed_depth_stencil =
	((gl_flavor == CAIRO_GL_FLAVOR_DESKTOP &&
	 _cairo_gl_has_extension ("GL_EXT_packed_depth_stencil")) ||
	(gl_flavor == CAIRO_GL_FLAVOR_ES &&
	 _cairo_gl_has_extension ("GL_OES_packed_depth_stencil")));

    ctx->num_samples = 1;

#if CAIRO_HAS_GL_SURFACE
    if (ctx->has_packed_depth_stencil &&
	_cairo_gl_has_extension ("GL_ARB_framebuffer_object")) {
	glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
    }
#endif

#if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT)
    if (ctx->has_packed_depth_stencil &&
	_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) {
	glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
    }
#endif
    ctx->supports_msaa = ctx->num_samples > 1;
    if (ctx->num_samples > MAX_MSAA_SAMPLES)
	ctx->num_samples = MAX_MSAA_SAMPLES;


    ctx->current_operator = -1;
    ctx->gl_flavor = gl_flavor;

    status = _cairo_gl_context_init_shaders (ctx);
    if (unlikely (status))
        return status;

    status = _cairo_cache_init (&ctx->gradients,
                                _cairo_gl_gradient_equal,
                                NULL,
                                (cairo_destroy_func_t) _cairo_gl_gradient_destroy,
                                CAIRO_GL_GRADIENT_CACHE_SIZE);
    if (unlikely (status))
        return status;

    ctx->vb = malloc (CAIRO_GL_VBO_SIZE);
    if (unlikely (ctx->vb == NULL)) {
	    _cairo_cache_fini (&ctx->gradients);
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES;
    _cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short));

    /* PBO for any sort of texture upload */
    dispatch->GenBuffers (1, &ctx->texture_load_pbo);

    ctx->max_framebuffer_size = 0;
    glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
    ctx->max_texture_size = 0;
    glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
    ctx->max_textures = 0;
    glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &ctx->max_textures);

    for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
	_cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]);

    return CAIRO_STATUS_SUCCESS;
}