[patch] gl: cache uniform location
"Henry (Yu) Song - SISA" <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <3955FA337689574EB32F94B12A7E6E9E246B0CF4@sisaex01sj> |
GetUniformLocation is expensive call, especially on embedded device, we can cache them once obtained. From c856118e637412a8c5cd7b68cc569f7e1bf4f44c Mon Sep 17 00:00:00 2001 From: Henry Song <[email protected]> Date: Fri, 6 Jan 2012 16:46:25 -0800 Subject: [PATCH] gl/msaa: Cache shader uniform locations Instead of continuously fetching the uniform locations from compiled shaders, cache them. --- src/cairo-gl-private.h | 1 + src/cairo-gl-shaders.c | 122 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index 48087ec..057b9f3 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -196,6 +196,7 @@ typedef enum cairo_gl_tex { typedef struct cairo_gl_shader { GLuint fragment_shader; GLuint program; + cairo_hash_table_t *uniform_cache; } cairo_gl_shader_t; typedef enum cairo_gl_shader_in { diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c index 41672d6..c07150e 100644 --- a/src/cairo-gl-shaders.c +++ b/src/cairo-gl-shaders.c @@ -52,6 +52,75 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, cairo_bool_t use_coverage, const char *fragment_text); +typedef struct _cairo_gl_uniform_entry { + cairo_hash_entry_t base; + char *name; + GLint location; +} cairo_gl_uniform_entry_t; + +static void +_cairo_gl_uniform_entry_init (cairo_gl_uniform_entry_t *key, + const char *name) +{ + unsigned long sum = 0; + unsigned int i; + + for (i = 0; i < strlen(name); i++) + sum += name[i]; + key->base.hash = sum; + key->name = strdup(name); + key->location = -1; +} + +static void +_cairo_gl_uniform_entry_fini (cairo_gl_uniform_entry_t *entry) +{ + free (entry->name); + entry->location = -1; +} + +static cairo_bool_t +_cairo_gl_uniform_equal (const void *key_a, + const void *key_b) +{ + const cairo_gl_uniform_entry_t *a = key_a; + const cairo_gl_uniform_entry_t *b = key_b; + + return strcmp (a->name, b->name) == 0; +} + +static void +get_uniform_location (cairo_gl_context_t *ctx, + cairo_gl_shader_t *shader, + const char *name, + GLint *location) +{ + cairo_gl_uniform_entry_t key, *uniform_entry; + + _cairo_gl_uniform_entry_init (&key, name); + + uniform_entry = _cairo_hash_table_lookup (shader->uniform_cache, &key.base); + if (uniform_entry) { + *location = uniform_entry->location; + _cairo_gl_uniform_entry_fini (&key); + return; + } + + *location = ctx->dispatch.GetUniformLocation (shader->program, name); + + uniform_entry = _cairo_malloc (sizeof (cairo_gl_uniform_entry_t)); + if (unlikely (uniform_entry == NULL)) + return; + + _cairo_gl_uniform_entry_init (uniform_entry, name); + uniform_entry->location = *location; + if (_cairo_hash_table_insert (shader->uniform_cache, + &uniform_entry->base)) { + _cairo_gl_uniform_entry_fini (uniform_entry); + free (uniform_entry); + } +} + typedef struct _cairo_shader_cache_entry { cairo_cache_entry_t base; @@ -136,6 +205,7 @@ _cairo_gl_shader_init (cairo_gl_shader_t *shader) { shader->fragment_shader = 0; shader->program = 0; + shader->uniform_cache = _cairo_hash_table_create (_cairo_gl_uniform_equal); } cairo_status_t @@ -199,6 +269,19 @@ _cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx) } _cairo_cache_fini (&ctx->shaders); + _cairo_gl_shader_fini (ctx, &ctx->fill_rectangles_shader); +} + +static void +_cairo_gl_shader_uniform_cache_destroy_entry (void *entry, + void *closure) +{ + cairo_gl_uniform_entry_t *uniform_entry = entry; + + _cairo_hash_table_remove ((cairo_hash_table_t *) closure, + &uniform_entry->base); + _cairo_gl_uniform_entry_fini (uniform_entry); + free (uniform_entry); } void @@ -210,6 +293,13 @@ _cairo_gl_shader_fini (cairo_gl_context_t *ctx, if (shader->program) ctx->dispatch.DeleteProgram (shader->program); + + if (shader->uniform_cache) { + _cairo_hash_table_foreach (shader->uniform_cache, + _cairo_gl_shader_uniform_cache_destroy_entry, + shader->uniform_cache); + _cairo_hash_table_destroy (shader->uniform_cache); + } } static const char *operand_names[] = { "source", "mask", "dest" }; @@ -853,12 +943,12 @@ _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx, glGetIntegerv (GL_CURRENT_PROGRAM, &saved_program); dispatch->UseProgram (shader->program); - location = dispatch->GetUniformLocation (shader->program, "source_sampler"); -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo