diff options
Diffstat (limited to 'src/mesa/main/texenvprogram.c')
-rw-r--r-- | src/mesa/main/texenvprogram.c | 212 |
1 files changed, 59 insertions, 153 deletions
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 512d52704d8..713ff3d2564 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -30,9 +30,11 @@ #include "enums.h" #include "shader/program.h" #include "shader/prog_parameter.h" +#include "shader/prog_cache.h" #include "shader/prog_instruction.h" #include "shader/prog_print.h" #include "shader/prog_statevars.h" +#include "shader/programopt.h" #include "texenvprogram.h" @@ -411,9 +413,9 @@ static struct ureg get_tex_temp( struct texenv_fragment_program *p ) } -static void release_temps( struct texenv_fragment_program *p ) +static void release_temps(GLcontext *ctx, struct texenv_fragment_program *p ) { - GLuint max_temp = p->ctx->Const.FragmentProgram.MaxTemps; + GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps; /* KW: To support tex_env_crossbar, don't release the registers in * temps_output. @@ -593,7 +595,7 @@ static struct ureg register_const4f( struct texenv_fragment_program *p, idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4, &swizzle ); ASSERT(swizzle == SWIZZLE_NOOP); - return make_ureg(PROGRAM_STATE_VAR, idx); + return make_ureg(PROGRAM_CONSTANT, idx); } #define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0) @@ -915,14 +917,14 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) */ if (alpha_shift || rgb_shift) { if (rgb_shift == alpha_shift) { - shift = register_scalar_const(p, 1<<rgb_shift); + shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift)); } else { shift = register_const4f(p, - 1<<rgb_shift, - 1<<rgb_shift, - 1<<rgb_shift, - 1<<alpha_shift); + (GLfloat)(1<<rgb_shift), + (GLfloat)(1<<rgb_shift), + (GLfloat)(1<<rgb_shift), + (GLfloat)(1<<alpha_shift)); } return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW, saturate, out, shift, undef ); @@ -951,9 +953,17 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) p->src_texture[unit] = emit_texld( p, OPCODE_TXP, tmp, WRITEMASK_XYZW, unit, dim, texcoord ); + if (p->state->unit[unit].shadow) p->program->Base.ShadowSamplers |= 1 << unit; - } else + + p->program->Base.SamplersUsed |= (1 << unit); + /* This identity mapping should already be in place + * (see _mesa_init_program_struct()) but let's be safe. + */ + p->program->Base.SamplerUnits[unit] = unit; + } + else p->src_texture[unit] = get_zero(p); } } @@ -1051,7 +1061,7 @@ create_new_program(GLcontext *ctx, struct state_key *key, p.one = undef; p.last_tex_stage = 0; - release_temps(&p); + release_temps(ctx, &p); if (key->enabled_units) { /* First pass - to support texture_env_crossbar, first identify @@ -1069,7 +1079,7 @@ create_new_program(GLcontext *ctx, struct state_key *key, for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) if (key->enabled_units & (1<<unit)) { p.src_previous = emit_texenv( &p, unit ); - release_temps(&p); /* release all temps */ + release_temps(ctx, &p); /* release all temps */ } } @@ -1099,6 +1109,7 @@ create_new_program(GLcontext *ctx, struct state_key *key, * a reduced value and not what is expected in FogOption */ p.program->FogOption = ctx->Fog.Mode; + p.program->Base.InputsRead |= FRAG_BIT_FOGC; /* XXX new */ } else p.program->FogOption = GL_NONE; @@ -1114,15 +1125,21 @@ create_new_program(GLcontext *ctx, struct state_key *key, ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS); /* Allocate final instruction array */ - program->Base.Instructions - = _mesa_alloc_instructions(program->Base.NumInstructions); - if (!program->Base.Instructions) { + p.program->Base.Instructions + = _mesa_alloc_instructions(p.program->Base.NumInstructions); + if (!p.program->Base.Instructions) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating tex env program"); return; } - _mesa_copy_instructions(program->Base.Instructions, instBuffer, - program->Base.NumInstructions); + _mesa_copy_instructions(p.program->Base.Instructions, instBuffer, + p.program->Base.NumInstructions); + + if (p.program->FogOption) { + _mesa_append_fog_code(ctx, p.program); + p.program->FogOption = GL_NONE; + } + /* Notify driver the fragment program has (actually) changed. */ @@ -1138,106 +1155,35 @@ create_new_program(GLcontext *ctx, struct state_key *key, } -static struct gl_fragment_program * -search_cache(const struct texenvprog_cache *cache, - GLuint hash, - const void *key, - GLuint keysize) -{ - struct texenvprog_cache_item *c; - - 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 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 clear_cache(GLcontext *ctx, struct texenvprog_cache *cache) -{ - struct texenvprog_cache_item *c, *next; - GLuint i; - - for (i = 0; i < cache->size; i++) { - for (c = cache->items[i]; c; c = next) { - next = c->next; - _mesa_free(c->key); - _mesa_reference_fragprog(ctx, &c->data, NULL); - _mesa_free(c); - } - cache->items[i] = NULL; - } - - - cache->n_items = 0; -} - - -static void cache_item( GLcontext *ctx, - struct texenvprog_cache *cache, - GLuint hash, - const struct state_key *key, - struct gl_fragment_program *prog) +/** + * Return a fragment program which implements the current + * fixed-function texture, fog and color-sum operations. + */ +struct gl_fragment_program * +_mesa_get_fixed_func_fragment_program(GLcontext *ctx) { - struct texenvprog_cache_item *c = CALLOC_STRUCT(texenvprog_cache_item); - c->hash = hash; + struct gl_fragment_program *prog; + struct state_key key; + + make_state_key(ctx, &key); + + prog = (struct gl_fragment_program *) + _mesa_search_program_cache(ctx->FragmentProgram.Cache, + &key, sizeof(key)); - c->key = _mesa_malloc(sizeof(*key)); - memcpy(c->key, key, sizeof(*key)); + if (!prog) { + prog = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - c->data = prog; + create_new_program(ctx, &key, prog); - if (cache->n_items > cache->size * 1.5) { - if (cache->size < 1000) - rehash(cache); - else - clear_cache(ctx, cache); + _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache, + &key, sizeof(key), &prog->Base); } - cache->n_items++; - c->next = cache->items[hash % cache->size]; - cache->items[hash % cache->size] = c; + return prog; } -static GLuint hash_key( const struct state_key *key ) -{ - GLuint *ikey = (GLuint *)key; - GLuint hash = 0, i; - - /* Make a slightly better attempt at a hash function: - */ - for (i = 0; i < sizeof(*key)/sizeof(*ikey); i++) - { - hash += ikey[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - - return hash; -} /** @@ -1248,44 +1194,22 @@ static GLuint hash_key( const struct state_key *key ) void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) { - struct state_key key; - GLuint hash; const struct gl_fragment_program *prev = ctx->FragmentProgram._Current; ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram); /* If a conventional fragment program/shader isn't in effect... */ if (!ctx->FragmentProgram._Enabled && - (!ctx->Shader.CurrentProgram || !ctx->Shader.CurrentProgram->FragmentProgram)) { + (!ctx->Shader.CurrentProgram || + !ctx->Shader.CurrentProgram->FragmentProgram) ) + { struct gl_fragment_program *newProg; - make_state_key(ctx, &key); - hash = hash_key(&key); - - newProg = search_cache(&ctx->Texture.env_fp_cache, hash, &key, sizeof(key)); - - if (!newProg) { - /* create new tex env program */ - - if (0) - _mesa_printf("Building new texenv proggy for key %x\n", hash); - - newProg = (struct gl_fragment_program *) - ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - - create_new_program(ctx, &key, newProg); - - /* Our ownership of newProg is transferred to the cache */ - cache_item(ctx, &ctx->Texture.env_fp_cache, hash, &key, newProg); - } + newProg = _mesa_get_fixed_func_fragment_program(ctx); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg); } - else { - /* _Current pointer has been updated in update_program */ - /* ctx->FragmentProgram._Current = ctx->FragmentProgram.Current; */ - } /* Tell the driver about the change. Could define a new target for * this? @@ -1295,21 +1219,3 @@ _mesa_UpdateTexEnvProgram( GLcontext *ctx ) (struct gl_program *) ctx->FragmentProgram._Current); } } - - -void _mesa_TexEnvProgramCacheInit( GLcontext *ctx ) -{ - ctx->Texture.env_fp_cache.ctx = 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 ) -{ - clear_cache(ctx, &ctx->Texture.env_fp_cache); - _mesa_free(ctx->Texture.env_fp_cache.items); -} |