diff options
Diffstat (limited to 'src/mesa/main/texenvprogram.c')
-rw-r--r-- | src/mesa/main/texenvprogram.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 520ea02b61..63c93c96fc 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -1023,6 +1023,10 @@ create_new_program(struct state_key *key, GLcontext *ctx, p.src_texture[unit] = undef; p.src_previous = undef; + p.half = undef; + p.zero = undef; + p.one = undef; + p.last_tex_stage = 0; release_temps(&p); @@ -1106,27 +1110,53 @@ static void *search_cache( struct texenvprog_cache *cache, const void *key, GLuint keysize) { - struct texenvprog_cache *c; + struct texenvprog_cache_item *c; - for (c = cache; c; c = c->next) { - if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0) + for (c = cache->items[hash % cache->size]; c; c = c->next) { + if (c->hash == hash && memcmp(c->key, key, keysize) == 0) return c->data; } return NULL; } -static void cache_item( struct texenvprog_cache **cache, +static void rehash( struct texenvprog_cache *cache ) +{ + struct texenvprog_cache_item **items; + struct texenvprog_cache_item *c, *next; + GLuint size, i; + + size = cache->size * 3; + items = (struct texenvprog_cache_item**) _mesa_malloc(size * sizeof(*items)); + _mesa_memset(items, 0, size * sizeof(*items)); + + for (i = 0; i < cache->size; i++) + for (c = cache->items[i]; c; c = next) { + next = c->next; + c->next = items[c->hash % size]; + items[c->hash % size] = c; + } + + _mesa_free(cache->items); + cache->items = items; + cache->size = size; +} + +static void cache_item( struct texenvprog_cache *cache, GLuint hash, void *key, void *data ) { - struct texenvprog_cache *c = CALLOC_STRUCT(texenvprog_cache); + struct texenvprog_cache_item *c = MALLOC(sizeof(*c)); c->hash = hash; c->key = key; c->data = data; - c->next = *cache; - *cache = c; + + if (++cache->n_items > cache->size * 1.5) + rehash(cache); + + c->next = cache->items[hash % cache->size]; + cache->items[hash % cache->size] = c; } static GLuint hash_key( struct state_key *key ) @@ -1154,7 +1184,7 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) ctx->FragmentProgram._Current = ctx->_TexEnvProgram = (struct fragment_program *) - search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key)); + search_cache(&ctx->Texture.env_fp_cache, hash, key, sizeof(*key)); if (!ctx->_TexEnvProgram) { if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash); @@ -1184,14 +1214,29 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) } } + +void _mesa_TexEnvProgramCacheInit( GLcontext *ctx ) +{ + ctx->Texture.env_fp_cache.size = 17; + ctx->Texture.env_fp_cache.n_items = 0; + ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **) + _mesa_calloc(ctx->Texture.env_fp_cache.size * + sizeof(struct texenvprog_cache_item)); +} + + void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx ) { - struct texenvprog_cache *a, *tmp; + struct texenvprog_cache_item *c, *next; + GLuint i; - for (a = ctx->Texture.env_fp_cache; a; a = tmp) { - tmp = a->next; - _mesa_free(a->key); - ctx->Driver.DeleteProgram(ctx, (struct program *) a->data); - _mesa_free(a); - } + for (i = 0; i < ctx->Texture.env_fp_cache.size; i++) + for (c = ctx->Texture.env_fp_cache.items[i]; c; c = next) { + next = c->next; + _mesa_free(c->key); + _mesa_free(c->data); + _mesa_free(c); + } + + _mesa_free(ctx->Texture.env_fp_cache.items); } |