summaryrefslogtreecommitdiff
path: root/src/mesa/tnl/t_vp_build.c
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2005-11-01 17:25:49 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2005-11-01 17:25:49 +0000
commitc3626a91cee5034528f3f92c802a8e5947ea5f92 (patch)
treefd16d99ef237e31067e9f7a74bc2cee471bcc7e9 /src/mesa/tnl/t_vp_build.c
parent6aa6d440d9d312cb984020e746aa80c3dbf6ea2c (diff)
Several fp and vp tweaks:
- Renumber VERT_RESULT_* values so that they match the numbers of the corresponding FRAG_ATTRIB_ values. - Add ctx->VertexProgram._Current and FragmentProgram._Current values which point to either the current client-supplied program if enabled, or otherwise to the current mesa-internal program. Thus this program is always the correct one for the current state, providing that the mesa flags to turn on automatic generation are enabled. - Add callbacks to ctx->Driver.BindProgram() in texenvprogram.c and t_vp_build.c so that the driver knows when the generated program changes. This is cleaner than trying to code all the possible _NEW_* flags into the driver, and more precise as well. - Add a UsesKill flag to identify fragment programs with that instruction, as these can require special treatment. - Move the FRAG_OUTPUT values to mtypes.h, near to similar defn's.
Diffstat (limited to 'src/mesa/tnl/t_vp_build.c')
-rw-r--r--src/mesa/tnl/t_vp_build.c145
1 files changed, 90 insertions, 55 deletions
diff --git a/src/mesa/tnl/t_vp_build.c b/src/mesa/tnl/t_vp_build.c
index 02e5a2aa1b..0fc4f6c6b5 100644
--- a/src/mesa/tnl/t_vp_build.c
+++ b/src/mesa/tnl/t_vp_build.c
@@ -53,10 +53,10 @@ struct state_key {
unsigned fog_source_is_depth:1;
unsigned tnl_do_vertex_fog:1;
unsigned separate_specular:1;
- unsigned fog_enabled:1;
unsigned fog_mode:2;
unsigned point_attenuated:1;
unsigned texture_enabled_global:1;
+ unsigned fragprog_inputs_read:12;
struct {
unsigned light_enabled:1;
@@ -75,10 +75,10 @@ struct state_key {
-#define FOG_LINEAR 0
-#define FOG_EXP 1
-#define FOG_EXP2 2
-#define FOG_UNKNOWN 3
+#define FOG_NONE 0
+#define FOG_LINEAR 1
+#define FOG_EXP 2
+#define FOG_EXP2 3
static GLuint translate_fog_mode( GLenum mode )
{
@@ -86,7 +86,7 @@ static GLuint translate_fog_mode( GLenum mode )
case GL_LINEAR: return FOG_LINEAR;
case GL_EXP: return FOG_EXP;
case GL_EXP2: return FOG_EXP2;
- default: return FOG_UNKNOWN;
+ default: return FOG_NONE;
}
}
@@ -116,9 +116,16 @@ static struct state_key *make_state_key( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
+ struct fragment_program *fp = ctx->FragmentProgram._Current;
struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i;
+ /* This now relies on texenvprogram.c being active:
+ */
+ assert(fp);
+
+ key->fragprog_inputs_read = fp->InputsRead;
+
key->separate_specular = (ctx->Light.Model.ColorControl ==
GL_SEPARATE_SPECULAR_COLOR);
@@ -166,18 +173,13 @@ static struct state_key *make_state_key( GLcontext *ctx )
if (ctx->Transform.RescaleNormals)
key->rescale_normals = 1;
- if (ctx->Fog.Enabled)
- key->fog_enabled = 1;
-
- if (key->fog_enabled) {
- if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
- key->fog_source_is_depth = 1;
-
- if (tnl->_DoVertexFog)
- key->tnl_do_vertex_fog = 1;
-
- key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
- }
+ key->fog_mode = translate_fog_mode(fp->FogOption);
+
+ if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
+ key->fog_source_is_depth = 1;
+
+ if (tnl->_DoVertexFog)
+ key->tnl_do_vertex_fog = 1;
if (ctx->Point._Attenuated)
key->point_attenuated = 1;
@@ -332,6 +334,9 @@ static struct ureg get_temp( struct tnl_program *p )
_mesa_exit(1);
}
+ if (bit > p->program->Base.NumTemporaries)
+ p->program->Base.NumTemporaries = bit;
+
p->temp_in_use |= 1<<(bit-1);
return make_ureg(PROGRAM_TEMPORARY, bit-1);
}
@@ -710,6 +715,8 @@ static GLuint material_attrib( GLuint side, GLuint property )
side);
}
+/* Get a bitmask of which material values vary on a per-vertex basis.
+ */
static void set_material_flags( struct tnl_program *p )
{
p->color_materials = 0;
@@ -1194,9 +1201,14 @@ static void build_texture_transform( struct tnl_program *p )
GLuint i, j;
for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
- if (p->state->unit[i].texgen_enabled || texmat_enabled) {
+ if (!(p->state->fragprog_inputs_read & (FRAG_BIT_TEX0<<i)))
+ continue;
+
+ if (p->state->unit[i].texgen_enabled ||
+ p->state->unit[i].texmat_enabled) {
+
+ GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
struct ureg out_texgen = undef;
@@ -1293,10 +1305,7 @@ static void build_texture_transform( struct tnl_program *p )
release_temps(p);
}
- else if (p->state->unit[i].texunit_really_enabled) {
- /* KW: _ReallyEnabled isn't sufficient? Need to know whether
- * this texture unit is referenced by the fragment shader.
- */
+ else {
emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
}
}
@@ -1338,15 +1347,23 @@ static void build_tnl_program( struct tnl_program *p )
/* Lighting calculations:
*/
- if (p->state->light_global_enabled)
- build_lighting(p);
- else
- emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
+ if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
+ if (p->state->light_global_enabled)
+ build_lighting(p);
+ else {
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
+ emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
+
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
+ emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL1);
+ }
+ }
- if (p->state->fog_enabled)
+ if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
+ p->state->fog_mode != FOG_NONE)
build_fog(p);
- if (p->state->texture_enabled_global)
+ if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
build_texture_transform(p);
if (p->state->point_attenuated)
@@ -1470,42 +1487,60 @@ void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct state_key *key;
GLuint hash;
+ struct vertex_program *prev = ctx->VertexProgram._Current;
- if (ctx->VertexProgram._Enabled)
- return;
-
- /* Grab all the relevent state and put it in a single structure:
- */
- key = make_state_key(ctx);
- hash = hash_key(key);
+ if (ctx->VertexProgram._Enabled) {
+ /* Grab all the relevent state and put it in a single structure:
+ */
+ key = make_state_key(ctx);
+ hash = hash_key(key);
+
+ if (tnl->vp_cache == NULL) {
+ tnl->vp_cache = MALLOC(sizeof(*tnl->vp_cache));
+ tnl->vp_cache->size = 5;
+ tnl->vp_cache->n_items = 0;
+ tnl->vp_cache->items = MALLOC(tnl->vp_cache->size *
+ sizeof(*tnl->vp_cache->items));
+ _mesa_memset(tnl->vp_cache->items, 0, tnl->vp_cache->size *
+ sizeof(*tnl->vp_cache->items));
+ }
- /* Look for an already-prepared program for this state:
- */
- ctx->_TnlProgram = (struct vertex_program *)
- search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
+ /* Look for an already-prepared program for this state:
+ */
+ ctx->_TnlProgram = (struct vertex_program *)
+ search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
- /* OK, we'll have to build a new one:
- */
- if (!ctx->_TnlProgram) {
- if (0)
- _mesa_printf("Build new TNL program\n");
+ /* OK, we'll have to build a new one:
+ */
+ if (!ctx->_TnlProgram) {
+ if (0)
+ _mesa_printf("Build new TNL program\n");
+
+ ctx->_TnlProgram = (struct vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
- ctx->_TnlProgram = (struct vertex_program *)
- ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ create_new_program( key, ctx->_TnlProgram,
+ ctx->Const.VertexProgram.MaxTemps );
- create_new_program( key, ctx->_TnlProgram,
- ctx->Const.VertexProgram.MaxTemps );
- cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram );
+ cache_item(tnl->vp_cache, hash, key, ctx->_TnlProgram );
+ }
+ else {
+ FREE(key);
+ if (0)
+ _mesa_printf("Found existing TNL program for key %x\n", hash);
+ }
}
else {
- FREE(key);
- if (0)
- _mesa_printf("Found existing TNL program for key %x\n", hash);
+ ctx->VertexProgram._Current = ctx->VertexProgram.Current;
}
- /* Need a BindProgram callback for the driver?
+ /* Tell the driver about the change. Could define a new target for
+ * this?
*/
+ if (ctx->VertexProgram._Current != prev)
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, (struct program *)
+ ctx->VertexProgram._Current);
}