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; }
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; }
/** * _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; }
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; }