#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
FRAG_ATTRIB_TEX4 = 8,
FRAG_ATTRIB_TEX5 = 9,
FRAG_ATTRIB_TEX6 = 10,
- FRAG_ATTRIB_TEX7 = 11
+ FRAG_ATTRIB_TEX7 = 11,
+
+ FRAG_ATTRIB_MAX = 12
};
/*
/*@}*/
+/* 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
*/
GLuint NumNativeTexIndirections;
GLenum FogOption;
struct program_parameter_list *Parameters; /**< array [NumParameters] */
+ GLboolean UsesKill;
#ifdef USE_TCC
char c_str[4096]; /* experimental... */
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];
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 */
{
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 )
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;
-#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 )
{
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;
}
}
{
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);
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;
_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);
}
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;
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;
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);
}
}
/* 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)
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);
}