summaryrefslogtreecommitdiff
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
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.
-rw-r--r--src/mesa/main/mtypes.h43
-rw-r--r--src/mesa/main/texenvprogram.c49
-rw-r--r--src/mesa/shader/arbprogparse.c3
-rw-r--r--src/mesa/shader/arbprogparse.h2
-rw-r--r--src/mesa/shader/nvfragprog.h9
-rw-r--r--src/mesa/shader/nvvertparse.c5
-rw-r--r--src/mesa/tnl/t_vp_build.c145
7 files changed, 156 insertions, 100 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index aadd0a7e7f..d77759df25 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -195,18 +195,18 @@ enum
#define VERT_RESULT_HPOS 0
#define VERT_RESULT_COL0 1
#define VERT_RESULT_COL1 2
-#define VERT_RESULT_BFC0 3
-#define VERT_RESULT_BFC1 4
-#define VERT_RESULT_FOGC 5
-#define VERT_RESULT_PSIZ 6
-#define VERT_RESULT_TEX0 7
-#define VERT_RESULT_TEX1 8
-#define VERT_RESULT_TEX2 9
-#define VERT_RESULT_TEX3 10
-#define VERT_RESULT_TEX4 11
-#define VERT_RESULT_TEX5 12
-#define VERT_RESULT_TEX6 13
-#define VERT_RESULT_TEX7 14
+#define VERT_RESULT_FOGC 3
+#define VERT_RESULT_TEX0 4
+#define VERT_RESULT_TEX1 5
+#define VERT_RESULT_TEX2 6
+#define VERT_RESULT_TEX3 7
+#define VERT_RESULT_TEX4 8
+#define VERT_RESULT_TEX5 9
+#define VERT_RESULT_TEX6 10
+#define VERT_RESULT_TEX7 11
+#define VERT_RESULT_PSIZ 12
+#define VERT_RESULT_BFC0 13
+#define VERT_RESULT_BFC1 14
#define VERT_RESULT_MAX 15
@@ -226,7 +226,9 @@ enum
FRAG_ATTRIB_TEX4 = 8,
FRAG_ATTRIB_TEX5 = 9,
FRAG_ATTRIB_TEX6 = 10,
- FRAG_ATTRIB_TEX7 = 11
+ FRAG_ATTRIB_TEX7 = 11,
+
+ FRAG_ATTRIB_MAX = 12
};
/*
@@ -257,6 +259,14 @@ enum
/*@}*/
+/* Fragment program results
+ */
+#define FRAG_OUTPUT_COLR 0
+#define FRAG_OUTPUT_COLH 1
+#define FRAG_OUTPUT_DEPR 2
+#define FRAG_OUTPUT_MAX 3
+
+
/**
* Indexes for all renderbuffers
*/
@@ -1791,6 +1801,7 @@ struct fragment_program
GLuint NumNativeTexIndirections;
GLenum FogOption;
struct program_parameter_list *Parameters; /**< array [NumParameters] */
+ GLboolean UsesKill;
#ifdef USE_TCC
char c_str[4096]; /* experimental... */
@@ -1835,6 +1846,9 @@ struct gl_vertex_program_state
GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_NV */
GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_NV */
struct vertex_program *Current; /**< ptr to currently bound program */
+ struct vertex_program *_Current; /**< ptr to currently bound
+ program, including internal
+ (t_vp_build.c) programs */
GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
@@ -1865,7 +1879,8 @@ struct gl_fragment_program_state
GLboolean _Enabled; /* Really enabled? */
GLboolean _Active; /* Really really enabled? */
struct fragment_program *Current; /* ptr to currently bound program */
- struct fragment_program *_Current; /* ptr to currently active program */
+ struct fragment_program *_Current; /* ptr to currently active program
+ (including internal programs) */
struct fp_machine Machine; /* machine state */
GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /* Env params */
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 18d704ce1b..43dda28f26 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -1130,32 +1130,41 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
{
struct state_key *key;
GLuint hash;
+ struct fragment_program *prev = ctx->FragmentProgram._Current;
- if (ctx->FragmentProgram._Enabled)
- return;
-
- key = make_state_key(ctx);
- hash = hash_key(key);
-
- ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
- (struct fragment_program *)
- search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key));
+ if (!ctx->FragmentProgram._Enabled) {
+ key = make_state_key(ctx);
+ hash = hash_key(key);
+
+ ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
+ (struct fragment_program *)
+ 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);
+ if (!ctx->_TexEnvProgram) {
+ if (1) _mesa_printf("Building new texenv proggy for key %x\n", hash);
- ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
- (struct fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
+ (struct fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- create_new_program(key, ctx, ctx->_TexEnvProgram);
+ create_new_program(key, ctx, ctx->_TexEnvProgram);
- cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
- } else {
- FREE(key);
- if (0) _mesa_printf("Found existing texenv program for key %x\n", hash);
+ cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
+ } else {
+ FREE(key);
+ if (1) _mesa_printf("Found existing texenv program for key %x\n", hash);
+ }
+ }
+ else {
+ ctx->FragmentProgram._Current = ctx->FragmentProgram.Current;
}
-
+
+ /* Tell the driver about the change. Could define a new target for
+ * this?
+ */
+ if (ctx->FragmentProgram._Current != prev)
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct program *)
+ ctx->FragmentProgram._Current);
}
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index e8fe869d0b..19c38b6272 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -3013,6 +3013,7 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
break;
case OP_TEX_KIL:
+ Program->UsesKill = 1;
if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
return 1;
fp->Opcode = FP_OPCODE_KIL;
@@ -4014,6 +4015,8 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
program->NumTexInstructions =
program->NumTexIndirections = 0;
+ program->UsesKill = 0;
+
program->FPInstructions = NULL;
program->VPInstructions = NULL;
diff --git a/src/mesa/shader/arbprogparse.h b/src/mesa/shader/arbprogparse.h
index ececfafa8f..947c22e767 100644
--- a/src/mesa/shader/arbprogparse.h
+++ b/src/mesa/shader/arbprogparse.h
@@ -65,6 +65,8 @@ struct arb_program
GLuint NumAluInstructions;
GLuint NumTexInstructions;
GLuint NumTexIndirections;
+
+ GLboolean UsesKill;
};
diff --git a/src/mesa/shader/nvfragprog.h b/src/mesa/shader/nvfragprog.h
index 99ec20bb82..bd9c8bb06c 100644
--- a/src/mesa/shader/nvfragprog.h
+++ b/src/mesa/shader/nvfragprog.h
@@ -37,15 +37,6 @@
#include "mtypes.h"
-/**
- * Fragment program output registers.
- * Note: when we fully suppport GL_ARB_draw_buffers we'll have more than
- * one output color.
- */
-#define FRAG_OUTPUT_COLR 0 /* fragment color */
-#define FRAG_OUTPUT_COLH 1 /* fragment color, half precision (NV) */
-#define FRAG_OUTPUT_DEPR 2 /* depth/Z */
-
/* condition codes */
#define COND_GT 1 /* greater than zero */
diff --git a/src/mesa/shader/nvvertparse.c b/src/mesa/shader/nvvertparse.c
index c48a4cb358..24882a2897 100644
--- a/src/mesa/shader/nvvertparse.c
+++ b/src/mesa/shader/nvvertparse.c
@@ -288,8 +288,9 @@ static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
};
static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
- "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
- "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
+ "HPOS", "COL0", "COL1", "FOGC",
+ "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7",
+ "PSIZ", "BFC0", "BFC1", NULL
};
/* NOTE: the order here must match opcodes in nvvertprog.h */
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);
}